# TikTok Live Scraper — rooms, viewers, streams (`mu0i/tiktok-live-scraper`) Actor

Find live TikTok rooms by keyword with playable HLS/FLV/DASH stream links, check whether specific creators are live, or re-check a watchlist of rooms.

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

## Pricing

from $2.70 / 1,000 live rooms

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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 — rooms, viewers, streams

Find live TikTok rooms by keyword and get **playable stream links** — HLS, FLV and DASH — plus the stream title,
viewer count and host. Or check whether specific creators are live right now. Or re-check a watchlist of rooms
in a single request.

No login, no cookies, no browser.

### The stream links are real, and they are checked

Each room comes with its full quality ladder. The links are fetched and verified, not just passed along:

| | |
|---|---|
| `recommendedHlsUrl` | returns `200 application/x-mpegURL` and a real `#EXTM3U` playlist — paste it into a browser player, ffmpeg or VLC |
| `flvOriginUrl` | returns `200 video/x-flv` with real FLV magic bytes — this is what TikTok's own app pulls |
| `dash` | returns `200 application/dash+xml`, a real MPD |
| `flvAudioOnlyUrl` | audio-only pull, for transcription or monitoring without the video bandwidth |

**Why `recommendedHlsUrl` exists rather than just handing you the ladder.** TikTok's HLS `origin` quality
returns **404** — reproducibly, on every room tested — while `uhd_60`, `hd_60`, `hd`, `sd` and `ld` all serve
properly. `origin` is exactly the key you would reach for first, so this Actor picks the best quality that
actually works and tells you which one it chose in `recommendedHlsQuality`.

**Prefer HLS or DASH over FLV.** The FLV pull is HEVC/H.265, which most players and every browser refuse. HLS
and DASH are what will actually play. When a room has no HLS the row says so and points you at the FLV links.

### One page per keyword — a real limit, stated up front

TikTok's live search returns **one page**. Any offset above zero returns an empty list, while the response still
reports `has_more: 1` and advances its own cursor — so it looks like working pagination and is not. The ceiling
is therefore **30 rooms per keyword**; use more keywords for more rooms.

The input schema caps `maxRoomsPerKeyword` at 30 rather than accepting a number it cannot honour.

### How to use

1. Click **Try for free** at the top of this page. Apify creates a free account if you do not have one — no card is needed to run this.
2. Put what you want scraped into **Keywords** — one per line.
3. Set **Max rooms per keyword** to bound the run, then press **Start**. You are billed per row, so this field is also your budget.
4. Rows show up in the **Dataset** tab *while the run is still going*. Export to JSON, CSV, Excel or XML from there, or read them over the API.

Live rooms end. Rows carry `expiresAt` for the stream links, and re-checking a list of `roomIds` later is the cheap way to poll.

### Three ways in, combinable in one run

Every field, with its default — paste the whole block and delete what you do not need:

```json
{
  "keywords": [
    "gaming"
  ],
  "maxRoomsPerKeyword": 20,
  "creators": [],
  "roomIds": [],
  "streamFormats": [
    "hls",
    "flv"
  ]
}
```

| input | what it gives you |
|---|---|
| `keywords` | up to 30 live rooms each, **with stream links**, titles and viewer counts |
| `creators` | one row per creator: are they streaming, and in which room. Handles, URLs or numeric IDs |
| `roomIds` | one request re-checks the whole list — the cheap way to poll rooms from an earlier run |
| `maxRoomsPerKeyword` | caps each keyword's search. Default 30, which is also as deep as one page goes |
| `streamFormats` | which stream links to include. Default **HLS + FLV** |

On `streamFormats`: **HLS** (`.m3u8`) plays in browsers and in ffmpeg or VLC and is the one to keep if you
only keep one. **FLV** is what TikTok's own app pulls, and it is HEVC — many players cannot decode it.
**DASH** (`.mpd`) is the browser-native alternative to HLS and is off by default.

Stream links come only from keyword search. A creator check tells you they are live and gives you the room ID;
the row says so plainly rather than leaving you to wonder where the links went.

### Output

Every row carries `source` (`search`, `creator` or `roomCheck`) so mixed runs stay readable.

