# TikTok Live Status Scraper & Monitor - Go-Live Alerts, Viewers (`neverempty/tiktok-live-status-monitor`) Actor

Check whether TikTok accounts are live right now: viewer count, total enters, stream title, start time, playback URLs and follower count. Turn monitoring on and a run returns an account only when it goes live or ends a stream, for a small fee per account checked.

- **URL**: https://apify.com/neverempty/tiktok-live-status-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Social media, Videos, Automation
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.65 / 1,000 live status row returneds

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## TikTok Live Status Scraper & Monitor - go-live alerts, priced per check

Check whether TikTok accounts are live right now - viewer count, total enters, stream title, start time, how long they have been live, playback URLs and follower count - and, with monitoring on, **receive a row only when something happens**: an account goes live, ends a stream, or starts a new one. A poll on which nothing changed returns a single free `no-change` row.

In monitoring mode you pay a small fee per account checked, **$0.30 per 1,000 checks**, and the normal row price only for the rows that report a change. Watching 10 creators every 5 minutes is 86,400 checks a month, which is **$25.92** in check fees, plus the change rows you receive.

### Best for

- **Go-live alerts** - schedule a run every few minutes, send the dataset to Slack, Discord, Telegram or a webhook, and every row you receive is an event worth sending.
- **Sponsored-live verification** - confirm that a paid creator actually went live, when, for roughly how long, and the highest viewer count seen while you were watching.
- **Live-commerce and competitor tracking** - log when a roster of accounts streams and how big those streams get.
- **"Who is live now" lists** - check a roster once with `onlyLive` and receive only the accounts that are live.

### What each row contains

