# TikTok Creator & Video Growth Tracker (`maydit/tiktok-creator-video-growth-tracker`) Actor

Track public TikTok creator and video metrics over time. Compare saved counts and timestamped changes within a bounded creator sample. No login or video downloads.

- **URL**: https://apify.com/maydit/tiktok-creator-video-growth-tracker.md
- **Developed by:** [Brandt May](https://apify.com/maydit) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 saved video observations

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 Creator & Video Growth Tracker

<img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/r4RVqhPKWACJsK9zp-actor-f3bLI4HzXwaCsXI1l-jnUrZlrQxZ-tiktok-literal-v2.png" alt="TikTok Creator &amp; Video Growth Tracker icon" width="112" height="112">

**See how the public videos you follow are changing.** Enter a creator handle, collect a small video sample, and compare the next observation with the last one you saved. The output connects reported views, likes, comments, shares and saves to the video, its creator and the time of collection.

Use it for a creator watchlist, a campaign check-in or a spreadsheet of competitor content. The first run needs no TikTok login, API key or proxy.

[Start a run](https://console.apify.com/actors/maydit~tiktok-creator-video-growth-tracker/input) | [Output fields](#what-you-get) | [Monitoring](#turn-a-sample-into-a-watchlist) | [Coverage](#understand-the-sample)

### Start with three videos

Paste this input into the Actor. It selects the first three videos currently exposed by the NBA's public creator embed:

```json
{
  "profiles": ["https://www.tiktok.com/@nba"],
  "maxVideosPerProfile": 3,
  "maxResults": 3
}
```

1. Replace `nba` with a public creator handle or direct profile URL.
2. Choose a small **Videos per creator** limit and set a maximum charge in Apify Run options.
3. Run the Actor, open the dataset, then review the **Run report** for source coverage. Export JSON or CSV for your workflow.

Omitted inputs use `nba` and three videos. A profile sample may include pinned or older posts; it is not a guaranteed chronological list. Explicit video URLs are available under the advanced input section when a stable watchlist is more useful.

### What you get

One dataset row represents one successfully validated video observation.

| Field | How to use it |
| --- | --- |
| `videoId`, `videoUrl` | Stable identity and public evidence link. |
| `creatorId`, `creatorHandle`, `creatorName` | The creator reported by the video page, checked against the requested identity. |
| `caption`, `createdAt`, `durationSeconds` | Public caption, publication timestamp and duration when exposed. Captions are limited to 8,000 characters with `captionTruncated`. |
| `views`, `likes`, `comments`, `shares`, `saves` | Literal numbers from the public page. Missing optional saves are `null`. |
| `creatorFollowers`, `creatorFollowing`, `creatorLikes`, `creatorVideos` | Creator counts when that video's page exposes them; otherwise `null`. |
| `rawMetrics`, `metricSources` | Original count values and the embedded field supplying each video metric. |
| `comparisonStatus`, `changedFields`, `previous` | Whether this is a new, changed or unchanged saved observation, and the previous values. |
| `metricDeltas`, `previousObservedAt`, `observationIntervalSeconds` | Count differences over the actual interval between observations. |
| `viewsPerHourSincePrevious` | Observed view-counter change divided by the elapsed time, expressed per hour. No prior baseline or an interval below 60 seconds means `null`. |
| `sampleComparison` | The median reported views and relative view count within this creator's selected sample, only when that sample was fully retrieved. |
| `observedAt`, `contentHash`, `sourceUrl` | Collection time, stable snapshot hash and source provenance. |

The source may round, delay or revise counts even when it returns an integer. `metricsPrecision` is therefore `source_reported_precision_unknown`. A difference is a change in the numbers exposed by TikTok, not a verified count of unique people or newly completed views. Counts can decrease; those fields are listed in `countersDecreased`. A negative rate can reflect a correction or source revision; it does not establish negative viewing activity. Rates are descriptive counter-change measurements, never delivery forecasts.

`engagementPerViewPercent` is `(likes + comments + shares) / views * 100`, or `null` when views are zero. It is a ratio of reported interactions to reported views, not unique-audience engagement. The sample median includes the current video, mixes publication ages, and is not age-adjusted or a viral-performance prediction.

### Turn a sample into a watchlist

For repeatable video tracking, use exact URLs, enable comparison and keep the same `snapshotName` and input scope. The first comparison returns `new` rows and establishes history **only after each output row is saved**. Later runs expose current and previous values. Set `onlyChanges: true` to omit unchanged rows; a healthy unchanged repeat can save zero rows.

For a spreadsheet or database, upsert current state by `videoId`. To keep an observation log, use `videoId` plus `observedAt`; use `contentHash` to avoid replaying an identical snapshot. Review `SUMMARY` before sending alerts. A source failure or missing video is not a zero count or deletion.

History is stored in your named Apify key-value store, scoped to the sorted profile/video inputs and per-profile sample size. Changing those inputs starts a separate baseline. Use one writer per name and scope. The Actor checks for a changed baseline before committing and reports detected conflicts; storage does not provide an atomic cross-run lock. At most 20,000 video identities are retained per scope. Use a fresh name for a deliberate reset.

### Three ready-to-use examples

#### A small Duolingo sample

```json
{
  "profiles": ["duolingo"],
  "maxVideosPerProfile": 2,
  "maxResults": 2
}
```

#### NBA creator context

```json
{
  "profiles": ["https://www.tiktok.com/@nba"],
  "maxVideosPerProfile": 3,
  "maxResults": 3
}
```

#### Three exact videos with saved comparison

```json
{
  "profiles": [],
  "videoUrls": [
    "https://www.tiktok.com/@duolingo/video/7696211706317409550",
    "https://www.tiktok.com/@nba/video/7697747447862398238",
    "https://www.tiktok.com/@washingtonpost/video/7697752148280495373"
  ],
  "comparePrevious": true,
  "snapshotName": "three-video-example",
  "maxResults": 3
}
```

Examples are public observations checked during development, not permanently available fixtures. A creator can change visibility or remove a video.

### Pricing and run limits

Base pricing is **$0.001 per saved video observation** plus **$0.00005 per run start**. Reading a creator selection, skipped unchanged observations, failed source requests, SUMMARY and the HTML report do not produce paid dataset rows. Check the current Pricing tab and your plan before running; platform or other applicable charges are governed by Apify.

- Up to **10 profiles**, **10 selected videos per profile**, and **30 additional exact video URLs**.
- At most **100 saved observations** per run; the default result allowance is 30, while the default creator sample is three.
- Own collection budget: **240 seconds** by default, bounded further by the platform timeout with a 25-second reserve.
- Public requests are sequential, capped at 4 MiB each. Only transient HTTP 502/503/504 receives one short retry within the remaining budget. Access refusals and unavailable video responses are not bypassed.

Source collection stops five seconds before the output deadline to allow already validated observations to be saved. Cloud SDK requests have a five-second timeout and no automatic retries; an unconfirmed write never advances history. These reserves reduce data loss during slow responses, but a platform interruption can still prevent a final summary or history commit.

A result or spending limit can leave later sources or rows unprocessed. Previously saved data is retained. History advances only for confirmed saved rows and may be withheld if the deadline or a concurrent history change prevents a safe commit.

### Understand the sample

The Actor reads ordinary public creator-embed and video-page HTML. It does not use TikTok's authenticated Display or Research APIs, run a browser, collect cookies, solve challenges, download media, or call a paid transcription service. Creator embedding is documented by TikTok; the embedded state used for metrics is an observed website format, not a guaranteed metrics API. TikTok's crawler guidance currently disallows creator-embed crawling. Public accessibility is separate from permission to reuse data; use the service consistently with applicable source terms.

Only the exposed selection is checked. There is no full-profile pagination, historical backfill, keyword search, follower list, comment text, transcript, private-account access or deleted-post inference. Public photo posts and shortened URLs are unsupported. An embed can list a video whose detail page is unavailable; valid videos can still be saved, with the gap recorded explicitly.

`SUMMARY.status` is `ok`, `partial`, `spending_limit` or `failed`. `selectedWindowFetchedComplete` records successful retrieval of the selected window; `outputComplete` also requires every valid observation to be saved or intentionally skipped as unchanged. `selectionComplete` requires complete delivery without reported time, spending or history issues. A result cap that leaves observations unsaved makes output incomplete; a cap exactly equal to the fully delivered sample does not invent a missing row. `fullProfileCovered` is always false for a creator selection. `failedSources`, `sourcesNotReached`, source coverage and limit flags explain missing data. All-source or all-output failures fail the run; a legitimately empty public selection or unchanged comparison is distinguished from failure. The readable `RUN_REPORT` presents the same diagnostics without creating dataset rows.

### Sources and support

- [TikTok creator embeds](https://developers.tiktok.com/docs/en/embed-creator-profiles)
- [TikTok video embeds](https://developers.tiktok.com/docs/en/embed-videos)
- [TikTok crawler guidance](https://www.tiktok.com/robots.txt)
- [TikTok terms](https://www.tiktok.com/legal/page/row/terms-of-service/en)

For help, source-change reports or data-removal requests, open an Actor Issue or email **bmay@mayd-it.com**. Include the run ID and public source URL; omit credentials and private information. This Actor is provided by Mayd It and is not affiliated with TikTok.

# Actor input Schema

## `profiles` (type: `array`):

Up to 10 public creator handles (duolingo or @duolingo) or direct https://www.tiktok.com/@handle URLs. With no profiles or video URLs, the first run checks nba. Shortened URLs and query strings are not accepted.

## `maxVideosPerProfile` (type: `integer`):

Read the first 1-10 videos supplied in each creator embed. The selection can contain pinned or older videos and is not a complete or guaranteed chronological profile archive.

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

Up to 30 direct https://www.tiktok.com/@handle/video/ID URLs. Added to profile selections, deduplicated by video ID. Set profiles to \[] for a video-only watchlist. Photo posts and shortened/share URLs are not supported.

## `comparePrevious` (type: `boolean`):

First comparison emits new observations and establishes history only after output is saved. Later runs emit changed or unchanged rows with prior values, count deltas and observation interval. Missing videos never imply deletion.

## `onlyChanges` (type: `boolean`):

Also enables comparison. An unchanged repeat can save zero rows successfully. Changing the selected profile/video scope or per-profile sample size creates a separate baseline.

## `snapshotName` (type: `string`):

1-80 letters, digits, underscores or hyphens. Use separate names for separate workflows. Do not run overlapping writers for the same name and scope; detected conflicts preserve the other writer.

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

Maximum confirmed saved rows. Default creator selection is only three videos. Unchanged skipped rows do not count toward this cap. Reaching the cap leaves later observations unchecked or unsaved; consult SUMMARY.

## `maxRunSeconds` (type: `integer`):

Own wall-clock budget, also limited by the platform timeout with a 25-second reserve. Every source HTTP request is bounded by remaining time. Source failures and deadline stops remain visible in SUMMARY.

## Actor input object example

```json
{
  "profiles": [
    "nba"
  ],
  "maxVideosPerProfile": 3,
  "comparePrevious": false,
  "onlyChanges": false,
  "snapshotName": "default",
  "maxResults": 30,
  "maxRunSeconds": 240
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

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

No description

## `report` (type: `string`):

No description

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

// Run the Actor and wait for it to finish
const run = await client.actor("maydit/tiktok-creator-video-growth-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 = { "profiles": ["nba"] }

# Run the Actor and wait for it to finish
run = client.actor("maydit/tiktok-creator-video-growth-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 '{
  "profiles": [
    "nba"
  ]
}' |
apify call maydit/tiktok-creator-video-growth-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maydit/tiktok-creator-video-growth-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/f3bLI4HzXwaCsXI1l/builds/ldcibwlm0WLf34Zht/openapi.json
