# TikTok Profile, Video & Comments Scraper + Growth Tracker (`moonweil/tiktok-scraper`) Actor

Scrape TikTok profiles, videos and comment threads in bulk: followers, likes, plays, engagement rate, bio emails & links, music, hashtags, captions/transcripts and every comment with replies. Track follower & view growth between runs. No browser, no login.

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

## Pricing

from $1.00 / 1,000 profiles

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?

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 Profile, Video & Comments Scraper + Growth Tracker

Get clean, export-ready TikTok data for **profiles**, **videos** and **comment threads** in bulk:
followers, total likes, plays, shares, saves, **engagement rate**, emails and links from bios,
music, hashtags, **transcripts** from TikTok's captions, and every comment with its replies.

Turn on **growth tracking** and schedule it: each run tells you how many followers, likes, plays
and comments each account or video gained since the last run, per day and in percent.

No TikTok account, no cookies, no browser. Fast and cheap, with flat per-result pricing.

### Why this one

- **Flat, predictable pricing.** No add-on fees on top of each result. Comments and
  transcripts are billed per item delivered, and failed or empty lookups are free.
- **Metrics you'd otherwise compute in a spreadsheet:** engagement rate, plays per follower,
  average likes per video, follower/following ratio, video age.
- **Growth tracking built in.** You don't have to diff exports yourself.
- **Exact counters.** TikTok's own `heartCount` overflows to a negative number for very big
  accounts. We read the exact values, so 2.7B likes stays 2.7B.
- **Flat rows.** Every column exports cleanly to CSV / Excel / Google Sheets, with no nested
  `authorMeta.*` to unpick.
- **Bulk-friendly input.** Usernames, `@handles`, profile links, video links, photo posts,
  `vm.tiktok.com` / `vt.tiktok.com` share links and bare video IDs all go in one list.
  Duplicates are merged.
- **Banned / deleted accounts reported, not dropped.** You get a free `not-found` row with
  TikTok's reason, which helps when you're vetting a list of creators.

### What you can do with it

- **Influencer vetting:** paste 500 handles and get followers, total likes, average likes per
  video, verification, business/seller flags and the contact email from each bio.
- **Campaign reporting:** track the plays, likes, shares and saves of your sponsored videos
  daily, with growth per day.
- **Competitor & creator tracking:** follower growth of competitors or your roster, week over week.
- **Comment mining & sentiment:** full comment threads with replies, likes, and whether the
  creator liked or pinned each comment.
- **Content research:** transcripts of what's said in a video, its sound, hashtags and mentions.

### Input

| Field | What it does |
|---|---|
| **Profiles** | Usernames (`mrbeast`, `@khaby.lame`) or profile links |
| **Videos** | Video / photo links, share links (`vm.tiktok.com/…`) or video IDs |
| **Comments per video** | Top-level comments per video (0 = off) |
| **Replies per comment** | Replies under each scraped comment (0 = off) |
| **Add transcript** | Spoken text from TikTok's captions, in your preferred language |
| **Track growth** + **Tracker name** | Compare every profile/video with the previous run of the same tracker |
| **Proxy** | Apify Proxy recommended; switches to residential automatically if TikTok blocks |

Example:

```json
{
  "profiles": ["mrbeast", "https://www.tiktok.com/@khaby.lame"],
  "videos": ["https://www.tiktok.com/@tiktok/video/7106594312292453675", "https://vm.tiktok.com/ZMhvqkFWM/"],
  "maxCommentsPerVideo": 100,
  "maxRepliesPerComment": 5,
  "includeTranscript": true,
  "trackGrowth": true,
  "monitorName": "my-creators"
}
```

### Output

The dataset has a `type` column (`profile`, `video`, `comment`, `not-found`) and a view for
each. Export it as JSON, CSV, Excel, XML or RSS, or read it through the API.

**Profile** (the `growth` numbers are illustrative)

