# TikTok Live Scraper (`khadinakbar/tiktok-live-scraper`) Actor

TikTok LIVE scraper — is-live check by username, full live-room metadata + viewer count + stream URLs, real-time chat & gifts feed, and currently-live creator discovery. Auto-detects mode from input. No cookies, no login. MCP-ready.

- **URL**: https://apify.com/khadinakbar/tiktok-live-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Social media, Automation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 live result (status / room / discover)s

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## TikTok Live Scraper

**All-in-one TikTok LIVE data tool.** Check who is currently broadcasting, get full live-room metadata (viewers, title, hashtag, paid-event flag, stream URLs), capture the real-time chat + gifts + joins + likes feed, or discover currently-live rooms by category and region. Auto-detects mode from input. No cookies, no login, no browser extension. MCP-ready for AI agents.

### What it does

This actor exposes four TikTok LIVE workflows behind one input schema and one dataset. The mode is detected automatically from which fields you fill in.

| Mode | Trigger | Returns |
|---|---|---|
| **Live status** | `usernames: ["..."]` | One record per handle with `isLive`, `roomId`, `viewerCount`, `roomTitle`, `startedAt`, follower stats |
| **Room details** | `liveRoomUrls: ["..."]` | One record per live room (`tiktok.com/@user/live` or numeric roomId) with the full room object |
| **Chat + gifts feed** | `chatFeedUsername: "..."` | One record per real-time chat / gift / join / like / social event for `chatCaptureSeconds` seconds |
| **Discover currently-live** | `discoverCategory: "gaming"` | List of currently-broadcasting rooms in that category for `discoverRegion` |

It uses public data only. You never supply TikTok credentials, session cookies, or device tokens. Live-status and room-details are powered by managed providers (ScrapeCreators primary, SociaVault fallback). Chat capture connects directly to the public TikTok WebSocket. Discovery uses residential proxies via Playwright.

### When to use it

- Brand monitoring: know the second a creator goes live.
- Influencer / talent scouting: scan currently-broadcasting rooms in a niche.
- Live-shopping analytics: capture comments and gift volume during a live drop.
- Creator-tools / bot building: feed real-time chat into Streamlabs-style dashboards.
- AI agents that watch livestreams: a single MCP tool covers monitoring, room metadata, and chat capture.

**Not for:** past video transcripts (use `tiktok-transcript-scraper`), trending VODs (use `tiktok-trending-videos-scraper`), or scraping past live recordings — TikTok does not expose a stable public archive of past LIVEs.

### Output

One dataset with `recordType` discriminating the four modes. Common fields:

| Field | Description |
|---|---|
| `recordType` | `live-status` | `room-details` | `discover-live` | `chat-event` |
| `username` | TikTok @handle (lowercase, no @ prefix) |
| `userId` | TikTok numeric user ID |
| `nickname` | Display name of the creator |
| `verified` | Verification flag |
| `avatarUrl` | Avatar image URL |
| `followerCount` | Follower count at scrape time |
| `isLive` | True if currently broadcasting (live-status / room-details modes) |
| `roomId` | TikTok live roomId (numeric string) |
| `roomTitle` | Live room title set by the creator |
| `coverUrl` | Live cover image URL |
| `viewerCount` | Current concurrent viewers |
| `totalEnterCount` | Cumulative viewers since stream start |
| `startedAt` | ISO 8601 timestamp the stream started |
| `hashTag` | Primary hashtag associated with the live |
| `isPaidEvent` / `isSubOnly` | Paid-ticketed and sub-only flags |
| `liveUrl` | Public TikTok URL of the live room |
| `streamUrls` | Object with HLS/FLV stream URLs at multiple quality levels |
| `chatEventType` | `chat` | `gift` | `member` | `like` | `social` (chat-feed mode) |
| `chatText` | Comment text (chat events) |
| `giftName`, `giftCount`, `giftDiamondValue`, `giftTotalDiamonds` | Gift event fields |
| `fromUsername`, `fromNickname` | Sender of chat/gift events |
| `chatTimestamp` | ISO 8601 timestamp of the chat event |
| `discoverRank` | Position on the discovery page (1-based) |
| `source` | `scrapecreators` | `sociavault` | `tiktok-ws` | `tiktok-discover` |
| `status` | `ok` | `not_live` | `not_found` | `provider_error` | `discover_blocked` | `chat_disconnected` |
| `note` | Human-readable detail for non-`ok` records |
| `scrapedAt` | ISO 8601 extraction timestamp |

#### Example: live-status record