| field | |
|---|---|
| `roomId`, `title`, `viewers`, `isLive` | |
| `ownerUsername`, `ownerNickname`, `ownerId`, `ownerSecUid`, `profileUrl`, `liveUrl` | |
| `qualities[]` | every quality the room offers |
| `recommendedHlsUrl`, `recommendedHlsQuality` | the HLS link that works |
| `hls`, `flv`, `dash` | the full ladders, per format you asked for |
| `flvOriginUrl`, `flvAudioOnlyUrl` | |
| `expiresAt` | when the link signatures lapse |
| `keyword`, `note` | which term found it, and anything worth knowing |

One row, exactly as it lands in your dataset (long signed CDN links shortened here for readability):

```json
{
  "source": "search",
  "keyword": "music",
  "roomId": "7673903898944375566",
  "title": "FEEL GOOD FRI DJ LIVE",
  "viewers": 138,
  "isLive": true,
  "ownerUsername": "thelovelythicki",
  "ownerNickname": "♡ THiCKiANA ♡",
  "ownerId": "6532034235442692097",
  "ownerSecUid": "MS4wLjABAAAAdy_TEP2jMKBhoIIEmVTqd5d9-fNXvL7D7ZMpBLl_IGPgXAY4qqb90yn5rm09-hIW",
  "profileUrl": "https://www.tiktok.com/@thelovelythicki",
  "liveUrl": "https://www.tiktok.com/@thelovelythicki/live",
  "qualities": [
    "uhd",
    "hd",
    "origin",
    "…"
  ],
  "recommendedHlsUrl": "https://pull-hls-f16-tt01.tiktokcdn-us.com/game/stream-357866927008619…?…",
  "recommendedHlsQuality": "hd",
  "expiresAt": "2026-08-28T19:31:54.000Z",
  "note": "hls.origin returns 404 on every room measured — use recommendedHlsUrl",
  "hls": {
    "uhd": "https://pull-hls-f16-tt01.tiktokcdn-us.com/game/stream-357866927008619…?…",
    "hd": "https://pull-hls-f16-tt01.tiktokcdn-us.com/game/stream-357866927008619…?…",
    "origin": "https://pull-hls-f16-tt01.tiktokcdn-us.com/game/stream-357866927008619…?…",
    "sd": "https://pull-hls-f16-tt01.tiktokcdn-us.com/game/stream-357866927008619…?…",
    "ld": "https://pull-hls-f16-tt01.tiktokcdn-us.com/game/stream-357866927008619…?…"
  },
  "flv": {
    "uhd": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3578669270086190012_…?…",
    "hd": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3578669270086190012_…?…",
    "origin": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3578669270086190012.…?…",
    "sd": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3578669270086190012_…?…",
    "ld": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3578669270086190012_…?…",
    "ao": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3578669270086190012.…?…"
  },
  "flvOriginUrl": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3578669270086190012.…?…",
  "flvAudioOnlyUrl": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3578669270086190012.…?…"
}
```

### Notes

- **Links are session tokens, not permalinks.** The signature lasts around two weeks, but a live room ends long
  before that — treat a link as good for this stream only, and re-run to find what is live now.
- You get links; the stream itself is pulled directly from TikTok's CDN by your own player or downloader.
- Chat, gifts and anything interactive genuinely need an account and are not available here. Watching does not.
- Rooms are region-dependent: these are what a US viewer sees.
- Only public data. There is no login, so nothing hidden from a logged-out visitor is reachable.

#### Run it from your own code

Every Actor is an API endpoint. This starts a run, waits for it, and returns the rows in one call — swap in your token from **Settings → Integrations**:

```bash
curl -X POST 'https://api.apify.com/v2/acts/mu0i~tiktok-live-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "keywords": [
      "gaming"
    ],
    "maxRoomsPerKeyword": 20,
    "creators": [],
    "roomIds": [],
    "streamFormats": [
      "hls",
      "flv"
    ]
  }'
```

### Pricing

Pay per result — you are billed for rows you receive, not for time or compute.

| Event | Per 1,000 | What one unit is |
|---|---:|---|
| `room` | $6.00 | one live room in the dataset |

