# TikTok Views Tracker (`searchshark/tiktok-views-tracker`) Actor

Track public TikTok video views over time with persistent history. Get previous views, views gained, growth %, views per hour, 1h/24h/7d growth metrics, and growth status. Supports bulk URLs, retries, deduplication, and structured errors.

- **URL**: https://apify.com/searchshark/tiktok-views-tracker.md
- **Developed by:** [SearchShark Tools](https://apify.com/searchshark) (community)
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

Track how fast public TikTok videos are gaining views — not just what their view count is right now.

Paste direct TikTok video URLs and this Actor records timestamped view snapshots in persistent storage. On later runs it compares the new count with previous snapshots and returns **views gained, growth percentage, views per hour, rolling 1h / 24h / 7d growth metrics, and a transparent growth status**.

This Actor is intentionally focused on **video growth monitoring**. It is not a general-purpose profile, hashtag, comments, or media downloader.

### Why use TikTok Video Views Tracker?

Many TikTok scrapers are designed around static extraction. This tracker is built for the next question:

**"How fast is this video growing?"**

Key features:

- 📈 **Persistent cross-run history** — snapshots survive separate Actor runs
- ⚡ **Views gained and views/hour** — compare the current count with the previous snapshot
- 🕐 **Rolling 1h, 24h, and 7d metrics** — use historical snapshots when enough history exists
- 🚦 **Clear growth status** — `first_snapshot`, `insufficient_history`, `stalled`, `growing`, `fast_growing`, or `counter_decrease`
- 📦 **Bulk tracking** — monitor up to 100 TikTok video URLs in one run
- 🔁 **Duplicate-safe input** — duplicate video IDs are processed once
- 🧯 **Per-video error isolation** — one failed URL does not stop the whole batch
- 🧾 **Structured error codes** — invalid URLs, blocked/challenged pages, HTTP failures, missing data, and other failures are explicit
- 🛡️ **No fake zeroes** — unavailable view counts are returned as errors instead of being silently converted to `0`
- 🔓 **No TikTok login, cookies, or TikTok API key required** for public video pages
- 📤 **Apify Dataset output** — export results using Apify's standard dataset formats or consume them through the API

### Quick start

Use one or more direct public TikTok video URLs:

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@scout2015/video/6718335390845095173"
  ],
  "concurrency": 3
}
```

#### First run

The first successful run stores the initial snapshot. There is no older snapshot to compare against yet, so historical growth fields are `null` and:

```json
{
  "historyStatus": "tracked",
  "growthStatus": "first_snapshot",
  "isFirstSnapshot": true,
  "previousViews": null,
  "viewsGained": null,
  "growthPercent": null,
  "viewsPerHour": null
}
```

#### Later runs

Run the Actor again with the same video URL. The Actor loads that video's persistent history and calculates growth:

```json
{
  "status": "ok",
  "videoId": "6718335390845095173",
  "username": "scout2015",
  "views": 160700,
  "historyStatus": "tracked",
  "growthStatus": "fast_growing",
  "isFirstSnapshot": false,
  "previousViews": 159200,
  "viewsGained": 1500,
  "elapsedHours": 1,
  "growthPercent": 0.9422,
  "viewsPerHour": 1500
}
```

The values above are an example of the output shape. Your results depend on the actual public TikTok view counts and the time between snapshots.

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `videoUrls` | string\[] | Yes | Direct public TikTok video URLs. Up to 100 URLs per run. |
| `concurrency` | integer | No | Number of video pages fetched in parallel. Default: `3`. Allowed range: `1`–`10`. |

Supported URL shape:

```text
https://www.tiktok.com/@username/video/1234567890123456789
```

Invalid URLs are returned as error rows instead of stopping the batch.

### Output

Each input produces a flat success or error row in the default Dataset.

#### Current snapshot fields

| Field | Meaning |
| --- | --- |
| `status` | `ok` or `error` |
| `inputUrl` | Original input URL |
| `videoId` | TikTok video ID |
| `username` | TikTok username parsed from the URL |
| `url` | Normalized TikTok video URL |
| `views` | Current public TikTok view count |
| `fetchedAt` | Timestamp of the current snapshot |
| `source` | Current data source identifier |
| `historyStatus` | Whether persistent history was recorded successfully |

#### Previous-snapshot growth fields

| Field | Meaning |
| --- | --- |
| `previousViews` | View count from the previous stored snapshot |
| `previousFetchedAt` | Timestamp of the previous stored snapshot |
| `viewsGained` | Current views minus previous views |
| `elapsedHours` | Time between the two snapshots |
| `growthPercent` | Percentage growth from the previous view count |
| `viewsPerHour` | View growth normalized to one hour |
| `counterDecreaseDetected` | `true` when TikTok's current counter is lower than a prior snapshot |

Counter decreases are preserved instead of rewritten to zero. This makes corrections or counter changes visible in downstream analytics.

### Growth status

`growthStatus` is a transparent classification based on the same metrics returned in the row.

| Status | Meaning |
| --- | --- |
| `first_snapshot` | This is the first stored snapshot for the video |
| `insufficient_history` | A previous snapshot exists, but less than 15 minutes of history is available |
| `counter_decrease` | The current public view count is lower than the previous snapshot |
| `stalled` | Enough history exists, but the video gained no positive views |
| `growing` | The video is gaining views |
| `fast_growing` | At least 1,000 views/hour **or** at least 10% growth since the previous snapshot |

This is deliberately not an opaque "viral score." The underlying counts, timing, percentage, and velocity are returned beside the status so you can audit the classification yourself.

### Rolling 1h, 24h, and 7d growth

When enough history exists, the Actor can also return:

- `viewsGained1h`, `viewsPerHour1h`, `growthPercent1h`, `actualWindowHours1h`
- `viewsGained24h`, `viewsPerHour24h`, `growthPercent24h`, `actualWindowHours24h`
- `viewsGained7d`, `viewsPerHour7d`, `growthPercent7d`, `actualWindowHours7d`

The Actor uses the stored snapshot closest to the requested historical window, within a bounded tolerance. If there is no appropriate snapshot yet, the related fields stay `null`.

That means `null` does **not** mean zero growth. It means there is not yet a suitable historical comparison point.

For useful rolling metrics, run the same tracked videos on a consistent schedule.

### Persistent history

History is stored per TikTok video ID in a named Apify key-value store. Each tracked video keeps a bounded timestamped snapshot history instead of relying only on the current run's Dataset.

This provides two useful layers:

1. **Previous-run comparison** for immediate `viewsGained`, `growthPercent`, and `viewsPerHour`
2. **Historical-window comparison** for 1h, 24h, and 7d metrics

History recording is isolated from view retrieval. If the current TikTok view count is fetched successfully but persistent history storage fails, the success row is still returned with:

```json
{
  "status": "ok",
  "historyStatus": "error",
  "historyErrorMessage": "..."
}
```

### Recommended monitoring workflows

#### Creators

Track a shortlist of recent posts and see which clips are still gaining views instead of comparing raw totals manually.

#### Agencies

Monitor client and competitor videos using the same repeatable schema. Export the Dataset to a spreadsheet or dashboard and rank videos by growth rather than lifetime views.

#### Brands

Track campaign videos after launch and watch view velocity over repeated runs.

#### Researchers

Build a clean time series of public TikTok view counts without maintaining your own snapshot database.

#### Automation and AI workflows

Use the Actor through Apify API integrations, schedules, or downstream automation. The flat Dataset schema is designed to be easy to filter by `growthStatus`, `viewsGained`, `viewsPerHour`, and rolling-window fields.

### Reliability behavior

The Actor is designed to fail clearly rather than return misleading analytics.

Examples:

- Invalid TikTok URL → structured error row
- One video fails → remaining videos continue
- TikTok challenge or blocked response → explicit error
- Embedded video data missing → explicit error
- View count unavailable → explicit error
- Persistent history write fails → current successful view result is preserved and history is marked as failed

Network/data failures may be retried when appropriate. Non-retryable HTTP failures are returned directly.

### Limitations

- Tracks **public TikTok video URLs** only
- Does not access private videos, account analytics, or data behind a TikTok login
- Does not bypass CAPTCHA, login challenges, or TikTok access restrictions
- Does not scrape profile feeds, comments, hashtags, sounds, or search results
- Does not download TikTok video files
- TikTok can change its public page structure, which may temporarily affect retrieval
- Historical metrics require repeated runs; the first run cannot calculate past growth that was never recorded

These limits are intentional: the Actor stays focused on low-overhead, auditable view-growth monitoring.

### FAQ

#### Why are my 1h / 24h / 7d fields `null`?

There is not yet a stored snapshot close enough to that historical window. Keep running the same video URLs on a consistent schedule.

#### Why is `growthStatus` `insufficient_history`?

A previous snapshot exists, but less than 15 minutes have elapsed. This avoids labeling extremely short intervals as meaningful growth trends.

#### Why is `viewsGained` negative?

TikTok's public counter can sometimes decrease or be corrected. The Actor preserves that value and sets `counterDecreaseDetected: true` instead of hiding it.

#### Does the Actor need my TikTok account?

No. It reads public video pages and does not require your TikTok login, cookies, or TikTok developer credentials.

#### Can one bad URL break the whole run?

No. Errors are isolated per video and returned as structured error rows.

#### How many URLs can I track at once?

Up to 100 TikTok video URLs per run.

### Best use case

Choose this Actor when you already know **which TikTok videos you want to monitor** and care about **how their views change over time**.

If your main goal is broad content discovery, profile scraping, hashtag search, comments, or media downloads, a general TikTok scraper is a better fit. If your goal is persistent view-growth monitoring, this Actor keeps the workflow focused and the output easy to analyze.

# Actor input Schema

## `videoUrls` (type: `array`):

Direct public TikTok video URLs to track. Re-run the same URLs later to calculate growth from persistent history.

## `concurrency` (type: `integer`):

Number of TikTok video pages fetched in parallel. Default: 3. Increase cautiously for larger batches.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@scout2015/video/6718335390845095173"
  ],
  "concurrency": 3
}
```

# Actor output Schema

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

Per-video TikTok view results stored in the default dataset.

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

Run totals stored in the OUTPUT record of the default key-value store.

# 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 = {
    "videoUrls": [
        "https://www.tiktok.com/@scout2015/video/6718335390845095173"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("searchshark/tiktok-views-tracker").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 = { "videoUrls": ["https://www.tiktok.com/@scout2015/video/6718335390845095173"] }

# Run the Actor and wait for it to finish
run = client.actor("searchshark/tiktok-views-tracker").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 '{
  "videoUrls": [
    "https://www.tiktok.com/@scout2015/video/6718335390845095173"
  ]
}' |
apify call searchshark/tiktok-views-tracker --silent --output-dataset

```

## MCP server setup

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

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/5xFxpc3dFqVi7eLYM/builds/3h7TJfD6BTtxrMCXv/openapi.json
