Skip to content
PirateTokPublic

About

TikTok Live WebSocket connector for Rust — real-time chat, gifts, likes, and 60+ event types. No authentication required.

Resources

Stars

6 stars

Watchers

2 watching

Forks

Latest commit

 

History

32 Commits

Folders and files

Repository files navigation

PirateTok

piratetok-live-rs

Connect to any TikTok Live stream and receive real-time events — chat, gifts, likes, joins, viewer counts, and 64 decoded event types. No signing server, no API keys, no authentication required.

use piratetok_live_rs::TikTokLive;
use piratetok_live_rs::structs::TikTokLiveEvent;

#[tokio::main]
async fn main() {
    // Connect to a live stream — handles auth, room resolution, and WSS automatically
    let mut stream = TikTokLive::builder("username_here")
        .connect()
        .await
        .unwrap();

    // Each event is a fully decoded protobuf message; Err(ConnectionClosed) once the stream is done
    while let Ok(event) = stream.next_event().await {
        match event {
            TikTokLiveEvent::Chat(msg) => {
                let nick = msg.user.as_ref().map_or("?", |u| u.nickname.as_str());
                println!("{nick}: {}", msg.comment);
            }
            TikTokLiveEvent::Gift(msg) => {
                let nick = msg.user.as_ref().map_or("?", |u| u.nickname.as_str());
                let gift = msg.gift_details.as_ref().map_or("gift", |g| g.gift_name.as_str());
                let diamonds = msg.gift_details.as_ref().map_or(0, |g| g.diamond_count);
                println!("{nick} sent {gift} ({diamonds} diamonds)");
            }
            TikTokLiveEvent::Like(msg) => {
                println!("{} total likes", msg.total_like_count);
            }
            TikTokLiveEvent::Disconnected => break,
            _ => {} // 64 decoded event types available
        }
    }
}

Install

[dependencies]
piratetok-live-rs = "0.3"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }

Other languages

Language Install Repo
Go go get github.com/PirateTok/live-go live-go
Python pip install piratetok-live-py live-py
JavaScript npm install piratetok-live-js live-js
C# dotnet add package PirateTok.Live live-cs
Java com.piratetok:live live-java
Lua luarocks install piratetok-live-lua live-lua
Elixir {:piratetok_live, "~> 0.1"} live-ex
Dart dart pub add piratetok_live live-dart
C #include "piratetok.h" live-c
PowerShell Install-Module PirateTok.Live live-ps1
Shell bpkg install PirateTok/live-sh live-sh

Features

  • Zero signing dependency — no API keys, no signing server, no external auth
  • 64 decoded event types — chat, gifts, likes, joins, follows, shares, battles, polls, envelopes, and more
  • Auto-reconnection — stale detection, exponential backoff, self-healing auth
  • Enriched User data — badges, gifter level, moderator status, follow info, fan club, subscriber status
  • Sub-routed convenience events — Follow, Share, Join, LiveEnded fire alongside raw events

Configuration

TikTokLive::builder("username_here")
    .cdn(CdnEndpoint::Eu)        // EU / US / Global (default)
    .timeout(Duration::from_secs(15))
    .heartbeat_interval(Duration::from_secs(10))  // default 10s
    .max_retries(10)             // default 5, 0 to disable
    .stale_timeout(Duration::from_secs(90))  // default 60s
    .proxy("socks5://user:pass@127.0.0.1:1080") // http(s)://, socks5://, socks5h:// (+ user:pass) for HTTP and WSS
    .user_agent("Mozilla/5.0 ...")            // override random UA pool with a fixed UA
    .cookies("sessionid=abc; sid_tt=abc")     // session cookies appended alongside ttwid
    .language("de")              // override auto-detected language (default from system locale)
    .region("DE")                // override auto-detected region (default from system locale)
    .compress(false)             // disable gzip for WSS payloads (default true)
    .connect()
    .await

Room info (optional, separate call)

use piratetok_live_rs::http::api::{fetch_room_info, FetchParams};

// Normal rooms — no cookies needed
let info = fetch_room_info("ROOM_ID", FetchParams::default()).await?;

// 18+ rooms — pass session cookies from browser DevTools
let info = fetch_room_info("ROOM_ID", FetchParams {
    cookies: Some("sessionid=abc; sid_tt=abc"), ..Default::default()
}).await?;

