Build a TikTok LIVE chat bot
Read every chat, gift, and join event from any TikTok LIVE stream. Reply with commands. Run in Node.js or Python with under 60 lines of code.
Install the SDK
One package. No build step. Works in any Node 18+ or Python 3.9+ environment.
npm install tiktok-live-apiSet your credentials
You need two things:
- API key - from your dashboard. The free tier is fine for one stream.
- TikTok login cookies - only required if your bot will send chat. Reading events needs nothing else.
To get your TikTok cookies: open tiktok.com in a logged-in browser, open DevTools → Application → Cookies, copy every cookie as a name=value; string into TIKTOK_COOKIES.
export TIKTOOL_API_KEY="tk_yourkey"
export TIKTOK_USERNAME="target_streamer"
export TIKTOK_COOKIES="sessionid=...; sessionid_ss=...; ttwid=...; msToken=..."Write the bot
Listens for chat, gifts, joins, likes. Responds to !hello and !ping commands.
// bot.mjs
import { TikTokLive } from 'tiktok-live-api'
const USERNAME = process.env.TIKTOK_USERNAME
const API_KEY = process.env.TIKTOOL_API_KEY
const COOKIES = process.env.TIKTOK_COOKIES
async function reply(roomId, text) {
const r = await fetch('https://api.tik.tools/webcast/chat', {
method: 'POST',
headers: { 'content-type': 'application/json', 'x-api-key': API_KEY, 'x-cookie-header': COOKIES },
body: JSON.stringify({ room_id: String(roomId), text, unique_id: USERNAME }),
}).then(r => r.json())
if (!r.signed_url) return console.warn('sign failed:', r.error)
const out = await fetch(r.signed_url, {
method: 'POST',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36',
'content-type': 'application/json; charset=UTF-8',
'origin': 'https://www.tiktok.com', 'referer': 'https://www.tiktok.com/',
cookie: COOKIES,
},
body: r.body,
}).then(r => r.json())
if (out.status_code === 0) console.log(`>> replied: ${text}`)
}
const client = new TikTokLive(USERNAME, { apiKey: API_KEY })
let roomId = null
client.on('connected', e => { roomId = e.roomId })
client.on('chat', async e => {
console.log(`@${e.user.uniqueId}: ${e.comment}`)
if (e.comment.toLowerCase() === '!hello') await reply(roomId, `hi @${e.user.uniqueId} 👋`)
if (e.comment.toLowerCase() === '!ping') await reply(roomId, 'pong 🏓')
})
client.on('gift', e => console.log(`gift: ${e.user.uniqueId} → ${e.giftName} (${e.diamondCount}💎)`))
client.connect()Run it
The bot stays connected until you stop it. Reconnect logic is built into the SDK.
node bot.mjsType !hello or !ping from any TikTok account into the streamer's chat and your bot replies as your account.
Limitations to plan around
Everything below is what TikTok enforces on your account/IP - not something tik.tools can lift. Build your bot logic with these in mind.
chat sends per 3 min
Per-IP edge limit. Hitting it returns HTTP 403 with empty body and locks chat send for ~15-20 min. Mitigation: throttle to 1 send per 5-10 seconds, watch the X-RateLimit-* headers we return.
required to send chat
Reading events needs no TikTok account. Sending chat needs full cookies (sessionid, ttwid, msToken, etc.) from a logged-in browser session. The cookies expire periodically - rotate them when chat starts failing.
some streams restrict chat
Creators can disable comments, restrict to followers, or shadow-mute accounts. TikTok returns status_code=4010048 when this happens. The send looks successful but the message never appears in the public chat.
events per stream per minute
Big creators (1M+ viewers) push tens of thousands of events per minute. Your bot needs to process them lazily - don't block the event loop on every chat. Drop or queue heavy work.
session ends with the LIVE
When the streamer ends their LIVE, the WebSocket closes. The SDK fires disconnected. Reconnect after the streamer goes live again - poll tik.tools/api/live/check-live or use webhooks.
not endorsed by TikTok
This is an unofficial integration. Use a dedicated TikTok account for the bot, don't mix it with your main, and don't impersonate creators. TikTok may suspend the account if the bot looks like spam.