> ## Documentation Index
> Fetch the complete documentation index at: https://docs.responsivevoice.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Migration Guide

This guide helps you migrate from the legacy `responsivevoice.js` script to the modern `@responsivevoice/core` package.

## What's New

The new package provides:

- **TypeScript support** with full type definitions
- **Modern build formats** (ESM, CJS, browser bundle)
- **Tree-shakeable exports**
- **Better error handling**
- **API-first architecture** (voice data fetched at runtime)
- **Full backward compatibility** with the legacy API
- **Access to Premium neural voices** from several specialized TTS Providers (via bring-your-own-keys)
- **New UI features** — see the new [ResponsiveVoice WebPlayer](/guides/web-player/) in action in the [live example](https://examples.responsivevoice.org/browser/web-player/) and [how to customize it](https://examples.responsivevoice.org/browser/web-player-customization/).

> [!TIP]
> The migration is designed to be a drop-in replacement. Most code will work without changes.

## Installation Changes

### Before

```html
<script src="https://code.responsivevoice.org/responsivevoice.js?key=YOUR_KEY"></script>
```

### After

The closest migration keeps a script tag — load the browser bundle from the CDN and move your key into an `init()` call. Use npm instead if your app has a bundler.

**Browser bundle (CDN)**

```html
<script src="https://cdn.responsivevoice.org/sdk/latest/responsivevoice.js"></script>
<script>
  responsiveVoice.init({ apiKey: 'YOUR_KEY' });
</script>
```

**npm**

```bash
npm install @responsivevoice/core
```

```typescript
import { getResponsiveVoice } from '@responsivevoice/core';

const rv = await getResponsiveVoice({ apiKey: 'YOUR_KEY' });
```

## API Mapping

The core API remains the same:

| Legacy                        | Modern           | Notes          |
| ----------------------------- | ---------------- | -------------- |
| `responsiveVoice.speak()`     | `rv.speak()`     | Same signature |
| `responsiveVoice.cancel()`    | `rv.cancel()`    | Same behavior  |
| `responsiveVoice.pause()`     | `rv.pause()`     | Same behavior  |
| `responsiveVoice.resume()`    | `rv.resume()`    | Same behavior  |
| `responsiveVoice.getVoices()` | `rv.getVoices()` | Same behavior  |
| `responsiveVoice.isPlaying()` | `rv.isPlaying()` | Same behavior  |

In the browser bundle the global stays `responsiveVoice`; with npm you call the same methods on the `rv` instance from `getResponsiveVoice()`. The signatures are identical either way.

## Configuration Changes

### Before

```javascript
// Global configuration via URL parameter
<script src="...?key=YOUR_KEY"></script>;

// Or via global variable
window.responsiveVoice.setDefaultVoice('UK English Female');
```

### After

**Browser bundle (CDN)**

```html
<script src="https://cdn.responsivevoice.org/sdk/latest/responsivevoice.js"></script>
<script>
  responsiveVoice.init({
    apiKey: 'YOUR_KEY',
    defaultVoice: 'UK English Female',
  });
</script>
```

**npm**

```typescript
import { getResponsiveVoice } from '@responsivevoice/core';

const rv = await getResponsiveVoice({
  apiKey: 'YOUR_KEY',
  defaultVoice: 'UK English Female',
});
```

## Event System

Per-call event callbacks are unchanged from the legacy script:

**Browser bundle (CDN)**

```javascript
responsiveVoice.speak('Hello', 'UK English Female', {
  onstart: () => console.log('Started'),
  onend: () => console.log('Ended'),
});
```

**npm**

```typescript
rv.speak('Hello', 'UK English Female', {
  onstart: () => console.log('Started'),
  onend: () => console.log('Ended'),
});
```

## Breaking Changes

> [!WARNING]
> The following changes may require code updates:

### 1. Voice Data is Fetched at Runtime

Voice mappings are no longer bundled in the JavaScript file — `init()` fetches them from the API and caches them locally.

**Impact:** First initialization needs a network connection to fetch the voice catalog. There's nothing to pre-fetch — `init()` already loads voices before it resolves.

### 2. No Internet Explorer Support

The browser bundle (CDN) ships the polyfills modern browsers need and targets Chrome 69+, Firefox 65+, Safari 12+, Edge 79+, iOS Safari 12+, Chrome Android 69+, Android WebView 69+. Internet Explorer 11 is not supported.

**Impact:** If you need to support IE11 or similarly old browsers, stay on the legacy `responsivevoice.js` (v1).

## TypeScript Support

The new package includes full TypeScript definitions:

```typescript
import {
  getResponsiveVoice,
  type ResponsiveVoiceInitOptions,
} from '@responsivevoice/core';
import type { SpeakParams } from '@responsivevoice/types';

const options: ResponsiveVoiceInitOptions = {
  apiKey: 'YOUR_KEY',
};

const rv = await getResponsiveVoice(options);

const params: SpeakParams = {
  pitch: 1.0,
  rate: 1.0,
  onend: () => console.log('Done'),
};

rv.speak('Hello', 'UK English Female', params);
```

## Troubleshooting

### "Voice not found" Error

Ensure the voice name exactly matches an available voice:

```typescript
const voices = rv.getVoices();
console.log(voices.map((v) => v.name));
```

### "API key required" Error

Make sure to initialize with an API key:

```typescript
const rv = await getResponsiveVoice({ apiKey: 'YOUR_KEY' });
```

### Audio Not Playing on iOS

Mobile browsers (iOS, and Android Chrome) block autoplay, but ResponsiveVoice handles this automatically with a built-in permission prompt that captures the first tap and unlocks audio. If you've disabled the prompt, trigger speech from your own gesture handler instead:

```typescript
button.addEventListener('click', () => {
  rv.speak('Hello');
});
```

See the [FAQ](/guides/faq/#does-responsivevoice-work-on-ios) for details.

## Need Help?

- [API Reference](/api/core/src/)
- [Support](https://responsivevoice.org/support)