**Paid Apify plans pay less than this.** The table above is the free-plan rate. Starter, Scale and Business each get a lower per-unit price — up to **55% off** on Business — and the Actor's Pricing tab shows every tier before you run anything.

**Starting a run costs $0.00001** — a cent per thousand runs — and there is no run minimum. **You are never billed for a run that found nothing.** If an input has nothing to collect the run says so
in a row of the dataset — never a silently empty result, and never a charge. A run that fails because the
data could not be *reached* fails loudly, because that one is worth retrying.

### Related Actors

Fourteen Actors covering the whole public TikTok surface. Same billing rules and the same guarantees throughout: billed once for each row you receive, never billed for a run that found nothing, and told in the dataset why it found nothing.

| Actor | What it does |
|---|---|
| [TikTok Search Scraper — videos, users, hashtags](https://apify.com/mu0i/tiktok-search-scraper) | Keyword search across every tab, deduplicated. |
| [TikTok Hashtag Scraper — videos by hashtag](https://apify.com/mu0i/tiktok-hashtag-scraper) | Every video under a hashtag, walked deep. |
| [TikTok Trending Scraper — the real Explore feed](https://apify.com/mu0i/tiktok-trending) | The app's real Explore feed, not Creative Center. |
| [TikTok Profile Scraper — followers, likes, bio](https://apify.com/mu0i/tiktok-profile-scraper) | Followers, likes, bio for any public account. |
| [TikTok User Posts Scraper — every video + stats](https://apify.com/mu0i/tiktok-user-posts) | Every video an account posted, with stats. |
| [TikTok Comments Scraper — replies, no duplicates](https://apify.com/mu0i/tiktok-comments-scraper) | Every comment and reply, no duplicate pages. |
| [TikTok Video Downloader — no watermark MP4/MP3](https://apify.com/mu0i/tiktok-video-downloader) | No-watermark MP4, MP3, covers and subtitles. |
| [TikTok Transcript Scraper — no AI, no waiting](https://apify.com/mu0i/tiktok-transcripts) | Subtitles from TikTok's own caption track. |
| [TikTok Sound Scraper — videos using a sound](https://apify.com/mu0i/tiktok-sound-scraper) | Videos that actually use a sound, filtered. |
| [TikTok Places Scraper — locations and reviews](https://apify.com/mu0i/tiktok-places-scraper) | Locations with addresses, coordinates and reviews. |
| [TikTok Shop Scraper — Products, Sellers & Reviews](https://apify.com/mu0i/tiktok-shop-scraper) | Shop search, product detail, seller catalogue. |
| [TikTok Shop Category Scraper — every product](https://apify.com/mu0i/tiktok-shop-category-scraper) | Every product in a Shop category and its subcategories. |
| [TikTok Shop Reviews Scraper — full archive](https://apify.com/mu0i/tiktok-shop-reviews-scraper) | The full review archive for a Shop product. |

# Actor input Schema

## `keywords` (type: `array`):

One per line. Each keyword returns up to 30 currently-live rooms WITH playable stream links.

## `maxRoomsPerKeyword` (type: `integer`):

TikTok's live search returns ONE page — there is no second page for any offset we could find — so 30 is the ceiling per keyword. Use more keywords for more rooms.

## `creators` (type: `array`):

@handles, profile URLs or numeric user IDs. Returns one row each saying whether they are streaming and in which room. Stream links are not available this way — only keyword search carries them.

## `roomIds` (type: `array`):

Numeric room IDs from an earlier run. One request re-checks the whole list, which is the cheap way to poll a watchlist.

## `streamFormats` (type: `array`):

HLS plays in browsers and in ffmpeg/VLC. FLV is what TikTok's own app pulls and is HEVC — many players cannot decode it. DASH is the browser-native alternative to HLS.

## Actor input object example

```json
{
  "keywords": [
    "gaming"
  ],
  "maxRoomsPerKeyword": 20,
  "streamFormats": [
    "hls",
    "flv"
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

Live rooms with playable stream links.

# 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 = {
    "keywords": [
        "gaming"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mu0i/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 = { "keywords": ["gaming"] }

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

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

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

```

## CLI example

```bash
echo '{
  "keywords": [
    "gaming"
  ]
}' |
apify call mu0i/tiktok-live-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mu0i/tiktok-live-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

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