API Reference
POST /v1/sessions
Bootstrap a chat stream and receive the credentials, first continuation token, and initial backlog.
Opens a chat stream. Call this once per video, then drive
/v1/poll with what it returns.
POST /v1/sessions
Content-Type: application/jsonRequest
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
videoId |
string |
yes | — | A full YouTube URL or a bare 11-character video id |
includeInitial |
boolean |
no | true |
Include the backlog already on the page in messages |
videoId is permissive about its input — see
Client Usage for every URL form that resolves.
{
"videoId": "https://www.youtube.com/watch?v=zvwJ29RFVww",
"includeInitial": true
}Response
| Field | Type | Description |
|---|---|---|
videoId |
string |
The resolved 11-character id |
chatType |
"liveChatRenderer" | "liveChatReplayRenderer" |
Whether this is a live chat or a replay chat |
client |
string |
The innertube client that worked, e.g. WEB |
host |
string |
The host that client talks to, e.g. https://www.youtube.com |
endpoint |
"get_live_chat" | "get_live_chat_replay" |
The innertube endpoint that worked |
apiKey |
string |
Innertube API key scraped from sw.js |
webVersion |
string |
Innertube client version scraped from sw.js |
token |
string |
The first continuation token |
timeoutMs |
number |
How long YouTube suggests waiting before the first poll |
messages |
Message[] |
The initial backlog, or [] when includeInitial is false |
{
"videoId": "zvwJ29RFVww",
"chatType": "liveChatRenderer",
"client": "WEB",
"host": "https://www.youtube.com",
"endpoint": "get_live_chat",
"apiKey": "AIzaSy...",
"webVersion": "2.20240726.00.00",
"token": "0ofMyAN...",
"timeoutMs": 1000,
"messages": []
}Carrying the session forward
Five of these fields are the input to every subsequent poll:
const poll = {
token: session.token,
client: session.client,
endpoint: session.endpoint,
apiKey: session.apiKey,
webVersion: session.webVersion,
}token is replaced by each poll response; the other four stay fixed for the
life of the stream.
Live versus replay
You do not choose between them — the server detects which one the video has.
chatType tells you what it found, and endpoint tells you which innertube
endpoint is being used to read it. The two do not always pair the way you would
expect: the server picks whichever endpoint actually returns a parseable
response, so a replay chat may still be read through get_live_chat.
Errors
| Status | Code | Cause |
|---|---|---|
400 |
INVALID_REQUEST |
Body failed schema validation |
400 |
INVALID_VIDEO_ID |
videoId is not a URL or id this server can parse |
404 |
NO_LIVE_CHAT |
No chat renderer with a continuation token was found |
502 |
SW_JS_FAILED |
Could not read the API key / client version from sw.js |
502 |
NO_WORKING_CLIENT |
No client + endpoint combination was accepted |
502 |
UPSTREAM_ERROR |
YouTube returned an error while bootstrapping |
Full descriptions in Errors.