```json
{
  "type": "profile",
  "username": "mrbeast",
  "nickname": "MrBeast",
  "followers": 144599186,
  "following": 346,
  "likes": 1543257983,
  "videos": 483,
  "avgLikesPerVideo": 3195151,
  "followersPerFollowing": 417916.72,
  "bio": "Checkout My New Book!👇",
  "bioLink": "http://themostdangerousgames.com",
  "emails": [],
  "verified": true,
  "privateAccount": false,
  "isOrganization": false,
  "isSeller": false,
  "profileUrl": "https://www.tiktok.com/@mrbeast",
  "growth": {
    "since": "2026-10-20T07:00:00.000Z",
    "days": 1,
    "change": { "followers": 41200, "likes": 2900000, "videos": 1 },
    "perDay": { "followers": 41200, "likes": 2900000, "videos": 1 },
    "changePercent": { "followers": 0.03, "likes": 0.19, "videos": 0.21 }
  }
}
```

**Video**

```json
{
  "type": "video",
  "id": "7478435819724934446",
  "url": "https://www.tiktok.com/@garyvee/video/7478435819724934446",
  "description": "Please please never ever ever ever ... make yourself lesser than anyone.  #lifeadvice #garyvee #selfesteem",
  "createdAt": "2025-03-05T21:11:00.000Z",
  "authorUsername": "garyvee",
  "authorFollowers": 15500000,
  "plays": 306700,
  "likes": 21500,
  "comments": 354,
  "shares": 1974,
  "saves": 4270,
  "engagementRate": 9.16,
  "playsPerFollower": 0.02,
  "durationSecs": 26,
  "musicTitle": "original sound - GaryVee",
  "hashtags": ["lifeadvice", "garyvee", "selfesteem"],
  "subtitleLanguages": ["eng-US"],
  "transcript": "You feel lesser than in a room? …",
  "coverUrl": "https://p16-common-sign.tiktokcdn-eu.com/…"
}
```

**Comment** (replies have `isReply: true` and a `parentCommentId`)

```json
{
  "type": "comment",
  "videoId": "7106594312292453675",
  "commentId": "7127915639835460357",
  "parentCommentId": null,
  "isReply": false,
  "text": "THERES FROGS IN MINECRAFT SINCE WHEN!!!!",
  "likes": 8,
  "replyCount": 1,
  "createdAt": "2022-08-04T07:13:57.000Z",
  "likedByCreator": false,
  "pinnedByCreator": false,
  "authorUsername": "a.o.r.xx",
  "authorProfileUrl": "https://www.tiktok.com/@a.o.r.xx"
}
```

The run's **SUMMARY** record (key-value store) lists each input's status, counts and charges.

### Growth tracking

1. Turn on **Track growth between runs** and give it a **Tracker name**.
2. Schedule the task (daily or weekly) in Apify Console → Schedules.
3. The first run records a baseline (`growth: null`). Every later run adds a `growth` block
   comparing it with the previous run: change, change per day and change in percent.

The last 60 snapshots per profile/video are kept in the key-value store `tiktok-growth-<name>`
on your account. Use a different name per list.

### Pricing

Pay per result, with no subscription and no add-ons:

| Event | Price |
|---|---|
| Profile scraped | $0.001 |
| Video scraped | $0.0015 |
| Comment or reply scraped | $0.0003 |
| Transcript extracted (only when a video has captions) | $0.001 |

1,000 profiles cost $1. One video with 1,000 comments costs about $0.30. A video with its
transcript costs $0.0025.
Not-found inputs, failed lookups and videos without captions are free.

### Limits and good to know

- **What it covers:** the profiles and videos you give it, plus their comments. It does **not**
  list a profile's videos, hashtag feeds or search results. TikTok only serves those to signed-in
  browser sessions, and we don't fake those. To find videos, start from links you already have:
  a list, a spreadsheet, or another tool's output.
- **Transcripts** come from TikTok's own captions (auto-generated or the creator's). Videos
  without captions get `transcript: null` and are not charged for it.
- **Media URLs** (`playUrl`, `coverUrl`, images) are signed by TikTok and expire after some hours.
  Download them soon after the run if you need the files.
- **Comments:** you get the comments TikTok shows logged-out visitors. On some videos that's
  far fewer than the comment counter, because the counter also includes replies and comments
  TikTok hides, filters or has deleted. A reply thread TikTok hides comes back empty. You're
  only charged for comments actually delivered.
