API Reference
Errors
The error envelope, every error code with its HTTP status, and which ones are worth retrying.
The envelope
Every failure — whatever its cause — returns the same shape:
{
"error": {
"code": "NO_LIVE_CHAT",
"message": "no live chat found - video may not be live, have no chat, or be unavailable"
}
}code is a stable enum and is what you should branch on. message is
human-readable, may be passed through from YouTube, and may change.
Every code
| Status | Code | Meaning |
|---|---|---|
400 |
INVALID_REQUEST |
The request body failed schema validation, or client was WEB with no webVersion |
400 |
INVALID_VIDEO_ID |
videoId was neither a recognized YouTube URL nor a bare 11-character id |
404 |
NO_LIVE_CHAT |
No liveChatRenderer or liveChatReplayRenderer with a continuation token could be found for the video |
410 |
TOKEN_EXPIRED |
The continuation token is no longer accepted and cannot be reused |
422 |
UNKNOWN_CLIENT |
client was not one of the known innertube client labels |
502 |
SW_JS_FAILED |
sw.js could not be fetched, or the API key / client version could not be parsed out of it |
502 |
NO_WORKING_CLIENT |
Neither WEB nor TVHTML5 produced a usable response on either endpoint |
502 |
UPSTREAM_ERROR |
YouTube returned an error for the request |
500 |
INTERNAL |
An unexpected server-side failure |
Notes on individual codes
INVALID_VIDEO_ID
The id must be extractable. These forms all work:
zvwJ29RFVww
https://www.youtube.com/watch?v=zvwJ29RFVww
https://youtu.be/zvwJ29RFVww
https://www.youtube.com/shorts/zvwJ29RFVww
https://www.youtube.com/embed/zvwJ29RFVww
https://www.youtube.com/live/zvwJ29RFVwwA channel URL or a playlist URL does not contain a video id and will fail.
NO_LIVE_CHAT
This is a 404 because it describes the video, not a fault. It covers several
real situations that are indistinguishable from the outside:
- the video is not live and has no replay chat,
- chat was disabled for the broadcast,
- replay chat has not finished processing, or has been turned off,
- the video is private, deleted, or region-blocked.
Retrying will not help unless the underlying situation changes.
TOKEN_EXPIRED
The only error with a clean recovery path: call
/v1/sessions again, take the fresh token, and
resume polling. Everything else in the session bundle stays valid. The client
library does this for you automatically and transparently.
SW_JS_FAILED
The server refuses to hardcode the innertube API key and fetches it live per
session. If YouTube changes the shape of sw.js, this is the code you get.
It is a server-side problem, not something a caller can fix.
UPSTREAM_ERROR
Worth knowing: YouTube signals innertube failures with HTTP 200 and an
error object in the body. The server treats that as a failure rather than an
empty success, which is why a genuine upstream problem surfaces here as a 502
instead of silently looking like a quiet chat.
Which errors are retryable
| Code | Retry? |
|---|---|
TOKEN_EXPIRED |
Yes — re-bootstrap a session, then continue |
UPSTREAM_ERROR |
Yes, with backoff — often transient |
INTERNAL |
Yes, with backoff |
SW_JS_FAILED |
Yes, with backoff, but repeated failures need a fix |
NO_WORKING_CLIENT |
Rarely — usually means the video is not readable |
NO_LIVE_CHAT |
No |
INVALID_VIDEO_ID |
No |
INVALID_REQUEST |
No |
UNKNOWN_CLIENT |
No |
The client library implements exactly this policy: exponential backoff from
500 ms, capped at 15 000 ms, giving up after 3 consecutive
failures — except for TOKEN_EXPIRED, which re-bootstraps and resets the
counter. See Events & Options.
Errors in the client library
The client raises every failure as an ApiHttpError:
import { ApiHttpError } from '@gettersethya/yt-livechat-client'
client.on('error', (error) => {
// error.code -> the enum above
// error.message -> human-readable detail
// error.status -> HTTP status, or 0 if the request never completed
if (error.code === 'NO_LIVE_CHAT') stopTrying()
})status is 0 when the failure happened before a response existed — a network
error, or an invalid video URL rejected in the constructor.