- **What you asked for and what TikTok returned** - `inputUsername`, `username`, `usernameMatchesInput`, `userId`, `secUid`, `nickname`, `verified`, `profileUrl`, `liveUrl`.
- **Live status** - `isLive`, `liveStatusCode` (TikTok's own code: 2 = live, 4 = not live), `roomId`.
- **Only while live** - `startedAt`, `startedAtEpoch`, `liveDurationSeconds`, `roomTitle`, `viewerCount` (people in the room now), `totalEnterCount` (entries since the stream started), `coverUrl`, `streamUrls`.
- **Only when not live** - `lastStreamStartedAt`, `lastStreamStartedAtEpoch` (the start of the most recent stream TikTok reports).
- **Account** - `followerCount`, `followingCount`.
- **Monitoring** - `change`, `isFirstCheck`, `previousCheckedAt`, `previousIsLive`, `previousRoomId`, and for a stream that ended: `endedAfter`, `endedBefore`, `streamDurationSecondsAtLeast`, `streamDurationSecondsAtMost`, `peakViewerCountSeen`, `lastSeenTotalEnterCount`, `checksWhileLive`.

Measured on 2026-09-14 from Apify: @aljazeeraenglish was live with `viewerCount` 11154 and `totalEnterCount` 13693658; @tiktok was not live, and its most recent stream had started on 2026-08-28.

#### What is deliberately not returned for an account that is not live

When an account is not live, TikTok still sends the numbers of its previous room: on 2026-09-14 the room of @tiktok reported a current user count of 1, the enter count of a stream that had ended weeks earlier, and playback URLs for it. Returning those would tell you that one person is watching a stream that is not happening. So `viewerCount`, `totalEnterCount`, `roomTitle`, `coverUrl` and `streamUrls` are filled **only while the account is live**; for an account that is not live you get `isLive: false` and the start time of its most recent stream.

#### Follower count

`followerCount` is the whole number the live endpoint returns (for example 95730279 for @tiktok on 2026-09-14), not a rounded "95.7M". It has not been compared against the figure on the profile page, and it can differ slightly between requests.

### Monitoring, and what it costs

Turn **monitoring mode** on and the Actor remembers each account's live status. On later runs an account comes back only with one of these `change` values:

| `change` | Meaning |
|---|---|
| `first-check` | The account had not been seen before. Every account is returned once on the first run, to set the baseline. |
| `went-live` | Not live at the previous run, live now. |
| `ended` | Live at the previous run, not live now. The row says the stream ended between `endedAfter` (the previous run) and `endedBefore` (this run), gives the duration as a range (`streamDurationSecondsAtLeast` to `streamDurationSecondsAtMost`), and the highest viewer count seen by your runs while it was live. |
| `new-stream` | Live at both runs, but in a different room: the previous stream ended and a new one started in between. |
| `stream-between-checks` | Not live at either run, but the most recent stream is newer than the one remembered: the account went live and ended between two runs. |

An account whose status did not change is **not returned**, so it costs no row price; the check fee for reading it still applies. While it stays live, the Actor keeps updating the highest viewer count it has seen, so the `ended` row can report it.

The duration of a stream is a range, not a single number, because the Actor only knows the status at the moments it runs. Run it more often for a narrower range.

The status is remembered **per account, not per list**, so adding a username does not reset the accounts already being watched. In monitoring mode `maxProfiles` does not cut changes: every change among the accounts read is returned. If the run's maximum total charge stops a change from being delivered, that change is not remembered, so the account still counts as changed the next time it is checked.

An account that comes back as `no-live-profile` (see below) is not remembered. If such an account later goes live and TikTok starts returning it, its first row is `first-check`, not `went-live`.

**Do not put the same account in two schedules that can run at the same time.** Each run writes back only the accounts it checked, merged into the statuses as they are at that moment, then reads them again and writes once more if another run overwrote them - so two overlapping runs over different accounts keep each other's history. But Apify's key-value store has no atomic update, so this cannot be made watertight: runs that finish at the same instant, or check the same account at the same time, can still overwrite each other's record, and the next run may return a `first-check` or a change a second time.

#### What monitoring costs

- **$0.30 per 1,000 account checks** - charged in monitoring mode for every account whose live status was read, whether or not it changed. Names TikTok returns nothing for and bot checks are not charged.
- **The row price** - charged only for the rows returned, which in monitoring mode means `first-check` rows and changes.

The Actor reads only as many accounts as the run's maximum total charge can pay for with both a check and a change row each, so a low limit cannot use up the budget on check fees and leave nothing for the rows. Accounts beyond that are not checked; a `budget-reached` row says how many, and raising the maximum total charge lets them be checked. Runs with monitoring off are charged per row only.

### Rows that are never charged

When there is nothing to return, this Actor says why instead of returning an empty result:

- `no-live-profile` - TikTok's live endpoint returned no user for that name (code 19881007, "user\_not\_found"). This is common for accounts that exist: on 2026-09-14, **33 of 83 accounts** (40%) whose profile pages had been read on 2026-09-06 got this answer, among them @nasa, @duolingo, @nytimes and @taylorswift - **exactly the same 114-byte answer** TikTok gives for a name that does not exist. So this row does not claim the account is missing, and it does not report it as offline.
- `blocked` - TikTok answered with a bot check or an empty response. The account is not reported as offline. Accounts are requested directly first, and only this answer makes the run switch to a proxy session and try again.
- `unreadable` - the response could not be read, or TikTok sent a status code whose meaning has not been measured here (only room status 2 and 4 have been). The code is reported as-is and is not translated.
- `no-change` - monitoring ran and no account changed. The row lists the accounts that are still live.
- `no-match` - `onlyLive` is on and none of the accounts is live right now.
- `invalid-input` - the text is not a TikTok username or profile URL, so nothing was requested.
- `budget-reached` - the run's maximum charge was reached: the row says how many ready rows fit, or how many accounts were not checked in monitoring mode.
- `not-checked` - the end of your list was not checked, because `maxProfiles` accounts had already been read (monitoring off), or because more than 1,000 usernames were given. The row says how many.

### Playback URLs

For live accounts, `streamUrls` holds the playback URLs TikTok publishes for the room, per quality (FLV, HLS and CMAF where present; from Apify on 2026-09-14 TikTok returned only the `hd` quality with FLV and CMAF). They are signed; TikTok decides how long they work (the `expire` value in the URLs measured on 2026-09-14 was about 14 days after the request), and they do not play once the stream has ended. **This Actor does not record, download or store any stream.** Turn `includeStreamUrls` off for smaller rows.

### How fast, and what it costs to run

Accounts are checked one at a time with a short pause between requests, about 0.7 seconds each (measured on Apify on 2026-09-14). One run checks up to 1,000 accounts, about 12 minutes.

### Input

| Field | What it does |
|---|---|
| `usernames` | The accounts to check: `@name`, `name`, or a profile or live URL. Names are sent in lower case, as TikTok stores them, so `@AlJazeeraEnglish` and `@aljazeeraenglish` are the same account and are checked once. If empty, the example accounts @aljazeeraenglish and @tiktok are checked. |
| `maxProfiles` | How many charged rows to return in total (up to 1,000). |
| `includeStreamUrls` | Return playback URLs for live accounts (on by default). |
| `onlyLive` | Return only the accounts that are live right now. |
| `monitoringMode` | Remember the status and return an account only when it changes. |
| `resetMonitoringState` | Forget every remembered status and start a fresh baseline. |
| `useProxy` | Retry through a proxy if TikTok answers with a bot check. Every account is requested directly first. |

### Questions

**How do I get an alert when a creator goes live?**
Turn on `monitoringMode`, schedule the Actor, and send the run's dataset to your channel with an Apify integration or webhook. How often is a trade-off between how fast you hear about a stream and the check fee: 10 accounts every 5 minutes is 86,400 checks a month ($25.92); every 15 minutes is 28,800 ($8.64). Rows with `change: "went-live"` are go-live events; `ended` rows tell you the stream is over. Runs on which nothing changed return a single free `no-change` row.

**Does monitoring charge me when nothing changed?**
Unchanged accounts are not returned and cost no row price. Each account checked costs the check fee ($0.30 per 1,000), changed or not - that is what pays for polling.

**Why does an account come back as `no-live-profile` when it exists?**
Because TikTok's live endpoint answers "user\_not\_found" for many accounts that exist - 33 of 83 in a sample measured on 2026-09-14 - with the same code and the same body as for a name that does not exist. The Actor cannot tell the two apart from that answer, so it tells you exactly that instead of guessing. The row is not charged, including the check fee.

**Why is the viewer count empty for an account that is not live?**
Because TikTok keeps sending the previous room's numbers after a stream ends, including a "current" user count of 1. Those are not returned as if they described a stream that is happening.

**Can I record the stream?**
No. This Actor reports status and passes on the playback URLs TikTok publishes; it does not record or store anything.

**Is `viewerCount` the same as what the app shows?**
It is the room's user count as TikTok's live endpoint returns it at the moment of the request. It has not been compared against the number displayed in the app.

### Example input

```json
{
  "usernames": ["@aljazeeraenglish", "@tiktok"],
  "monitoringMode": true,
  "includeStreamUrls": true,
  "maxProfiles": 100
}
```

# Actor input Schema

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

Accounts to check: @name, name, or a profile or live URL (https://www.tiktok.com/@name/live, with or without the scheme). Names are sent in lower case, as TikTok stores them, and duplicates are checked once. If you leave this empty, the example accounts @aljazeeraenglish and @tiktok are checked and every row says so in inputUsername.

## `maxProfiles` (type: `integer`):

How many charged rows to return in total when monitoring is off: reading stops once this many rows are ready (with onlyLive, once this many live accounts have been found), and a free row says how many entries at the end of the list were not checked. In monitoring mode it does not limit the changes returned - every change among the accounts read comes back. Up to 1,000 accounts are checked per run (about 0.7 seconds each).

## `includeStreamUrls` (type: `boolean`):

For accounts that are live, return the playback URLs TikTok publishes for the room (FLV / HLS / CMAF, per quality). They are signed, TikTok decides how long they work (about 14 days in URLs measured on 2026-09-14), and they do not play once the stream has ended. This Actor does not record or download anything.

## `onlyLive` (type: `boolean`):

On = accounts that are not live are checked but not returned, so they cost no row price (in monitoring mode the check fee still applies); with monitoring off, reading stops once maxProfiles live accounts have been found. Handy for a 'who is live now' list.

## `monitoringMode` (type: `boolean`):

Off = every account you listed comes back with its current status, charged per row. On = the Actor remembers each account and, on later runs, returns it only when it went live, ended a stream, started a new stream, or streamed and ended between two runs. The first run returns every account once to set the baseline. **In monitoring mode every account checked costs $0.30 per 1,000 checks, changed or not** (names TikTok returns nothing for and bot checks are free), plus the row price for the rows returned. Example: 10 accounts every 5 minutes = 86,400 checks a month = $25.92. The Actor reads only as many accounts as the run's maximum total charge can pay for with a check and a change row each. The status is remembered per account; do not put the same account in two schedules that can run at the same time.

## `resetMonitoringState` (type: `boolean`):

Clears every remembered live status for this Actor, so the next monitoring run returns each account once again. This affects all your monitoring runs, because the status is stored per account rather than per list.

## `useProxy` (type: `boolean`):

Every account is requested directly first, which is the fastest path and worked from Apify on every attempt measured on 2026-09-14. If TikTok answers with a bot check or an empty response, this switches to a proxy session and tries again. With it off, that answer is returned as a free 'blocked' row and no proxy is paid for.

## Actor input object example

```json
{
  "usernames": [
    "@aljazeeraenglish",
    "@tiktok"
  ],
  "maxProfiles": 100,
  "includeStreamUrls": true,
  "onlyLive": false,
  "monitoringMode": false,
  "resetMonitoringState": false,
  "useProxy": true
}
```

# Actor output Schema

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

One row per TikTok account: the username you asked for and the one TikTok resolved it to, whether the account is live right now, and for live accounts the room id, stream title, start time, how long it has been live, current viewer count, total enters, cover image and playback URLs; for accounts that are not live, the start time of their most recent stream; the follower and following counts; and, in monitoring mode, what changed since the last run (went live, ended, new stream, or a stream that started and ended between runs) with the bounds of the stream's duration and the highest viewer count seen. Names TikTok returns nothing for and bot checks come back as their own free rows; in monitoring mode unchanged accounts are not returned.

# 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": [
        "@aljazeeraenglish",
        "@tiktok"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/tiktok-live-status-monitor").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": [
        "@aljazeeraenglish",
        "@tiktok",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/tiktok-live-status-monitor").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 '{
  "usernames": [
    "@aljazeeraenglish",
    "@tiktok"
  ]
}' |
apify call neverempty/tiktok-live-status-monitor --silent --output-dataset

```

## MCP server setup

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

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/k103UH0p09YZdpTpy/builds/D4xwWzcktfkN1VoNZ/openapi.json