Who's watching (viewer names)

Two sources, matching what the web/phone app shows:

// 1. Top-viewers box (the top-3 next to the counter) — free with WSS, no cookies
TikTokLiveEvent::RoomUserSeq(msg) => {
    for c in msg.top_viewers() {
        if let Some(u) = &c.user {
            println!("#{} {} score={}", c.rank, u.nickname, c.score);
        }
    }
}
// 2. Full roster (every named viewer in the room) — HTTP, login-gated
use piratetok_live_rs::http::api::{fetch_room_id, fetch_room_audience, AnchorId, FetchParams};

let room = fetch_room_id("username", FetchParams::default()).await?;
let audience = fetch_room_audience(&room.room_id, AnchorId::Known(&room.anchor_id), FetchParams {
    cookies: Some("sessionid=abc; sid_tt=abc"), ..Default::default()
}).await?;
println!("{} in room ({} anonymous)", audience.total, audience.anonymous);
for v in &audience.viewers {
    println!("#{} @{} ({}) score={}", v.rank, v.username, v.nickname, v.score);
}

The roster endpoint needs session cookies (TikTok gates it behind login) but no signing — no msToken, no X-Bogus. Without cookies it returns TikTokLiveError::SessionRequired.

Errors from fetch_room_id / connect

Condition Error
statusCode 19881007 UserNotFound(username)
user exists, no active room / status ≠ 2 HostNotOnline
other non-zero statusCode ApiError(code)
HTTP 403/429, empty or non-JSON body TikTokBlocked(reason)

Gift streaks

TikTokLiveEvent::Gift(gift) => {
    if gift.is_combo_gift() {
        if gift.is_streak_over() {
            println!("x{} = {} diamonds", gift.repeat_count, gift.diamond_total());
        }
    } else {
        println!("{} diamonds", gift.diamond_total());
    }
}

How it works

  1. Resolves username to room ID via TikTok JSON API
  2. Authenticates and opens a direct WSS connection
  3. Sends protobuf heartbeats every 10s to keep alive
  4. Decodes protobuf event stream into typed Rust structs
  5. Auto-reconnects on stale/dropped connections

All protobuf structs are hand-written with prost derive macros — no .proto files, no codegen, no build-time protoc dependency.

Reconnection

  • TikTok only sets the ttwid cookie on some anonymous requests, so a cookie-less response is retried up to 8 times (750 ms apart). A ttwid that still can't be fetched counts as a failed attempt and goes through the normal backoff. It never kills the stream.
  • The ttwid + user agent pair is reused across reconnects. It's rotated on DEVICE_BLOCKED (2 s delay) and after a connection that dies within 30 s.
  • Backoff is 2 s → 4 s → 8 s → 16 s → 30 s cap. max_retries counts consecutive failures: a session that stayed up for 30 s resets the budget.

Full API reference (builder, config, stream, errors): docs/API.md.

CLI

cp .env.example .env          # TIKTOK_USERNAME=..., optional TIKTOK_COOKIES=...
cargo run --features cli
cargo run --features cli -- --username tiktok --room-info
RUST_LOG=debug cargo run --features cli -- -u tiktok   # verbose protocol logging

Examples

cargo run --example basic_chat -- <username>        # connect + print chat events
cargo run --example online_check -- <username>      # check if user is live
cargo run --example stream_info -- <username>       # fetch room metadata + stream URLs
cargo run --example gift_tracker -- <username>      # track gifts with diamond totals
cargo run --example gift_streak -- <username>       # per-event gift deltas via GiftStreakTracker
cargo run --example profile_lookup -- <username>    # look up profile data + HD avatars
cargo run --example audience -- <username> [cookies] # viewer names: top-3 box + full roster
cargo run --example like_debug -- <username>        # debug like event patterns

Replay testing

Deterministic cross-lib validation against binary WSS captures. Requires testdata from a separate repo:

git clone https://github.com/PirateTok/live-testdata testdata
cargo test

Tests skip gracefully if testdata is not found. You can also set PIRATETOK_TESTDATA to point to a custom location.

License

0BSD

About

TikTok Live WebSocket connector for Rust — real-time chat, gifts, likes, and 60+ event types. No authentication required.

Resources

Stars

6 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages