Skip to content

Browser Support

ResponsiveVoice works across all modern browsers with automatic fallback.

@responsivevoice/api-client
  • ChromeChrome66+
  • FirefoxFirefox57+
  • SafariSafari12+
  • EdgeEdge17+
  • OperaOpera53+
  • iOS SafariiOS Safari12+
  • Chrome AndroidChrome Android66+
  • Android WebViewAndroid WebView66+
@responsivevoice/core
  • ChromeChrome66+
  • FirefoxFirefox57+
  • SafariSafari14+
  • EdgeEdge16+
  • OperaOpera53+
  • iOS SafariiOS Safari14+
  • Chrome AndroidChrome Android66+
  • Android WebViewAndroid WebView66+

Data generated from MDN Browser Compat Data

Diagram
FeatureNative (Web Speech API)Fallback (API)
LatencyInstant~100–300 ms*
Offline
Voice qualityVaries by OSConsistent
Boundary events
SSML support
  • Best voice selection with Google TTS voices
  • Voices like "Google UK English Female" available
  • Full boundary event support
  • May require user interaction to start audio
  • Apple voices with "(Enhanced)" variants
  • Good offline voice quality
  • iOS requires user gesture to begin playback
  • Some voices locked to specific iOS versions
  • Limited native voice support
  • Falls back to API more frequently
  • No boundary events when using fallback
  • Full functionality with API fallback
  • Windows voices available (David, Zira, etc.)
  • Good Web Speech API support
  • Microsoft neural voices on Windows 10+
// Optional: trigger speech from your own button instead of the built-in prompt
document.getElementById('speakBtn').addEventListener('click', () => {
rv.speak('Hello from iOS', 'UK English Female');
});
  • Android Chrome requires a user gesture before audio — handled automatically by the same built-in permission prompt as iOS
  • Voice availability varies by device manufacturer
  • Google TTS voices commonly available
  • May need to download voices in system settings
  • Minimum supported: Android WebView 66+
  • Native TTS unavailable - always uses API fallback
  • Audio playback works normally via Audio element
  • Common in hybrid apps (Cordova, Capacitor, React Native WebView)

ResponsiveVoice works in Node.js environments using the @responsivevoice/api-client package. The minimum Node.js version varies by package:

PackageMinimum Node.js
@responsivevoice/types, text14+
@responsivevoice/api-client16+

@responsivevoice/core and @responsivevoice/features target the browser — Node is only their build environment (bundle with Vite/webpack), not a runtime.

All features work out of the box with native fetch, Blob, and AbortController:

import { ResponsiveVoiceAPIClient } from '@responsivevoice/api-client';
const client = new ResponsiveVoiceAPIClient({
apiKey: process.env.RESPONSIVEVOICE_API_KEY,
apiSecret: process.env.RESPONSIVEVOICE_API_SECRET,
});
const audio = await client.synthesize({
text: 'Hello from Node.js',
voice: 'UK English Female',
});

Native fetch is not available. Pass a fetch implementation via the fetch config option:

import fetch from 'node-fetch';
import { ResponsiveVoiceAPIClient } from '@responsivevoice/api-client';
const client = new ResponsiveVoiceAPIClient({
apiKey: process.env.RESPONSIVEVOICE_API_KEY,
apiSecret: process.env.RESPONSIVEVOICE_API_SECRET,
fetch,
});

The global WebSocket was added in Node.js 22. On older versions, pass a WebSocket implementation:

import WebSocket from 'ws';
import { WebSocketConnection } from '@responsivevoice/api-client';
const ws = new WebSocketConnection({
baseUrl: 'https://texttospeech.responsivevoice.org',
apiKey: process.env.RESPONSIVEVOICE_API_KEY,
WebSocket,
});

Check platform capabilities:

// Check if the Web Speech API is available
const hasNativeTTS = 'speechSynthesis' in window;
// Whether ResponsiveVoice can use native voices on this platform
const nativeSupported = rv.isNativeSupported();
// Check if a voice name is in the resolvable catalog
const voices = rv.getVoices();
const hasUKFemale = voices.some((v) => v.name === 'UK English Female');
// Native <-> fallback switches are reported via the OnServiceSwitched event
rv.addEventListener('OnServiceSwitched', (payload) => {
console.log(`Switched from ${payload.from} to ${payload.to}`);
});

Force server (fallback) audio even when native voices exist — set it at init or toggle at runtime:

// At init
const rv = await getResponsiveVoice({
apiKey: 'YOUR_API_KEY',
forceFallback: true,
});
// Or at runtime
rv.setForceFallback(true);

Modern browsers require user interaction before playing audio:

// ❌ This may be blocked
window.onload = () => {
rv.speak('Hello'); // Blocked by autoplay policy
};
// ✅ This works
button.onclick = () => {
rv.speak('Hello'); // Allowed - user initiated
};

Workaround: Initialize on First Interaction

Section titled “Workaround: Initialize on First Interaction”

On mobile, ResponsiveVoice's built-in permission prompt already unlocks audio on the first gesture — use this manual pattern only if you've disabled the prompt and want to unlock from your own handler:

let initialized = false;
document.addEventListener(
'click',
() => {
if (!initialized) {
rv.speak('', 'UK English Female'); // Silent init
initialized = true;
}
},
{ once: true },
);
// Log platform info for debugging
console.log({
browser: navigator.userAgent,
hasNativeTTS: 'speechSynthesis' in window,
nativeVoices: window.speechSynthesis?.getVoices().length ?? 0,
rvVoices: rv.getVoices().length,
});