```json
{
  "recordType": "live-status",
  "username": "stoolpresidente",
  "userId": "6701106726838632965",
  "nickname": "Dave Portnoy",
  "verified": true,
  "isLive": true,
  "roomId": "7398765432109876543",
  "roomTitle": "Pizza Review LIVE",
  "viewerCount": 4523,
  "totalEnterCount": 18450,
  "startedAt": "2026-06-27T03:10:00.000Z",
  "followerCount": 4321000,
  "liveUrl": "https://www.tiktok.com/@stoolpresidente/live",
  "source": "scrapecreators",
  "status": "ok",
  "scrapedAt": "2026-06-27T03:42:11.000Z"
}
```

#### Example: chat-event record

```json
{
  "recordType": "chat-event",
  "username": "stoolpresidente",
  "chatEventType": "gift",
  "giftName": "Rose",
  "giftCount": 5,
  "giftDiamondValue": 1,
  "giftTotalDiamonds": 5,
  "fromUsername": "fanofdave",
  "fromNickname": "Fan",
  "chatTimestamp": "2026-06-27T03:42:14.000Z",
  "source": "tiktok-ws",
  "status": "ok",
  "scrapedAt": "2026-06-27T03:42:14.000Z"
}
```

### Input

```json
{
  "usernames": ["stoolpresidente", "khaby.lame"]
}
```

Or one of:

```json
{ "liveRoomUrls": ["https://www.tiktok.com/@stoolpresidente/live"] }
{ "chatFeedUsername": "stoolpresidente", "chatCaptureSeconds": 120 }
{ "discoverCategory": "gaming", "discoverRegion": "US", "maxDiscoverResults": 50 }
```

- **usernames** — TikTok @handles or profile URLs for is-live checks.
- **liveRoomUrls** — Live room URLs (`tiktok.com/@user/live`) or numeric roomIds.
- **chatFeedUsername** — Single handle whose live chat/gifts will be captured.
- **chatCaptureSeconds** (default 60, range 10-1800) — How long to listen on the chat WebSocket.
- **chatEventTypes** (default `["chat","gift"]`) — Which event classes to push (add `member`, `like`, `social` if you want them).
- **discoverCategory** — Category slug to list currently-live rooms (`gaming`, `music`, `lifestyle`, …).
- **discoverRegion** (default `US`) — ISO country for residential proxy region in discover mode.
- **maxDiscoverResults** (default 50, range 1-200) — cap on discovery results.
- **maxResults** (default 100, range 1-1000) — cap on live-status + room-details records.

### Pricing

Pay-per-event:

- **Actor start** — $0.00005 per run.
- **Live result** — **$0.005 per result** (any of: live-status check, room-details record, discovered live room).
- **Chat / gift event** — **$0.0002 per event** captured from the live WebSocket.

Every run logs an upfront cost cap and prints the final billed amount in the status message. Pay-Per-Usage (compute + proxy passthrough) is also enabled for heavy users.

### How it works

1. The actor detects the mode from your input (live-status / room-details / chat-feed / discover-live).
2. **Live-status / room-details**: calls ScrapeCreators' `/v1/tiktok/user/live` (or `/v1/tiktok/live`) first; falls back to SociaVault's `/v1/scrape/tiktok/live` on miss. Normalizes both shapes to one schema.
3. **Chat-feed**: connects to the creator's public TikTok webcast WebSocket (no cookies) via `tiktok-live-connector`, emits one record per chat/gift/join/like/social event for up to `chatCaptureSeconds`, then disconnects. Stops early if the stream ends.
4. **Discover-live**: opens TikTok's `/live/discover` page with a residential proxy pinned to the requested region using Playwright, parses the SSR data blob or DOM cards, and pushes one record per live room.

### Reliability notes

- **No cookies required** — public data only.
- **Provider redundancy** — one provider down does not break is-live / room-details modes.
- **Graceful degradation** — not-live, not-found, and chat-not-connected return labeled records, not crashes.
- **Honest failure** — if every provider call fails at the network level, the run is marked failed with a clear message rather than silently succeeding empty.
- **Residential proxy** — discover mode automatically uses Apify Residential with the requested country code.

### MCP / AI-agent ready

One MCP-discoverable tool `apify--tiktok-live-scraper` exposes all four modes. Input descriptions are written for LLM tool-selection (when to use, what NOT to use it for). Output fields are flat, semantically named, and stable across runs.

### FAQ

**Q: Can I capture chat from a creator who isn't currently live?**
No. The WebSocket only exists while the room is broadcasting. The actor returns a `chat_disconnected` record with a clear note when the room is offline.

**Q: Does this return past LIVEs / replays?**
No. TikTok does not expose a stable public archive of past LIVEs. For past TikTok videos see `tiktok-trending-videos-scraper` or `tiktok-transcript-scraper`.

**Q: Can I run multiple `usernames` + chat capture in one run?**
No — chat capture is a single-creator, long-running operation. Run a separate task per creator if you need multiple chat captures.

**Q: How accurate is the viewer count?**
It is a snapshot of TikTok's reported `liveRoomStats.userCount` at the moment of the call. To watch it over time, schedule the actor on a 1-5 minute interval.