- Counters such as plays are rounded by TikTok on some videos (e.g. 1.6M → 1600000).
- Private accounts return profile stats but no video data. Deleted / banned items return a
  `not-found` row.
- Only public data is collected. Make sure your use complies with TikTok's terms and with
  privacy law (e.g. GDPR) where you process personal data such as usernames or emails.

# Actor input Schema

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

TikTok usernames (with or without @) or profile links like https://www.tiktok.com/@mrbeast. One row per profile: followers, following, total likes, video count, bio, bio link, emails found in the bio, verified / private / business flags, average likes per video.

## `videos` (type: `array`):

Video or photo-post links (https://www.tiktok.com/@user/video/...), share links (vm.tiktok.com/..., vt.tiktok.com/..., tiktok.com/t/...) or bare video IDs. One row per video: plays, likes, comments, shares, saves, engagement rate, author, music, hashtags, mentions, duration, cover and slideshow images.

## `maxCommentsPerVideo` (type: `integer`):

Top-level comments to scrape for each video (0 = none). Each comment is its own row with text, likes, reply count, date, author and whether the creator liked or pinned it.

## `maxRepliesPerComment` (type: `integer`):

Replies to fetch under each scraped comment (0 = none). Replies are rows too, linked to their parent by parentCommentId.

## `includeTranscript` (type: `boolean`):

Adds the video's spoken text from TikTok's own captions when the video has them. Videos without captions get transcript: null and are not charged for it.

## `transcriptLanguage` (type: `string`):

Preferred caption language code, e.g. en, es, de. Falls back to the auto-generated captions, then to any available language.

## `trackGrowth` (type: `boolean`):

Remember each profile's and video's numbers and add a growth block on the next run: change in followers, likes, videos, plays, comments, shares and saves since the previous run, per day and in percent. Schedule it daily or weekly to track influencers or campaigns.

## `monitorName` (type: `string`):

Required for growth tracking. Runs with the same name compare against each other. History is kept in the key-value store tiktok-growth-<name> on your account.

## `maxConcurrency` (type: `integer`):

Profiles / videos fetched in parallel.

## `proxyConfiguration` (type: `object`):

Apify Proxy is recommended. The scraper starts on your choice and switches to residential proxies by itself if TikTok starts blocking.

## Actor input object example

```json
{
  "profiles": [
    "mrbeast",
    "@khaby.lame"
  ],
  "videos": [
    "https://www.tiktok.com/@tiktok/video/7106594312292453675"
  ],
  "maxCommentsPerVideo": 0,
  "maxRepliesPerComment": 0,
  "includeTranscript": false,
  "transcriptLanguage": "en",
  "trackGrowth": false,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `profiles` (type: `string`):

One row per profile: followers, following, likes, videos, bio, bio link, emails, verified / private / business flags, average likes per video, and growth since the last run when tracking is on.

## `videos` (type: `string`):

One row per video: plays, likes, comments, shares, saves, engagement rate, plays per follower, author, music, hashtags, duration, cover, transcript, and growth when tracking is on.

## `comments` (type: `string`):

One row per comment or reply: text, likes, replies, date, author, and whether the creator liked or pinned it.

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

Per-input status (rows, not found, failures and why), skipped inputs, charged events and proxy statistics.

# 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": [
        "mrbeast",
        "@khaby.lame"
    ],
    "videos": [
        "https://www.tiktok.com/@tiktok/video/7106594312292453675"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("moonweil/tiktok-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 = {
    "profiles": [
        "mrbeast",
        "@khaby.lame",
    ],
    "videos": ["https://www.tiktok.com/@tiktok/video/7106594312292453675"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("moonweil/tiktok-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 '{
  "profiles": [
    "mrbeast",
    "@khaby.lame"
  ],
  "videos": [
    "https://www.tiktok.com/@tiktok/video/7106594312292453675"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call moonweil/tiktok-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,moonweil/tiktok-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/2iDIGFqidNSTnseYA/builds/QzfR6GZSUSjeRJQTd/openapi.json
