Browser Support
ResponsiveVoice works across all modern browsers with automatic fallback.
Chrome66+
Firefox57+
Safari12+
Edge17+
Opera53+
iOS Safari12+
Chrome Android66+
Android WebView66+
Chrome66+
Firefox57+
Safari14+
Edge16+
Opera53+
iOS Safari14+
Chrome Android66+
Android WebView66+
Data generated from MDN Browser Compat Data
How Fallback Works
Section titled “How Fallback Works”Native vs Fallback
Section titled “Native vs Fallback”| Feature | Native (Web Speech API) | Fallback (API) |
|---|---|---|
| Latency | Instant | ~100–300 ms* |
| Offline | ||
| Voice quality | Varies by OS | Consistent |
| Boundary events | ||
| SSML support |
Platform-Specific Notes
Section titled “Platform-Specific Notes”Chrome / Chromium
Section titled “Chrome / Chromium”- 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
Safari / iOS
Section titled “Safari / iOS”- Apple voices with "(Enhanced)" variants
- Good offline voice quality
- iOS requires user gesture to begin playback
- Some voices locked to specific iOS versions
Firefox
Section titled “Firefox”- 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+
Mobile Considerations
Section titled “Mobile Considerations”// Optional: trigger speech from your own button instead of the built-in promptdocument.getElementById('speakBtn').addEventListener('click', () => { rv.speak('Hello from iOS', 'UK English Female');});Android
Section titled “Android”- 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
Android WebView
Section titled “Android WebView”- 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)
Node.js Support
Section titled “Node.js Support”ResponsiveVoice works in Node.js environments using the @responsivevoice/api-client package. The minimum Node.js version varies by package:
| Package | Minimum Node.js |
|---|---|
@responsivevoice/types, text | 14+ |
@responsivevoice/api-client | 16+ |
@responsivevoice/core and @responsivevoice/features target the browser — Node is only their build environment (bundle with Vite/webpack), not a runtime.
Node.js 18+ (recommended)
Section titled “Node.js 18+ (recommended)”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',});Node.js 16–17
Section titled “Node.js 16–17”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,});WebSocket streaming on Node.js < 22
Section titled “WebSocket streaming on Node.js < 22”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,});Feature Detection
Section titled “Feature Detection”Check platform capabilities:
// Check if the Web Speech API is availableconst hasNativeTTS = 'speechSynthesis' in window;
// Whether ResponsiveVoice can use native voices on this platformconst nativeSupported = rv.isNativeSupported();
// Check if a voice name is in the resolvable catalogconst voices = rv.getVoices();const hasUKFemale = voices.some((v) => v.name === 'UK English Female');
// Native <-> fallback switches are reported via the OnServiceSwitched eventrv.addEventListener('OnServiceSwitched', (payload) => { console.log(`Switched from ${payload.from} to ${payload.to}`);});Forcing Fallback
Section titled “Forcing Fallback”Force server (fallback) audio even when native voices exist — set it at init or toggle at runtime:
// At initconst rv = await getResponsiveVoice({ apiKey: 'YOUR_API_KEY', forceFallback: true,});
// Or at runtimerv.setForceFallback(true);User Interaction Requirements
Section titled “User Interaction Requirements”Modern browsers require user interaction before playing audio:
// ❌ This may be blockedwindow.onload = () => { rv.speak('Hello'); // Blocked by autoplay policy};
// ✅ This worksbutton.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 },);Testing Across Platforms
Section titled “Testing Across Platforms”// Log platform info for debuggingconsole.log({ browser: navigator.userAgent, hasNativeTTS: 'speechSynthesis' in window, nativeVoices: window.speechSynthesis?.getVoices().length ?? 0, rvVoices: rv.getVoices().length,});