**Q: Discover mode returns zero rooms — why?**
TikTok occasionally rate-limits or A/B-tests the `/live/discover` surface. Retry, switch `discoverRegion`, or pick a different category. The actor returns a `discover_blocked` record instead of crashing.

### Legal

Use only for publicly available TikTok LIVE data. You are responsible for complying with TikTok's Terms of Service, applicable copyright, and data-protection law (including GDPR/CCPA) in your jurisdiction. This actor does not access private accounts, login-gated content, or paid-event content behind the paywall.

# Actor input Schema

## `usernames` (type: `array`):

List of TikTok @handles to check live status for (e.g. \['stoolpresidente', 'khaby.lame']). Bare handles or full profile URLs both accepted. Returns one record per handle with isLive, roomId, title, viewerCount, startedAt, streamUrls. Use this for is-live monitoring of known creators. NOT for one-off live-room URL inspection (use 'liveRoomUrls') or chat capture (use 'chatFeedUsername').

## `liveRoomUrls` (type: `array`):

List of TikTok live room URLs like 'https://www.tiktok.com/@user/live' or bare numeric roomIds. Returns the full live-room object (title, viewers, streamData, hashTag, paidEvent flag). Use this when you have direct room URLs from elsewhere; for username-only is-live checks use 'usernames'.

## `chatFeedUsername` (type: `string`):

Single TikTok @handle whose live chat/gifts/joins/likes will be captured for 'chatCaptureSeconds' seconds via WebSocket (no cookies). The creator must be live when the run starts. One event per comment/gift/member-join/like is pushed to the dataset. Charged at $0.0002 per event. NOT for is-live polling (use 'usernames').

## `chatCaptureSeconds` (type: `integer`):

How long to listen on the live chat WebSocket before closing. Defaults to 60 seconds. Range 10-1800. Only used when 'chatFeedUsername' is set. Longer captures cost more (one PPE event per chat/gift/join/like message). Run also stops early if the creator ends the stream.

## `chatEventTypes` (type: `array`):

Which WebSocket event classes to push. Defaults to \['chat','gift'] (the high-signal ones). Add 'member' for join notifications and 'like' for like bursts (verbose). 'social' = follows/shares.

## `discoverCategory` (type: `string`):

Category slug to list currently-broadcasting rooms (e.g. 'gaming', 'lifestyle', 'music'). Uses tiktok.com/live discovery via Playwright + residential proxy. Returns list of live rooms with creator handle, title, viewer count. Leave blank when not in discover mode.

## `discoverRegion` (type: `string`):

Two-letter ISO country code for residential proxy region when discovering live rooms (e.g. 'US', 'GB', 'JP'). Defaults to 'US'. Only used in discover mode.

## `maxDiscoverResults` (type: `integer`):

Hard cap on currently-live rooms returned by discover mode. Default 50, range 1-200. Higher = more compute + proxy cost.

## `maxResults` (type: `integer`):

Hard cap on records pushed by live-status + room-details modes (does NOT cap chat-feed events — use 'chatCaptureSeconds'). Default 100, range 1-1000.

## Actor input object example

```json
{
  "usernames": [
    "stoolpresidente",
    "khaby.lame"
  ],
  "liveRoomUrls": [
    "https://www.tiktok.com/@stoolpresidente/live"
  ],
  "chatFeedUsername": "stoolpresidente",
  "chatCaptureSeconds": 60,
  "chatEventTypes": [
    "chat",
    "gift"
  ],
  "discoverCategory": "",
  "discoverRegion": "US",
  "maxDiscoverResults": 50,
  "maxResults": 100
}
```

# Actor output Schema

## `records` (type: `string`):

All live-status / room-details / chat-event / discover-live records pushed during this run.

## `summary` (type: `string`):

Counts per recordType, charged event counts, billed amount.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "usernames": [
        "stoolpresidente"
    ],
    "chatCaptureSeconds": 60,
    "chatEventTypes": [
        "chat",
        "gift"
    ],
    "discoverRegion": "US",
    "maxDiscoverResults": 50,
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/tiktok-live-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "usernames": ["stoolpresidente"],
    "chatCaptureSeconds": 60,
    "chatEventTypes": [
        "chat",
        "gift",
    ],
    "discoverRegion": "US",
    "maxDiscoverResults": 50,
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/tiktok-live-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "usernames": [
    "stoolpresidente"
  ],
  "chatCaptureSeconds": 60,
  "chatEventTypes": [
    "chat",
    "gift"
  ],
  "discoverRegion": "US",
  "maxDiscoverResults": 50,
  "maxResults": 100
}' |
apify call khadinakbar/tiktok-live-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=khadinakbar/tiktok-live-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/bspeSQGxXQJBrCZiV/builds/jdn1whZyHUgoZrT1Q/openapi.json
