Migration guides / PlayHT
PlayHT shut down: move your PlayHT API calls to Cartesia
Code that still calls api.play.ht now fails at the DNS lookup, so every PlayHT request in your codebase needs a new target.
What happened to PlayHT
The dated events that ended the PlayHT API, each linked to its source.
Meta confirms it acquired PlayAI
Meta bought the company behind PlayHT and did not disclose terms. The team moved to Meta.
Biometric UpdateThe PlayHT API goes offline
API calls stopped working about two weeks after the acquisition, months before the platform's announced end date.
Inworld, migrating from PlayHTThe platform closes
Murf's transition guide quotes the date the platform would shut down completely.
Murf, PlayAI transition guideMigrate from PlayHT with your coding agent
Paste this into Claude Code, Cursor or Codex in the repo that calls PlayHT. It carries the field mapping, the Cartesia request and a rollout that keeps PlayHT behind a flag until you switch.
Prompt
Move this codebase from PlayHT to Cartesia for text to speech. Keep PlayHT working behind a flag until I switch over.
Shut down on December 31, 2025. Meta confirmed it had acquired PlayAI, PlayHT's parent, on July 12, 2025, and the API went offline around July 26, 2025. Inworld and Murf both give December 31, 2025 as the date the platform closed for good. We found no shutdown notice from PlayHT itself. On November 5, 2026 (UTC), `play.ht` and `api.play.ht` no longer resolved.
July 12, 2025: Meta confirms it acquired PlayAI. Meta bought the company behind PlayHT and did not disclose terms. The team moved to Meta. (https://www.biometricupdate.com/202507/meta-acquires-voice-generator-startup-playai)
July 26, 2025: The PlayHT API goes offline. API calls stopped working about two weeks after the acquisition, months before the platform's announced end date. (https://inworld.ai/resources/migrate-from-playht)
## 1. Find the calls
Search for `api.play.ht`, `PLAYHT_API_KEY` or `PLAYHT_USER_ID`. The request to replace is `POST https://api.play.ht/api/v2/tts/stream`. List every call site before you edit anything.
## 2. Target
- Request: `POST https://api.cartesia.ai/tts/bytes`
- Model: `model_id: "sonic-3.6"`
- Headers: `X-API-Key` read from the `CARTESIA_API_KEY` environment variable, and `Cartesia-Version: 2026-08-14`
- Auth swap: PlayHT sends the key in `AUTHORIZATION: Bearer` secret key plus an `X-USER-ID` header. Replace it with `X-API-Key` from `CARTESIA_API_KEY` on the Cartesia path only, and keep PlayHT's key for the PlayHT path. Both values are dead now. Remove them from your secrets store.
- Add `CARTESIA_API_KEY` wherever the project documents its environment (`.env.example`, README, deploy config). Never hardcode the key.
- Request size: PlayHT caps a request at 2,000 characters per request; 20,000 on Play3.0-mini. Cartesia publishes no per-request maximum, so keep any chunking the code already does and split at sentence boundaries; for long text, stream over the Cartesia TTS WebSocket.
- Voice IDs don't carry over. Keep each voice ID in one named constant or config value, put a placeholder where each PlayHT voice was, and list them for me so I can pick replacements at https://www.cartesia.ai/voices.
- Suggested starting points to put in those placeholders, for me to confirm by ear: Podcast or audiobook narrator → `a33f7a4c-100f-41cf-a1fd-5822e8fc253f` (Lauren - Lively Narrator); Support line or IVR prompt → `f786b574-daa5-4673-aa0c-cbe3e8534c02` (Katie - Friendly Fixer); Measured male voice for explainers → `98a34ef2-2140-4c28-9c71-663dc4dd7022` (Clyde - Calm Narrator).
## 3. Field mapping, PlayHT → Cartesia
- `POST https://api.play.ht/api/v2/tts/stream` → `POST /tts/bytes`
- `AUTHORIZATION: Bearer <secret key>` and `X-USER-ID` → `X-API-Key` and `Cartesia-Version: 2026-08-14`. Delete the user ID from your config. Cartesia has no equivalent.
- `voice`: an `s3://` manifest URL → `voice`: `{"id": "<voice id>"}`. PlayHT voices and clones went offline with the service. Pick a library voice, or clone again from your original recording.
- `voice_engine`: `PlayDialog`, `Play3.0-mini`, `PlayHT2.0` and others → `model_id`: `sonic-3.6`
- `text` (2,000 characters; 20,000 on `Play3.0-mini`) → `transcript`
- `language`: a lowercase name such as `english` → `language`: a code such as `en` or `en-GB`
- `output_format`: `mp3`, `wav` or `mulaw` → `output_format` object: `container` `mp3`, `wav` or `raw`, with `pcm_mulaw` for mu-law
- `sample_rate` (8000 to 48000) → `output_format.sample_rate` (8000 to 48000)
- `speed` (0.1 to 5) → `generation_config.speed` (0.6 to 1.5). Anything slower than 0.6 or faster than 1.5 has to be clamped.
- `emotion` → `generation_config.emotion`. The two vendors use different emotion names. Map each one by ear.
## 4. PlayHT fields with no Cartesia equivalent
- `output_format`: `ogg` or `flac`. What to do: Generate `mp3` or PCM, then convert with ffmpeg or your encoder of choice.
- `quality`, `temperature`, `seed`, `voice_guidance`, `style_guidance`, `text_guidance`. What to do: Drop them.
- `voice_2`, `turn_prefix`, `turn_prefix_2` (two-speaker PlayDialog). What to do: Synthesize each speaker's turns with that speaker's voice and join the clips in order.
## 5. Reference request
Match the language and HTTP client the codebase already uses. This is the same request in Python:
```python
import os
import requests
text = "Episode twelve. Today we talk to a beekeeper about the first warm week of spring."
VOICE_ID = "6ccbfb76-1fc6-48f7-b71d-91ac6298247b" # from /voices
response = requests.post(
"https://api.cartesia.ai/tts/bytes",
headers={
"X-API-Key": os.environ["CARTESIA_API_KEY"],
"Cartesia-Version": "2026-08-14",
},
json={
"model_id": "sonic-3.6",
"transcript": text,
"voice": {"id": VOICE_ID},
"language": "en",
"output_format": {
"container": "mp3",
"sample_rate": 44100,
"bit_rate": 128000,
},
},
)
response.raise_for_status()
open("out.mp3", "wb").write(response.content)
```
## 6. Roll out
1. Choose PlayHT or Cartesia per request from one config flag, defaulting to PlayHT.
2. Run the same scripts through both and save the clips side by side for me to listen to. Check that the container, encoding and sample rate match what downstream code expects.
3. Leave the PlayHT client, call and key in place so rollback is flipping the flag. Don't delete them in this change.
4. Run the existing tests, and add one that checks the Cartesia request body.
## Docs
- PlayHT stream API reference (docs.play.ht, still online): https://docs.play.ht/reference/api-generate-tts-audio-stream
- Inworld, migrating from PlayHT: https://inworld.ai/resources/migrate-from-playht
- Murf, PlayAI transition guide: https://murf.ai/blog/play-ai-transition-guide
- Cartesia TTS bytes API reference: https://docs.cartesia.ai/api-reference/tts/bytes
- Cartesia voice cloning guide: https://docs.cartesia.ai/build-with-cartesia/capability-guides/clone-voices
When you're done, tell me which files changed, which fields you couldn't map, and how to flip the flag.Every PlayHT field, mapped to Cartesia
The prompt carries this table. Each row is a field in your PlayHT request and the Cartesia field that replaces it.
- PlayHT
POST https:// api.play.ht/ api/ v2/ tts/ stream CartesiaPOST /tts/bytes - PlayHT
AUTHORIZATION: Bearer <secret key>andX-USER-IDCartesiaX-API-KeyandCartesia-Version: 2026-08-14NoteDelete the user ID from your config. Cartesia has no equivalent. - PlayHT
voice: ans3://manifest URLCartesiavoice:{"id": "<voice id>"}NotePlayHT voices and clones went offline with the service. Pick a library voice, or clone again from your original recording. - PlayHT
voice_engine:PlayDialog,Play3.0-mini,PlayHT2.0and othersCartesiamodel_id:sonic-3.6 - PlayHT
text(2,000 characters; 20,000 onPlay3.0-mini)Cartesiatranscript - PlayHT
language: a lowercase name such asenglishCartesialanguage: a code such asenoren-GB - PlayHT
output_format:mp3,wavormulawCartesiaoutput_formatobject:containermp3,wavorraw, withpcm_mulawfor mu-law - PlayHT
sample_rate(8000 to 48000)Cartesiaoutput_format.sample_rate(8000 to 48000) - PlayHT
speed(0.1 to 5)Cartesiageneration_config.speed(0.6 to 1.5)NoteAnything slower than 0.6 or faster than 1.5 has to be clamped. - PlayHT
emotionCartesiageneration_config.emotionNoteThe two vendors use different emotion names. Map each one by ear.
PlayHT API key and auth, mapped to Cartesia
Cartesia reads the key from the X-API-Key header and pins the API version with Cartesia-Version on every request.
- PlayHT
AUTHORIZATION: Bearersecret key plus anX-USER-IDheaderCartesiaX-API-KeyplusCartesia-Version: 2026-08-14NoteBoth values are dead now. Remove them from your secrets store.
PlayHT API pricing per 1,000 characters
List prices per 1,000 characters from the vendor's own pricing page. Plans, regions and volume discounts change what you pay.
- Model or plan
PlayHT API
PlayHTNot published (service ended)NoteThe pricing page went offline with the domain, so there is no current figure to cite.
On Cartesia, usage draws from your plan's credits: 20,000 credits a month on the Free plan (about 20,000 characters). Enterprise pricing is custom.
Cartesia plans and pricingPlayHT limits compared with Cartesia
Published limits from both companies. Plans change them, so check both pages before you size a rollout.
- Limit
Request limit
CartesiaNo published maximum; stream long text over the TTS WebSocketPlayHT2,000 characters per request; 20,000 on Play3.0-mini - Limit
Languages
Cartesia44 languages for text to speechPlayHT37languagevalues on Play3.0-mini and PlayDialog
Cartesia's figures come from its pricing page and voice library.
Cartesia pricing and plan limitsSources
Limits read from each company's documentation in November 2026.
PlayHT voices and where to start on Cartesia
Stock and cloned voices, each named by an s3:// manifest URL
Each card is a starting point for a common PlayHT pick, matched by language and use. Listen before you choose.
What you get on Cartesia
What changes once the PlayHT call is gone.
One key, no user ID
PlayHT wanted a secret key in AUTHORIZATION plus your account's X-USER-ID on every call. Cartesia takes one X-API-Key and a Cartesia-Version header.
Voices are IDs, not S3 manifests
PlayHT named each voice with an s3://.../manifest.json URL. A Cartesia voice is a UUID you copy from the voice library or get back when you clone.
Word timings for captions
Turn on add_timestamps over the TTS WebSocket to get a start and end time for every word, which is enough to sync podcast transcripts or subtitles.
How to migrate from PlayHT to Cartesia
The same changes the prompt makes, if you'd rather make them yourself.
Search the codebase for
api.play.ht,X-USER-IDandvoice_engineto find every call site, including ones that have failed silently since July 2025.Get a Cartesia API key. For each PlayHT voice, shortlist a library voice by role, or clone from the recording you originally uploaded to PlayHT (10 seconds minimum, Pro plan or higher).
Replace the request as in the code above. Translate
languagenames to codes and clampspeed.Split two-speaker PlayDialog scripts into one request per turn.
Remove the PlayHT key and user ID from your secrets store once no code reads them.
PlayHTSources
Request shapes checked against vendor documentation in November 2026.
Compare and read next
Frequently asked questions
What happened to PlayHT?
Can I recover my PlayHT voices?
Not from PlayHT. If you still have the recording you used to clone a voice, and permission to use it, Cartesia makes an instant clone from 10 seconds of it on a Pro plan or higher. A professional clone needs 30 minutes of audio and a Startup plan.
Where did play.ht pricing go?
Offline, along with the rest of play.ht. We can't cite a PlayHT price because no live page states one. Cartesia's plans are on /pricing.
What doesn't carry over from PlayHT?
quality, temperature, seed and the three guidance knobs have no Cartesia fields. Two-speaker PlayDialog requests become one request per turn. ogg and flac output need a transcode, and speed narrows from 0.1 to 5 down to 0.6 to 1.5.
How do I check the new voice against the old one?
You can't run PlayHT side by side any more, so compare against clips you saved while it worked. Pull a few stored PlayHT outputs, render the same scripts on Cartesia, and listen to them in pairs before you pick a voice for each role.
Get started today
Talk to an expert.
Connect with a member of our team and learn how Cartesia can help you build world-class voice experiences.
Start building.
Create an API key, then hand your coding agent the migration prompt and a few of your own scripts.