The TTS WebSocket connection
On this page
Updated November 3, 2026, based on the xAI Text to Speech page: deltas of up to 60,000 characters, no connection timeout, and a “session permit” of 600 seconds. Source: Text to Speech.
Real-time speech synthesis over WebSocket
The Grok TTS API offers a WebSocket mode for streaming speech synthesis. Unlike unary HTTP mode, which waits until processing is done to return the complete audio, WebSocket sends audio chunks as they’re generated. It’s ideal for interactive apps where perceived latency must be as low as possible.
WebSocket endpoint
You connect to wss://api.x.ai/v1/tts. Configuration parameters go in the query string of the initial connection.
Connection parameters
| Parameter | Required | Default | Description |
|---|---|---|---|
language | Yes | — | BCP-47 code or auto |
voice | No | — | ID of a built-in or custom voice |
codec | No | mp3 | mp3, wav, pcm, mulaw (or ulaw), alaw |
sample_rate | No | 24000 | Sample rate |
bit_rate | No | 128000 | Bit rate (MP3 only) |
Full connection URL
wss://api.x.ai/v1/tts?language=en&voice=rex&codec=mp3&sample_rate=24000
Open the connection
In JavaScript (browser or Node.js)
const ws = new WebSocket(
"wss://api.x.ai/v1/tts?language=en&voice=rex&codec=mp3",
{
headers: {
"Authorization": `Bearer ${API_KEY}`
}
}
);
ws.onopen = () => {
console.log("TTS connection established");
};
ws.onerror = (error) => {
console.error("WebSocket error:", error);
};
Important: in a browser, the native WebSocket API doesn’t support custom headers. You’ll need to go through your backend for the connection (see the production lesson).
In Python with websockets
import asyncio
import websockets
import json
async def connect_tts():
uri = "wss://api.x.ai/v1/tts?language=en&voice=rex&codec=mp3"
headers = {"Authorization": f"Bearer {api_key}"}
async with websockets.connect(uri, additional_headers=headers) as ws:
print("TTS connection established")
# Send text and receive audio...
Session management
Lifetime
The xAI Text to Speech page says two things you should read together: the WebSocket connection has no request timeout (it stays open), and the “session permit” has a lifetime of 600 seconds, without the page explaining what happens when it runs out. To be safe, your app should:
- Detect when the connection closes
- Reconnect automatically if needed
- Resume sending text where it left off
Concurrent sessions
According to the Text to Speech page, your team is limited to 50 concurrent WebSocket sessions (the Rate limits page counts TTS sessions by tier, starting at 100). Beyond that, new connections are refused. Manage a connection pool for high-traffic apps.
Several texts on one connection
Unlike unary HTTP mode, where requests time out after 15 minutes, the connection stays open after each audio.done: you can send one text after another without reconnecting, and cancel the current one with text.clear (lesson 10).
Unary HTTP versus WebSocket
| Aspect | Unary HTTP | WebSocket |
|---|---|---|
| Latency | Complete audio after processing | First bytes right away |
| Max text | 60,000 characters per request | Unlimited (deltas of 60,000 max) |
| Timeout | 15 minutes | None; session permit of 600 seconds |
| Sessions | N/A | 50 per team |
| Use cases | Batch, audio files | Real time, streaming |
When to use WebSocket
WebSocket is the way to go as soon as real time is involved. When a user is waiting for an immediate spoken answer, from a chatbot or a voice assistant, every second of silence before the first sound costs you in perceived experience, and WebSocket lets playback start on the first audio fragments, before generation is even finished. It’s also the natural architecture when the text itself arrives gradually: the streamed output of an LLM plugs straight into TTS, delta by delta, without waiting for the complete text. And it lifts the length constraint: there’s no overall limit on total text, only individual deltas are capped at 60,000 characters, enough to voice an entire document as a continuous stream.
Unary HTTP mode still has its place wherever real time adds nothing: generating audio files in batches, processes that need the complete file before acting (post-processing, storage, sending), and, more simply, any architecture that prefers a stateless round trip to a persistent connection to manage.
Key takeaways
- TTS WebSocket is available at
wss://api.x.ai/v1/tts - Parameters go in the query string when you connect
- The connection doesn’t expire on its own, but the docs mention a 600-second session permit: plan for reconnection
- The limit is 50 concurrent sessions per team
- Text is unlimited (sent in deltas of up to 60,000 characters)
- Use WebSocket for real time, HTTP for batch