Package Exports
- @tiktool/live
Readme
@tiktool/live
TikTok LIVE API SDK for Node.js, Bun, Deno, and Cloudflare Workers
Real-time TikTok LIVE events — chat messages, gifts, follows, likes, battles, viewer counts, and 18+ event types — streamed directly to your application via WebSocket.
Quick Start · Events · REST API · Pricing · Get API Key
Why @tiktool/live?
- Direct WebSocket connection to TikTok from your own IP — events are never proxied through third-party servers
- Zero dependencies — built-in protobuf parser, universal WebSocket resolution, gzip decompression
- Universal runtime support — Node.js 18+, Bun, Deno, Cloudflare Workers, Durable Objects, and browsers
- Full TypeScript — complete type definitions for all 18+ event types with IDE autocompletion
- Battle-tested — production-ready with auto-reconnect, heartbeat management, and error recovery
- Generous free tier — 30 requests/min, 3 concurrent WebSocket connections, all endpoints included
⚡ Quick Start
npm install @tiktool/liveGet your free API key at tik.tools — all endpoints are accessible on the free tier.
import { TikTokLive } from '@tiktool/live';
const live = new TikTokLive({
uniqueId: 'username',
apiKey: 'YOUR_API_KEY',
});
live.on('chat', e => console.log(`${e.user.uniqueId}: ${e.comment}`));
live.on('gift', e => console.log(`${e.user.uniqueId} sent ${e.giftName} (${e.diamondCount}💎)`));
live.on('member', e => console.log(`${e.user.uniqueId} joined the stream`));
live.on('roomUserSeq', e => console.log(`Viewers: ${e.viewerCount}`));
await live.connect();Architecture
Your App api.tik.tools TikTok
+-----------+ +--------------+ +--------------+
| |-- sign_url --> Signs URL | | |
| SDK |<-- X-Bogus --| (1 req) | | WebSocket |
| | | | | Server |
| |------------- Connect directly --------->| |
| |<------------ Live events (protobuf) <---| |
+-----------+ +--------------+ +--------------+
^ Only signing ^ Direct from
touches our API YOUR IPThe SDK calls the sign server once per connection to generate a cryptographic signature, then connects directly to TikTok's WebSocket server from your IP address. All event data flows directly between your app and TikTok — never through our infrastructure.
📡 Events
live.on('chat', (event) => {
event.user.uniqueId; // string
event.user.nickname; // string
event.comment; // string
});
live.on('event', (event) => {
console.log(event.type, event);
});Event Reference
| Event | Type | Description | Key Fields |
|---|---|---|---|
chat |
ChatEvent |
Chat message received | user, comment, emotes |
member |
MemberEvent |
User joined the stream | user, action |
like |
LikeEvent |
User liked the stream | user, likeCount, totalLikes |
gift |
GiftEvent |
Gift sent to streamer | user, giftName, diamondCount, repeatCount, combo |
social |
SocialEvent |
Follow or share event | user, action ('follow' / 'share') |
roomUserSeq |
RoomUserSeqEvent |
Viewer count update | viewerCount, totalViewers |
battle |
BattleEvent |
Battle started/ended | battleId, status, teams |
battleArmies |
BattleArmiesEvent |
Battle scores update | battleId, teams (with scores) |
subscribe |
SubscribeEvent |
New subscriber | user, subMonth |
emoteChat |
EmoteChatEvent |
Emote message | user, emoteId, emoteUrl |
envelope |
EnvelopeEvent |
Treasure chest | envelopeId, diamondCount |
question |
QuestionEvent |
Q&A question | user, questionText |
control |
ControlEvent |
Stream control signal | action (3 = stream ended) |
room |
RoomEvent |
Room status change | status |
liveIntro |
LiveIntroEvent |
Stream intro displayed | roomId, title |
rankUpdate |
RankUpdateEvent |
Ranking update | rankType, rankList |
linkMic |
LinkMicEvent |
Link Mic event | action, users |
unknown |
UnknownEvent |
Unrecognized message | method |
Connection Events
| Event | Callback | Description |
|---|---|---|
connected |
() => void |
Successfully connected to the livestream |
disconnected |
(code, reason) => void |
Disconnected from the livestream |
roomInfo |
(info: RoomInfo) => void |
Room metadata received |
error |
(error: Error) => void |
Connection or parsing error |
🌐 REST API Endpoints
The sign server at api.tik.tools exposes a full REST API alongside WebSocket signing. All endpoints are accessible on every tier — higher tiers unlock increased rate limits and concurrent connections.
| Endpoint | Description |
|---|---|
POST /webcast/sign_url |
Generate X-Bogus signed URL |
GET /webcast/check_alive |
Check if a user is currently live |
GET /webcast/room_info |
Detailed room metadata (title, viewers, streamer info) |
GET /webcast/room_id |
Resolve username to room ID |
GET /webcast/room_cover |
Get stream cover image URL |
GET /webcast/room_video |
Get HLS/FLV stream URLs |
GET /webcast/rankings |
In-stream contribution rankings |
GET /webcast/gift_info |
Available gifts and diamond values |
GET /webcast/hashtag_list |
Trending live hashtags |
GET /webcast/bulk_live_check |
Check multiple users' live status in one request |
POST /webcast/fetch |
Fetch protobuf messages via HTTP polling |
GET /webcast/ws_credentials |
Get WebSocket connection credentials |
POST /webcast/sign_websocket |
Sign a WebSocket URL |
GET /webcast/resolve_user_ids |
Resolve display names to user IDs |
POST /webcast/chat |
Send chat messages (requires session cookies) |
GET /webcast/user_earnings |
Streamer earnings data (requires session cookies) |
GET /webcast/feed |
Live feed discovery |
GET /webcast/live_analytics/* |
Video list, video detail, user interactions |
GET /webcast/moderation/* |
Mute and ban management |
POST /authentication/jwt |
Generate scoped JWT for frontend WebSocket access |
Full API documentation: tik.tools/docs
💰 Pricing
All plans include access to every endpoint. Higher tiers unlock increased throughput.
| Free | Pro | Ultra | |
|---|---|---|---|
| Price | Free forever | $29/mo | $99/mo |
| Rate Limit | 30 req/min | 120 req/min | 300 req/min |
| WebSocket Connections | 3 concurrent | 50 concurrent | 500 concurrent |
| Bulk Live Check | 5 users/req | 50 users/req | 100 users/req |
| Support | Community | Priority | Dedicated |
Get your API key at tik.tools.
Examples
Chat Bot
import { TikTokLive } from '@tiktool/live';
const live = new TikTokLive({
uniqueId: 'streamer_name',
apiKey: 'YOUR_API_KEY',
});
live.on('chat', (e) => {
if (e.comment.toLowerCase() === '!hello') {
console.log(`Hello, ${e.user.nickname}!`);
}
});
live.on('gift', (e) => {
if (e.repeatEnd) {
const total = e.diamondCount * e.repeatCount;
console.log(`${e.user.uniqueId} sent ${e.repeatCount}x ${e.giftName} (${total} diamonds)`);
}
});
await live.connect();Real-Time OBS Overlay
import { TikTokLive } from '@tiktool/live';
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
const live = new TikTokLive({
uniqueId: 'streamer_name',
apiKey: 'YOUR_API_KEY',
});
live.on('event', (event) => {
for (const client of wss.clients) {
client.send(JSON.stringify(event));
}
});
await live.connect();
console.log('Forwarding TikTok LIVE events → ws://localhost:8080');Gift Leaderboard
import { TikTokLive, GiftEvent } from '@tiktool/live';
const live = new TikTokLive({
uniqueId: 'streamer_name',
apiKey: 'YOUR_API_KEY',
});
const leaderboard = new Map<string, number>();
live.on('gift', (e: GiftEvent) => {
if (e.repeatEnd) {
const total = e.diamondCount * e.repeatCount;
const current = leaderboard.get(e.user.uniqueId) || 0;
leaderboard.set(e.user.uniqueId, current + total);
const sorted = [...leaderboard.entries()].sort((a, b) => b[1] - a[1]);
console.clear();
console.log('🏆 Gift Leaderboard');
sorted.slice(0, 10).forEach(([user, diamonds], i) => {
console.log(`${i + 1}. ${user}: ${diamonds} 💎`);
});
}
});
await live.connect();Battle Monitor
import { TikTokLive } from '@tiktool/live';
const live = new TikTokLive({
uniqueId: 'streamer_name',
apiKey: 'YOUR_API_KEY',
});
live.on('battle', (e) => {
console.log(`Battle ${e.battleId} — Status: ${e.status}`);
for (const team of e.teams) {
console.log(` Team ${team.hostUserId}: ${team.score} points (${team.users.length} members)`);
}
});
live.on('battleArmies', (e) => {
for (const team of e.teams) {
const host = team.hostUser?.uniqueId || team.hostUserId;
console.log(` ${host}: ${team.score} points`);
}
});
await live.connect();Frontend JWT Authentication
const data = await fetch('https://tik.tools/api/live/connect?uniqueId=streamer')
.then(r => r.json());
const ws = new WebSocket(`${data.wsUrl}?uniqueId=streamer&jwtKey=${data.token}`);
ws.onmessage = (event) => {
const parsed = JSON.parse(event.data);
console.log(parsed.type, parsed);
};🔧 Configuration
new TikTokLive(options)
| Option | Type | Default | Description |
|---|---|---|---|
uniqueId |
string |
— | TikTok username (without @) |
apiKey |
string |
— | API key from tik.tools |
signServerUrl |
string |
https://api.tik.tools |
Custom sign server URL |
autoReconnect |
boolean |
true |
Auto-reconnect on disconnect |
maxReconnectAttempts |
number |
5 |
Maximum reconnect attempts |
heartbeatInterval |
number |
10000 |
Heartbeat interval in milliseconds |
debug |
boolean |
false |
Enable debug logging |
webSocketImpl |
any |
Auto-detected | Custom WebSocket implementation |
Instance Properties
| Property | Type | Description |
|---|---|---|
connected |
boolean |
Current connection status |
eventCount |
number |
Total events received |
roomId |
string |
Active room ID |
Instance Methods
| Method | Returns | Description |
|---|---|---|
connect() |
Promise<void> |
Connect to a livestream |
disconnect() |
void |
Gracefully disconnect |
on(event, handler) |
this |
Listen for events |
once(event, handler) |
this |
Listen for a single event |
off(event, handler) |
this |
Remove event listener |
TypeScript
Full TypeScript support with generic type inference on all event handlers:
import { TikTokLive, ChatEvent, GiftEvent, BattleEvent } from '@tiktool/live';
const live = new TikTokLive({
uniqueId: 'username',
apiKey: 'YOUR_API_KEY',
});
live.on('chat', (event: ChatEvent) => {
const username: string = event.user.uniqueId;
const message: string = event.comment;
});
live.on('gift', (event: GiftEvent) => {
const diamonds: number = event.diamondCount;
const isCombo: boolean = event.combo;
});
live.on('battle', (event: BattleEvent) => {
const teams: typeof event.teams = event.teams;
const score: number = teams[0].score;
});All event types, user interfaces, and configuration options are fully exported for use in your application's type system.
Runtime Compatibility
| Runtime | Version | WebSocket | Notes |
|---|---|---|---|
| Node.js | ≥ 22 | Native | No additional packages needed |
| Node.js | 18–21 | ws package |
npm i ws |
| Bun | ≥ 1.0 | Native | Full support |
| Deno | ≥ 1.x | Native | Full support |
| Cloudflare Workers | — | Native | Full support |
| Browsers | Modern | Native | Via bundled connect endpoint |
License
MIT © TikTool