README 明确声明这不是生产级 API,而是逆向工程项目,生产环境建议改用其 WebSocket API;连接时默认会拉取房间信息,主播未开播会以 UserOfflineError 拒绝连接;使用 useMobile 必须同时开启 authenticateWs 并提供 session.cookie,否则抛 TypeError
TikTok-Live-Connector
zerodytrashAGPL-3.0活跃维护非官方 Node.js 库,实时接收 TikTok 直播间的评论、礼物等事件,方便做直播互动机器人或数据采集。
TikTok LIVE API for Node.js: An unofficial library to receive live stream events (comments, gifts, etc.) in realtime from TikTok LIVE.
用创作者用户名免登录接入 TikTok LIVE 实时事件流的 Node.js 非官方库
非官方 Node.js 库,实时接收 TikTok 直播间的评论、礼物等事件,方便做直播互动机器人或数据采集。
核心能力
- 用 uniqueId 直连 Webcast 推送服务,无需登录或注册应用
- 实时接收评论、礼物、点赞、关注、分享、观众数与连麦对战事件
- 提供 connect、fetchRoomInfo、fetchAvailableGifts 等连接与查询方法
- 可开启 enableExtendedGiftInfo 获取礼物名称、价格与图片
- 支持通过 webClientOptions 与 wsClientOptions 配置代理和超时
容易踩的坑
- v2.5.0最新正式版2026-09-16 · 2026-09-16 11:14 UTC
What's Changed
- Authenticated session connections fixed.
authenticateWs: truenow works with either a cookie bundle or an OAuth bundle.useMobile: truenow requiresauthenticateWs: trueand throws aTypeErrorotherwise. WebSocket handshake rejections during connect now surface the server'shandshake-msg, andEMPTY_COOKIESsign errors include it as well. (92dc913) - Anonymous connections no longer send session cookies over the WebSocket. New
WebcastCookieJar.getAnonymousCookieString()stripssessionidandtt-target-idc; it is used for the WebSocketCookieheader wheneverauthenticateWsis false. (2d47227, 92dc913) - Preserve Euler rate-limit response headers (
retry-after,x-ratelimit-reset,x-log-id,x-agent-id) onSignatureRateLimitErrorby @sleepylessons in https://github.com/zerodytrash/TikTok-Live-Connector/pull/331 - Docs:
useMobilerequiresauthenticateWsrather than implying it. (5bc9dc5)
Full Changelog: https://github.com/zerodytrash/TikTok-Live-Connector/compare/v2.4.4...v2.5.0
- Authenticated session connections fixed.
- v2.3.0-beta1pre-release2026-05-01 · 2026-05-01 00:21 UTC
查看更新说明
Developer Notes:
This is a major update.
The new 2.3.0 version has been promoted to beta, meaning it is considered much more stable.
This new version adds support for the v3 Schema, an update that adds 30+ new TikTok LIVE events!
This new version also fixes a lot of broken protobuf fields that were incorrect or outdated in the v2 schema that has been used for the last ~1 year.
The NodeJS library & Python library schemas are now 1:1 🎉 😄.
General Changes
- Decoupled Euler Stream fully, you can now run the library without Euler by swapping out routes via
RouteConfigglobal :star: - Dropped
axiosin favour of the much more moderngotHTTP library :star: - Removed
.protofolder & bundled Protobuf types in favour oftiktok-live-proto - Bumped
@eulerstream/euler-api-sdkto 0.3.0 - Added new
WebcastEvent.SUPER_FAN:new: - Added new
WebcastEvent.SUPER_FAN_JOIN:new: - Added new
WebcastEvent.SUPER_FAN_BOX:new: - Added
abortSignaltowaitUntilLivefunction :new: - Split the Config into
WebcastWebConfigDefaultsandWebcastWebSocketConfigDefaults:star:
Architecture Changes
- Routes were previously attached to a class object. They are now function-based instead which is much more idiomatic :star:
WebcastHttpClientnow is only a request library, and has no specific function calling implementation in it- Routes now have per-route configuration possible
CookieJarhas becomeWebcastCookieJarand is promise-based- Refactored project to be much more modular in nature
- Removed many duplicate constructor props & merged them into other props :star:
- Removed many no-longer relevant / deprecated constructor props :star:
- Introduced CI/CD pipeline basics with GitHub workflows
Auto-Generated:
What's Changed
- fix for undefined properties object being passed into getRoomInfo call by @AdamJessop in https://github.com/zerodytrash/TikTok-Live-Connector/pull/270
- Update README.md by @isaackogan in https://github.com/zerodytrash/TikTok-Live-Connector/pull/279
- fix(ws-client): remove recursive emit('close') from onDisconnect handler by @DonnyMoshWill in https://github.com/zerodytrash/TikTok-Live-Connector/pull/282
- fix gift not working by @adityadees in https://github.com/zerodytrash/TikTok-Live-Connector/pull/284
- Add Support for TikTok Super Fan Box Events by @sleepylessons in https://github.com/zerodytrash/TikTok-Live-Connector/pull/308
- Adding Support for Super Fan Box to LEGACY API by @sleepylessons in https://github.com/zerodytrash/TikTok-Live-Connector/pull/309
- Adding missing examples to README, updating existing to show more context by @sleepylessons in https://github.com/zerodytrash/TikTok-Live-Connector/pull/304
- #fix: update axios to 1.15.0 (CVE-2026-40175) by @dws2020 in https://github.com/zerodytrash/TikTok-Live-Connector/pull/317
- Distinguish Super Fan Joined from New Super Fan event by @sleepylessons in https://github.com/zerodytrash/TikTok-Live-Connector/pull/319
New Contributors
- @AdamJessop made their first contribution in https://github.com/zerodytrash/TikTok-Live-Connector/pull/270
- @DonnyMoshWill made their first contribution in https://github.com/zerodytrash/TikTok-Live-Connector/pull/282
- @adityadees made their first contribution in https://github.com/zerodytrash/TikTok-Live-Connector/pull/284
- @sleepylessons made their first contribution in https://github.com/zerodytrash/TikTok-Live-Connector/pull/308
- @dws2020 made their first contribution in https://github.com/zerodytrash/TikTok-Live-Connector/pull/317
Full Changelog: https://github.com/zerodytrash/TikTok-Live-Connector/compare/v1.2.2...v2.3.0-beta1
- Decoupled Euler Stream fully, you can now run the library without Euler by swapping out routes via
- v1.2.32025-01-28 · 2025-01-28 08:47 UTC
查看更新说明
- Fix
TikTok does not offer a websocket upgradeerror
Update via
npm updateornpm i tiktok-live-connector - Fix
- v1.2.22024-12-13 · 2024-12-13 16:48 UTC
查看更新说明
- Fix empty room info (#244, #245) by @isaackogan
- v1.1.92024-07-10 · 2024-07-10 23:36 UTC
查看更新说明
- Add
signProviderOptionsfor using non-default signing servers. (https://github.com/zerodytrash/TikTok-Live-Connector/pull/204) by @shaiyon - Fix
roomIdextraction from page source (https://github.com/zerodytrash/TikTok-Live-Connector/pull/212) by @fmalk
Update via
npm i tiktok-live-connector - Add
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
TikTok LIVE API for Node.JS (Unofficial)
TikTok LIVE API Client for Node.JS (Unofficial, Unaffiliated with ByteDance Ltd.)
Connect to any TikTok LIVE stream and receive real-time chat messages,
gifts, likes, follows, shares, viewer counts and battles using just a creator's username (@uniqueId).
No login, credentials or app registration are required.
TikTokLiveConnector reads TikTok's internal Webcast push service directly, which makes it the foundation for TikTok chat bots, gift trackers, OBS overlays, donation alerts, moderation tools and livestream analytics. It works for your own live chat and for any other creator's.
Full guides, event reference and API documentation: https://ttlc.docs.isaackogan.com/
Tracked events include Chat Comments, Members Joining, Gifts, Viewers, Follows, Shares, Questions, Likes, Super Fans and Battles.
[!NOTE] This is not a production-ready API. It is a reverse engineering project. Use the WebSocket API for production.
[!TIP] An example project is available at https://tiktok-chat-reader.zerody.one/ - View Source
Do you prefer other programming languages?
- Python rewrite: TikTokLive by @isaackogan and @eulerstream
- Java rewrite: TikTokLiveJava by @jwdeveloper and @kohlerpop1
- Go rewrite: GoTikTokLive by @steampoweredtaco and @davincible
- C# rewrite: TikTokLiveSharp by @frankvHoof93
Table of Contents
Getting Started
- Install the package via NPM
npm i tiktok-live-connector
- Create your first TikTok LIVE chat connection
// Username of someone who is currently live
import { TikTokLiveConnection, WebcastEvent } from 'tiktok-live-connector';
const tiktokUsername = 'officialgeilegisela';
// Create a new wrapper object and pass the username
const connection = new TikTokLiveConnection(tiktokUsername);
// Connect to the chat (await can be used as well)
connection.connect().then(state => {
console.info(`Connected to roomId ${state.roomId}`);
}).catch(err => {
console.error('Failed to connect', err);
});
// Define the events that you want to handle
// In this case we listen to chat messages (comments)
connection.on(WebcastEvent.CHAT, data => {
console.log(`${data.user.uniqueId} (userId:${data.user.uniqueId}) writes: ${data.comment}`);
});
// And here we receive gifts sent to the streamer
connection.on(WebcastEvent.GIFT, data => {
console.log(`${data.user.uniqueId} (userId:${data.user.userId}) sends ${data.giftId}`);
});
// ...and more events described in the documentation below
Params and Options
To create a new TikTokLiveConnection object the following parameters can be specified.
TikTokLiveConnection(uniqueId, [options])
| Param Name | Required | Description |
|---|---|---|
uniqueId | Yes | The unique username of the broadcaster. You can find this name in the URL.Example: https://www.tiktok.com/@officialgeilegisela/live becomes officialgeilegisela. The leading @ and the full URL form are also accepted. |
options | No | Optional connection properties. Defaults are applied when a value is not specified.signApiKey (default: undefined)Euler Stream API key. When provided, it is written to the global SignConfig.apiKey before the underlying Euler client is created. Ignored when eulerApiInstance is passed.eulerApiInstance (default: undefined)Pre-built EulerStreamApiClient to use for all sign-server traffic. Takes precedence over signApiKey.session (default: undefined)Authenticated session bundle. Pass session.cookie to seed the cookie jar with sessionid and tt-target-idc, and/or session.oAuthToken to send an OAuth token to the sign server. Required when authenticateWs or useMobile is true. See Authenticated Connection.authenticateWs (default: false)Forward the session cookies or OAuth token to the sign server so the WebSocket is authenticated. Disabled by default since signing is done by a third-party service; enabling it sends your session credentials to that service.useMobile (default: false)Use the mobile WebSocket flow. Requires authenticateWs: true and session.cookie; connecting with useMobile but without authenticateWs throws a TypeError.processInitialData (default: true)Decode and emit the message batch returned in the initial sign response (recent chat history etc.).fetchRoomInfoOnConnect (default: true)Fetch room info during connect. If the streamer is not currently live the connect rejects with UserOfflineError. The fetched info is stored on connection.roomInfo and is also accessible via fetchRoomInfo().enableExtendedGiftInfo (default: false)Fetch the room gift list during connect so WebcastGiftMessage events carry an extendedGiftInfo field with name, cost, and image data.clientPresets (default: randomized)Pre-built { device, screen, location } presets. Defaults to a freshly randomized set from getRandomPresets().webClientOptions (default: {})Extra options forwarded to the underlying got HTTP client (proxy agent, timeout, etc.). Headers and search params from this object are merged with the defaults; transport-only fields are passed through. See Proxied Connection.wsClientOptions (default: {})Extra options forwarded to the underlying ws WebSocket client. See Proxied Connection.webConfigOverrides (default: {})Partial overrides for the resolved WebcastWebConfigDefaults used by the HTTP client. Use this to customize DEFAULT_HTTP_CLIENT_PARAMS, DEFAULT_HTTP_CLIENT_HEADERS, etc.wsConfigOverrides (default: {})Partial overrides for the resolved WebcastWebSocketConfigDefaults used by the WebSocket client. Use this to customize DEFAULT_WS_CLIENT_PARAMS or DEFAULT_WS_CLIENT_HEADERS. |
Example Options
const tikTokLiveConnection = new TikTokLiveConnection(tiktokUsername, {
signApiKey: 'your-api-key',
processInitialData: false,
enableExtendedGiftInfo: true,
webConfigOverrides: {
DEFAULT_HTTP_CLIENT_PARAMS: {
app_language: 'en-US',
device_platform: 'web_pc'
},
DEFAULT_HTTP_CLIENT_HEADERS: {
'X-Custom-Header': 'value'
}
},
wsConfigOverrides: {
DEFAULT_WS_CLIENT_PARAMS: {
app_language: 'en-US'
},
DEFAULT_WS_CLIENT_HEADERS: {
'X-Custom-Header': 'value'
}
},
webClientOptions: {
timeout: { request: 10000 }
},
wsClientOptions: {
handshakeTimeout: 10000
}
});
Methods
| Method Name | Description |
|---|---|
connect([roomId]) | Connects to the live stream chat. Returns a Promise<TikTokLiveConnectionState> that resolves when the WebSocket is open and the room has been entered. Pass an explicit roomId to skip room-id resolution. |
disconnect() | Closes the WebSocket and waits for the close event before resolving. Safe to call even when not connected. |
sendMessage(content, [roomId]) | Sends a chat message to the connected room (or to roomId if provided). Requires signApiKey and an authenticated session. See Send Messages. |
fetchRoomId([uniqueId]) | Resolves the room id for the configured username (or for uniqueId if provided). Tries HTML scrape, then the TikTok API, then Euler Stream as a fallback. |
fetchIsLive([uniqueId]) | Resolves whether the user is currently live. Same fallback chain as fetchRoomId. |
waitUntilLive([seconds], [abortSignal]) | Polls fetchIsLive every seconds seconds (minimum 30) until the streamer goes live. Reject via abortSignal to cancel. |
fetchRoomInfo([roomId]) | Fetches room info from TikTok's webcast API. Caches the result on connection.roomInfo. Callable without an active connection. See Retrieve Room Info. |
fetchAvailableGifts() | Fetches the room gift list. Caches on connection.availableGifts. Callable without an active connection. See Retrieve Available Gifts. |
Properties
| Property Name | Description |
|---|---|
webClient: WebcastHttpClient | The HTTP client used to talk to TikTok's web and webcast APIs. Holds the cookie jar, the merged client params, and the merged client headers. |
apiClient: EulerStreamApiClient | The Euler Stream API client used for sign-server traffic and other premium endpoints. Equivalent to webClient.apiClient. |
wsClient: WebcastWebSocketClient | null | The active WebSocket client. null until the connection is established and after disconnect. |
options: TikTokLiveConnectionMutableOptions | The subset of options retained on the instance (processInitialData, fetchRoomInfoOnConnect, enableExtendedGiftInfo, authenticateWs, useMobile). |
roomInfo: RoomInfo | null | The room info object cached from the most recent fetchRoomInfo() call (or from connect, when fetchRoomInfoOnConnect is true). |
availableGifts: RoomGiftInfo | null | The cached gift list. Populated when enableExtendedGiftInfo is true or after manually calling fetchAvailableGifts(). |
isConnecting: boolean | True while connect() is in flight. |
isConnected: boolean | True after a successful connect, until the WebSocket closes. |
clientParams: Record<string, string> | Live URI parameters sent with every webClient request. Mutating this changes outgoing query strings. |
roomId: string | The currently bound room id. Empty string until connect resolves or fetchRoomId() is called. |
state: TikTokLiveConnectionState | Snapshot containing isConnected, isConnecting, roomId, roomInfo, and availableGifts. |
Signing Configuration
WebSocket URL signing is delegated to the Euler Stream sign server via the
@eulerstream/euler-api-sdk package. Configuration is held on the
mutable SignConfig singleton.
For most users, passing signApiKey to the TikTokLiveConnection constructor is enough. It writes the key to
SignConfig.apiKey before the underlying Euler client is built.
For advanced cases (custom sign-server URL, extra headers, JWT auth), mutate SignConfig directly before
constructing your first connection:
import { SignConfig } from 'tiktok-live-connector';
SignConfig.apiKey = 'your api key'; // An API key created at https://www.eulerstream.com
SignConfig.basePath = 'https://your-custom-sign-server.com';
SignConfig.baseOptions = SignConfig.baseOptions || {};
SignConfig.baseOptions.headers = {
...(SignConfig.baseOptions.headers || {}),
'X-Custom-Header': 'Custom-Header-Value'
};
[!IMPORTANT]
SignConfigis read once when the underlying Euler client is first instantiated and the result is cached. Mutate it before constructing the firstTikTokLiveConnection, or pass an expliciteulerApiInstanceto bypass the cache.
Accessing TikTok LIVE Routes
All HTTP route handlers live in the global RouteConfig registry and are also exported individually.
Each route is a function that accepts a single options object and returns a Promise resolving to the route's
response. The currently registered routes are:
fetchRoomInfo(TikTok webcast API)fetchRoomGifts(TikTok webcast API)fetchRoomInfoFromApiLive(TikTok web API)fetchRoomInfoFromHtml(HTML scrape with SIGI_STATE extraction)fetchRoomGiftsFromProvider(Euler Stream)fetchRoomGiftGalleryFromProvider(Euler Stream)fetchRoomIdFromProvider(Euler Stream)fetchRoomInfoFromProvider(Euler Stream)fetchSignedWebSocketFromProvider(Euler Stream)fetchWebcastSignatureFromProvider(Euler Stream)sendRoomChatFromProvider(Euler Stream)fetchRoomIdComposite(HTML, then API, then Euler fallback)fetchIsLiveComposite(HTML, then API, then Euler fallback)
Example Usage
Routes need a webClient (and an apiClient for Euler routes), both of which are exposed on a
TikTokLiveConnection instance:
import { TikTokLiveConnection, RouteConfig } from 'tiktok-live-connector';
const connection = new TikTokLiveConnection('officialgeilegisela');
const sigiState = await RouteConfig.fetchRoomInfoFromHtml({
webClient: connection.webClient,
uniqueId: 'officialgeilegisela'
});
console.log('SIGI_STATE liveRoom:', sigiState.liveRoom);
Swapping a Route Implementation
You can replace any handler in RouteConfig to inject custom behavior (caching, alternate sign provider,
proxying through your own backend, etc.):
import { RouteConfig } from 'tiktok-live-connector';
const original = RouteConfig.fetchSignedWebSocketFromProvider;
RouteConfig.fetchSignedWebSocketFromProvider = async (args) => {
console.log('signing for room', args.roomId);
return original(args);
};
Accessing 3rd-Party (Euler Stream) Routes
The Euler Stream API client is exposed as connection.apiClient. It wraps every endpoint published by the
@eulerstream/euler-api-sdk package, including premium and
analytics endpoints not bundled into RouteConfig.
Example 1: Fetching Rate Limits
import { TikTokLiveConnection } from 'tiktok-live-connector';
const connection = new TikTokLiveConnection('officialgeilegisela', {
signApiKey: 'your-api-key'
});
const response = await connection.apiClient.webcast.getRateLimits();
console.log('Rate Limits:', response.data);
Example 2: Using JWT Authentication
When running the connector in a client-facing environment (bundled desktop app, browser worker, etc.) you should not ship your raw API key. Mint a short-lived JWT on your server and hand that to the client instead.
Server-Side
import { SignConfig, createEulerClient } from 'tiktok-live-connector';
SignConfig.apiKey = 'your_server_side_api_key';
const apiClient = createEulerClient();
const res = await apiClient.authentication.createJWT(
122, // Your account ID
{
limits: { minute: 5, hour: 5, day: 5 },
expireAfter: 60 * 60 * 2 // 2 hours, the maximum accepted value
}
);
console.log('Generated JWT:', res.data.token);
Client-Side
import { SignConfig, TikTokLiveConnection } from 'tiktok-live-connector';
SignConfig.baseOptions = SignConfig.baseOptions || {};
SignConfig.baseOptions.headers = {
...(SignConfig.baseOptions.headers || {}),
'x-jwt-key': 'generated-jwt-key'
};
const connection = new TikTokLiveConnection('tv_asahi_news');
Events
A TikTokLiveConnection object has the following events which can be handled with an event listener.
The simplest event handler is a connect event:
const connection = new TikTokLiveConnection('officialgeilegisela');
connection.on(ControlEvent.CONNECTED, () => console.log("Connected!"));
Control Events:
See the control event reference for arguments and examples.
ControlEvent.CONNECTEDor"connected"ControlEvent.DISCONNECTEDor"disconnected"ControlEvent.RAW_DATAor"rawData"ControlEvent.DECODED_DATAor"decodedData"ControlEvent.WEBSOCKET_CONNECTEDor"websocketConnected"ControlEvent.ERRORor"error"ControlEvent.WEBSOCKET_DATAor"websocketData"
Message Events:
See the message event reference for payloads and examples.
WebcastEvent.CHATor"chat"WebcastEvent.GIFTor"gift"WebcastEvent.MEMBERor"member"WebcastEvent.LIKEor"like"WebcastEvent.SOCIALor"social"WebcastEvent.ENVELOPEor"envelope"WebcastEvent.QUESTION_NEWor"questionNew"WebcastEvent.LINK_MIC_BATTLEor"linkMicBattle"WebcastEvent.LINK_MIC_ARMIESor"linkMicArmies"WebcastEvent.LIVE_INTROor"liveIntro"WebcastEvent.SUPER_FANor"superFan"WebcastEvent.SUPER_FAN_JOINor"superFanJoin"WebcastEvent.FOLLOWor"follow"WebcastEvent.SHAREor"share"WebcastEvent.STREAM_ENDor"streamEnd"WebcastEvent.ROOM_USERor"roomUser"WebcastEvent.EMOTEor"emote"WebcastEvent.GOAL_UPDATEor"goalUpdate"WebcastEvent.ROOM_MESSAGEor"roomMessage"WebcastEvent.CAPTION_MESSAGEor"captionMessage"WebcastEvent.IM_DELETEor"imDelete"WebcastEvent.IN_ROOM_BANNERor"inRoomBanner"WebcastEvent.RANK_UPDATEor"rankUpdate"WebcastEvent.POLL_MESSAGEor"pollMessage"WebcastEvent.RANK_TEXTor"rankText"WebcastEvent.LINK_MIC_BATTLE_PUNISH_FINISHor"linkMicBattlePunishFinish"WebcastEvent.LINK_MIC_BATTLE_TASKor"linkMicBattleTask"WebcastEvent.LINK_MIC_FAN_TICKET_METHODor"linkMicFanTicketMethod"WebcastEvent.LINK_MIC_METHODor"linkMicMethod"WebcastEvent.UNAUTHORIZED_MEMBERor"unauthorizedMember"WebcastEvent.OEC_LIVE_SHOPPINGor"oecLiveShopping"WebcastEvent.MSG_DETECTor"msgDetect"WebcastEvent.LINK_MESSAGEor"linkMessage"WebcastEvent.ROOM_VERIFYor"roomVerify"WebcastEvent.LINK_LAYERor"linkLayer"WebcastEvent.ROOM_PINor"roomPin"WebcastEvent.SUPER_FAN_BOXor"superFanBox"WebcastEvent.ACCESS_CONTROLor"accessControl"WebcastEvent.ACCESS_RECALLor"accessRecall"WebcastEvent.BOOST_CARDor"boostCard"WebcastEvent.BOTTOM_MESSAGEor"bottomMessage"WebcastEvent.CAPSULEor"capsule"WebcastEvent.GAME_RANK_NOTIFYor"gameRankNotify"WebcastEvent.GIFT_BROADCASTor"giftBroadcast"WebcastEvent.GIFT_DYNAMIC_RESTRICTIONor"giftDynamicRestriction"WebcastEvent.GIFT_PANEL_UPDATEor"giftPanelUpdate"WebcastEvent.GIFT_PROMPTor"giftPrompt"WebcastEvent.GUIDEor"guide"WebcastEvent.HOURLY_RANKor"hourlyRank"WebcastEvent.LINK_MIC_LAYOUT_STATEor"linkMicLayoutState"WebcastEvent.LINK_STATEor"linkState"WebcastEvent.LIVE_GAME_INTROor"liveGameIntro"WebcastEvent.MARQUEE_ANNOUNCEMENTor"marqueeAnnouncement"WebcastEvent.NOTICEor"notice"WebcastEvent.PARTNERSHIP_DROPS_UPDATEor"partnershipDropsUpdate"WebcastEvent.PARTNERSHIP_GAME_OFFLINEor"partnershipGameOffline"WebcastEvent.PARTNERSHIP_PUNISHor"partnershipPunish"WebcastEvent.PERCEPTIONor"perception"WebcastEvent.ROOM_NOTIFYor"roomNotify"WebcastEvent.SPEAKERor"speaker"WebcastEvent.SUB_NOTIFYor"subNotify"WebcastEvent.SUB_PIN_EVENTor"subPinEvent"WebcastEvent.TOASTor"toast"WebcastEvent.VIEWER_PICKS_UPDATEor"viewerPicksUpdate"
Examples
Retrieve Room Info
const connection = new TikTokLiveConnection('@username');
connection.fetchRoomInfo().then((roomInfo: RoomInfoResponse) => {
console.log(roomInfo);
console.log(`Stream started timestamp: ${roomInfo.create_time}, Streamer bio: ${roomInfo.owner.bio_description}`);
console.log(`HLS URL: ${roomInfo.stream_url.hls_pull_url}`); // Can be played or recorded with e.g. VLC
}).catch(err => {
console.error(err);
});
Retrieve Available Gifts
const connection = new TikTokLiveConnection('@username');
connection.fetchAvailableGifts().then((giftList: RoomGiftInfo) => {
console.log(giftList);
giftList.forEach(gift => {
console.log(`id: ${gift.id}, name: ${gift.name}, cost: ${gift.diamond_count}`)
});
}).catch(err => {
console.error(err);
})
Proxied Connection
The HTTP layer uses got and the WebSocket layer uses
ws. Both accept a Node http.Agent, which makes
hpagent the recommended proxy integration. hpagent is already a
direct dependency of this package, so no extra install is required.
HTTP Client (got) via webClientOptions
got accepts an agent map keyed by protocol (http, https, http2). Provide proxy agents for each protocol
the connector talks to:
import { TikTokLiveConnection } from 'tiktok-live-connector';
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
const proxy = 'http://user:pwd@host:8080';
const connection = new TikTokLiveConnection('@username', {
webClientOptions: {
agent: {
http: new HttpProxyAgent({ proxy, keepAlive: true }),
https: new HttpsProxyAgent({ proxy, keepAlive: true })
}
}
});
This routes all TikTok web/webcast HTTP traffic (room id, room info, gift list, HTML scrape, sign requests) through the proxy.
WebSocket Client (ws) via wsClientOptions
ws accepts a single agent (a Node http.Agent). Since the WebSocket upgrade goes over wss://, use the
HTTPS variant:
import { TikTokLiveConnection } from 'tiktok-live-connector';
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
const proxy = 'http://user:pwd@host:8080';
const connection = new TikTokLiveConnection('@username', {
webClientOptions: {
agent: {
http: new HttpProxyAgent({ proxy, keepAlive: true }),
https: new HttpsProxyAgent({ proxy, keepAlive: true })
}
},
wsClientOptions: {
agent: new HttpsProxyAgent({ proxy, keepAlive: true })
}
});
// Connect as usual
await connection.connect();
Authenticated Connection
To connect as a specific TikTok account, log into TikTok in your browser and copy two cookies: sessionid and
tt-target-idc. Both are required. sessionid is your account's session token (keep it secret), and
tt-target-idc is the datacenter region your account belongs to (for example useast1a for North America).
Pass them via the session.cookie bundle. To force the WebSocket itself to authenticate (so the server treats you
as that account in chat), also set authenticateWs: true.
import { TikTokLiveConnection } from 'tiktok-live-connector';
const connection = new TikTokLiveConnection(
'tv_asahi_news',
{
signApiKey: 'your-api-key',
authenticateWs: true,
session: {
cookie: {
type: 'cookie',
value: {
sessionId: '<account_session_id>',
ttTargetIdc: '<account_target_idc>'
}
}
}
}
);
await connection.connect();
console.log('Connected to TikTok LIVE chat!');
You can also set the session after construction by calling setSessionBundle on the cookie jar:
await connection.webClient.cookieJar.setSessionBundle({
type: 'cookie',
value: {
sessionId: '<account_session_id>',
ttTargetIdc: '<account_target_idc>'
}
});
Send Messages
sendMessage posts a chat message into the currently connected room. It requires a valid Euler Stream API key
(see Signing Configuration) and an authenticated session bundle (cookies or OAuth token).
import { TikTokLiveConnection } from 'tiktok-live-connector';
const connection = new TikTokLiveConnection(
'tv_asahi_news',
{
signApiKey: 'your-api-key',
authenticateWs: true,
session: {
cookie: {
type: 'cookie',
value: {
sessionId: '<account_session_id>',
ttTargetIdc: '<account_target_idc>'
}
}
}
}
);
await connection.connect();
await connection.sendMessage('Hello world!');
console.log('Message sent!');
Frequently Asked Questions
Is there an official TikTok LIVE API?
TikTok does not offer a public official API for reading livestream events. TikTokLiveConnector is an unofficial, open-source TikTok LIVE API client that reads the same Webcast data available to any viewer of a stream.
How do I read TikTok live chat messages in Node.js?
Install with npm i tiktok-live-connector, create a TikTokLiveConnection with the streamer's @uniqueId, and
listen for WebcastEvent.CHAT. See Getting Started above — it takes about ten lines of code.
Can I track TikTok gifts, likes and viewer counts in real time?
Yes. GIFT (with streak handling), LIKE and ROOM_USER deliver gifts, likes and
live viewer counts as they happen, alongside follows, shares, subscriptions, questions and battles.
Does it work without logging in?
Yes. No credentials, cookies or app registration are required to read a public livestream. Authentication is only needed to send chat messages, which additionally requires a sign API key — see Send Messages.
Is it free?
Yes, the library is free and open source. Connecting requires a signed WebSocket token, provided by Euler Stream with free community rate limits; an API key raises those limits.
Is it production-ready?
The library is a reverse-engineering project and TikTok can change the Webcast protocol without notice. For workloads that need an uptime guarantee, use the managed TikTok LIVE WebSocket API, which handles signing, scaling and protocol drift for you.
Is this available in other languages?
Yes — see Do you prefer other programming languages? for the Python, Java, Go and C# ports.
Contributors
- Zerody - Initial Reverse-Engineering and Protobuf-Decoding - Zerody
- Isaac Kogan - TypeScript Rewrite, Sign-Server Maintainer - isaackogan
- sleepylessons - Docs & QoL Updates - sleepylessons
License
This project is licensed under a modified AGPL License. See the LICENSE file for details.