Skip to main content
Lesson 9 of 14 · Text-to-Speech API

The TTS WebSocket connection

Lesson 9 of 14 Updated November 3, 2026 Developer
On this page
  1. Real-time speech synthesis over WebSocket
  2. WebSocket endpoint
  3. Open the connection
  4. Session management
  5. Unary HTTP versus WebSocket
  6. When to use WebSocket
  7. Key takeaways

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.

wss://
Secure protocol
50
Sessions per team
600 s
Session permit
∞
Unlimited text

WebSocket endpoint

You connect to wss://api.x.ai/v1/tts. Configuration parameters go in the query string of the initial connection.

Connection parameters

ParameterRequiredDefaultDescription
languageYes—BCP-47 code or auto
voiceNo—ID of a built-in or custom voice
codecNomp3mp3, wav, pcm, mulaw (or ulaw), alaw
sample_rateNo24000Sample rate
bit_rateNo128000Bit 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:

  1. Detect when the connection closes
  2. Reconnect automatically if needed
  3. 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

AspectUnary HTTPWebSocket
LatencyComplete audio after processingFirst bytes right away
Max text60,000 characters per requestUnlimited (deltas of 60,000 max)
Timeout15 minutesNone; session permit of 600 seconds
SessionsN/A50 per team
Use casesBatch, audio filesReal 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