# TikTok Comments Scraper (`calm_builder/tiktok-comments-scraper`) Actor

Scrape TikTok comments and replies from any video, profile, hashtag or search. Get comment text, likes, replies, date, language, mentions and commenter, with the video on every row. Sort by most liked or newest, filter by date, likes or keywords.

- **URL**: https://apify.com/calm_builder/tiktok-comments-scraper.md
- **Developed by:** [Coder](https://apify.com/calm_builder) (community)
- **Stats:** 7 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 comment or reply scrapeds

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 Comments Scraper

Scrape TikTok comments and replies as clean, structured data.

Add video links, or profiles, hashtags and search keywords to collect the comments of their videos. Export the results as JSON, CSV or Excel, or pull them through the Apify API. Results appear in your dataset while the run is still going.

### What This Actor Does

- Collects **comments** with text, likes, reply count, date, language, pinned and liked-by-creator flags, and **@mentions**
- Collects **replies** too, with their own limit, each linked to the comment it answers
- Saves the **commenter**: username, name, verified badge, profile link and avatar
- Can also save **full video details** (views, likes, shares, date, music, creator) in a separate Videos table
- Puts the **video** on every row (`videoId`, `videoUrl`, `videoAuthor`, `videoCaption`), so each row stands on its own
- Marks comments and replies **written by the video's creator** (`isByVideoCreator`)
- Works from **video links**, or from **profiles, hashtags and search keywords** (it finds their videos for you)
- **Most liked** and **Newest** comment order, **date, like and keyword filters** and country selection are **included at no extra cost**
- One row per comment and per reply by default (spreadsheet-ready), or replies **nested inside their comment** with one switch

### Best For

- Sentiment analysis and AI training data
- Brand, product and campaign monitoring
- Finding purchase intent and questions (`price`, `where to buy`, `link`)
- Influencer audience research and engagement audits
- Community management: the most-liked comments and the creator's own replies

### Input

| Field                  | What it does                                                                                       |
| ---------------------- | -------------------------------------------------------------------------------------------------- |
| `videoUrls`            | TikTok video links, including short `vm.tiktok.com` links                                          |
| `profiles`             | Usernames or profile links. The comments of their latest videos are collected                     |
| `hashtags`             | Hashtags, with or without `#`                                                                      |
| `searchQueries`        | Keywords to search TikTok videos for                                                               |
| `resultsPerPage`       | Videos to take from each profile, hashtag or keyword (default 5)                                   |
| `newerThan`            | For profiles, hashtags and keywords: only videos posted after this date                           |
| `maxCommentsPerVideo`  | Top-level comments per video (default 100)                                                         |
| `maxRepliesPerComment` | Replies per comment (default 0 = no replies)                                                       |
| `commentSort`          | `default` (TikTok's order), `mostLiked` or `newest`                                                |
| `commentsAsThreads`    | `false` (default): one row per comment and per reply. `true`: replies nested inside their comment |
| `includeVideoDetails`  | Also save each video (views, likes, shares, date, music, creator...) in a separate **Videos** table |
| `commentsNewerThan`    | Only comments posted after this date. Accepts a date (`2026-06-01`) or a period (`7 days`)         |
| `minCommentLikes`      | Only comments with at least this many likes                                                        |
| `commentKeywords`      | Only comments containing one of these words or phrases                                             |
| `country`              | Collect as TikTok shows it in this country (default United States)                                 |

#### Example input

```json
{
  "videoUrls": ["https://www.tiktok.com/@gordonramsayofficial/video/7229884545150061851"],
  "profiles": ["nike"],
  "resultsPerPage": 5,
  "maxCommentsPerVideo": 200,
  "maxRepliesPerComment": 5,
  "commentSort": "mostLiked"
}
```

### Output

By default every comment and every reply is its own row. Replies have `type: "reply"` and `parentCommentId`, the ID of the comment they sit under, so you can rebuild every thread in a spreadsheet. Turn on **Nest replies inside their comment** to get one row per comment with its replies in a `replies` list instead.

Comments are always the main table. Turn on **Include video details** to also get a **Videos** table on the run's **Output** tab, with one row per video: views, likes, comment count, shares, saves, post date, caption, hashtags, music, cover and the creator's profile. Match comments to videos on `videoId` = `id`.

#### Comment fields

| Field                                                                         | Description                                                    |
| ----------------------------------------------------------------------------- | -------------------------------------------------------------- |
| `type`                                                                        | `comment` or `reply`                                           |
| `id`, `text`, `createdAt`, `language`                                         | The comment                                                    |
| `likeCount`, `replyCount`                                                     | Engagement                                                     |
| `isPinned`, `isLikedByCreator`, `isByVideoCreator`                            | Flags                                                          |
| `mentions`                                                                    | Mentioned accounts: name as typed, user ID and secUid          |
| `author`                                                                      | Commenter: ID, username, name, verified, secUid, profile link, avatar |
| `parentCommentId`, `replyToCommentId`                                         | Replies only: the comment they sit under, and the one they answer |
| `videoId`, `videoUrl`, `videoAuthor`, `videoCaption`                          | The video the comment belongs to                               |
| `source`                                                                      | The input the video came from                                  |
| `replies`                                                                     | Nested replies (only with **Nest replies inside their comment**) |

#### Example output

```json
{
  "type": "reply",
  "id": "7230818143198921499",
  "text": "the butteriest burger i ever seen",
  "createdAt": "2023-05-08T14:27:43Z",
  "likeCount": 539,
  "replyCount": 0,
  "isPinned": false,
  "isLikedByCreator": false,
  "language": "en",
  "mentions": [],
  "author": {
    "id": "6607828058173947909",
    "username": "meryy_690",
    "isVerified": false,
    "profileUrl": "https://www.tiktok.com/@meryy_690"
  },
  "parentCommentId": "7230126412157289259",
  "replyToCommentId": "7230126412157289259",
  "isByVideoCreator": false,
  "videoId": "7229884545150061851",
  "videoUrl": "https://www.tiktok.com/@gordonramsayofficial/video/7229884545150061851",
  "videoAuthor": "gordonramsayofficial",
  "videoCaption": "When in #australia....you cook up a delicious Wagyu #Burger with Cheese ! 🤤 #TikTokCooks"
}
```

### How To Use

1. Add video links, or profiles, hashtags or keywords (or a mix).
2. Set **Maximum comments per video**, and **Maximum replies per comment** if you want replies.
3. Optionally choose **Most liked** or **Newest**, and add filters.
4. Run the Actor and open the **Output** tab, export the results, or read them through the Apify API.

### Pricing

This Actor uses pay-per-event pricing, so you only pay for results you receive:

- **Comment**: each comment or reply saved to your dataset. With nested replies, each reply is still charged as one comment
- **Video**: each video row, only when **Include video details** is on
- **Actor start**: a small fee each time a run starts

With **Include video details** off (the default), videos are never charged. Comment order, filters and country selection are **included at no extra cost**, and you are charged only for comments that pass your filters. Current prices for each Apify plan are shown on the Actor's Pricing tab.

If a run reaches the maximum cost you set for it, it stops cleanly and keeps everything collected so far.

#### Free plan

On the Apify free plan every feature is available to try, with smaller amounts per run: up to **3** inputs, **3** videos per profile, hashtag or keyword, **20** comments per video and **5** replies per comment. Upgrade to a paid Apify plan to remove these limits.

### Best Practices

- Start with a small **Maximum comments per video** to check the output quickly.
- For monitoring, schedule the Actor with **Only comments newer than** (for example `24 hours`) to get only new comments.
- Use **Most liked** to get the comments that matter most without collecting thousands.
- Keep replies at **0** unless you need them: popular comments can have hundreds of replies.

### FAQ

#### How many comments can I get from one video?

Thousands. Popular videos regularly return 2,000+ comments plus their replies.

#### How do Most liked and Newest work?

The Actor reads up to 1,000 comments of each video and returns the most-liked or most recent ones. It takes a few seconds longer per video, and you are only charged for the comments returned.

#### Why did a video return fewer comments than I asked for?

The video may have fewer comments, the creator may have turned comments off, or fewer comments matched your filters. The run log names those videos.

#### Why do mentions have a name but no username?

TikTok stores a mention as the name typed in the comment plus the account's ID. Both are included.

### Responsible Use

This Actor collects publicly available data only. Make sure your use complies with TikTok's terms, applicable laws and data-protection rules such as the GDPR, especially when you process personal data.

### Troubleshooting

- **A link was skipped**: make sure it is a TikTok video link (`tiktok.com/@user/video/...`) or a short `vm.tiktok.com` link.
- **No comments from a video**: the creator may have turned comments off, or nothing matched your filters.

If something still does not work, open an issue on the Actor's Issues tab with your run link and we will take a look.

# Actor input Schema

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

TikTok video or photo post links, one per row.

Supported formats:

- `https://www.tiktok.com/@khaby.lame/video/7354016355398012192`
- `https://vm.tiktok.com/ZMxxxxxx/` (short links)

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

TikTok usernames or profile links, one per row (`khaby.lame`, `@khaby.lame` or a profile link). The comments of each profile's latest videos are collected.

## `hashtags` (type: `array`):

Hashtags, one per row, with or without the `#`. The comments of the hashtag's videos are collected.

## `searchQueries` (type: `array`):

Keywords to search TikTok videos for, one per row, e.g. `iphone 17 review`. The comments of the videos found are collected.

## `resultsPerPage` (type: `integer`):

How many videos to take from **each** profile, hashtag or search keyword. Video links always count as one video each.

## `newerThan` (type: `string`):

For profiles, hashtags and keywords: skip videos posted before this date. Pick a date, or enter a relative period such as `7 days`. Does not apply to video links.

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

How many top-level comments to collect from **each** video. Replies are counted separately below.

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

How many replies to collect under **each** comment. Set to **0** for no replies. Every reply is a result and is charged like a comment.

## `commentSort` (type: `string`):

Which comments to collect first.

- **TikTok's order** — the order the TikTok app shows (fastest)
- **Most liked** — the most-liked comments of each video
- **Newest** — the most recent comments of each video

**Most liked** and **Newest** read up to 1,000 comments per video to pick from, so they take a few seconds longer per video. You are charged only for the comments returned.

## `commentsAsThreads` (type: `boolean`):

Off (default): every comment and every reply is its own row, with `type` (`comment` or `reply`) and `parentCommentId` - best for spreadsheets.

On: one row per comment, with its replies inside the `replies` field - best for JSON and code. Pricing is the same either way.

## `includeVideoDetails` (type: `boolean`):

Also save each video in a separate **Videos** table: views, likes, comment count, shares, saves, post date, caption, hashtags, music, cover and the creator's profile. Comments link to it through `videoId`.

Each video row is charged as a video result. Every comment row already shows its video's link, ID, creator and caption at no extra cost.

## `commentsNewerThan` (type: `string`):

Skip comments posted before this date. Pick a date, or enter a relative period such as `24 hours` or `7 days`. Ideal for monitoring.

## `minCommentLikes` (type: `integer`):

Only return comments with at least this many likes. Leave empty to keep all.

## `commentKeywords` (type: `array`):

Only return comments containing at least one of these words or phrases (not case-sensitive), e.g. `price`, `where to buy`. Leave empty to keep all.

## `country` (type: `string`):

Collect results as TikTok shows them in this country. Included at no extra cost.

The default, **United States**, gives the most complete results.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.tiktok.com/@gordonramsayofficial/video/7229884545150061851"
  ],
  "resultsPerPage": 5,
  "maxCommentsPerVideo": 100,
  "maxRepliesPerComment": 5,
  "commentSort": "default",
  "commentsAsThreads": false,
  "includeVideoDetails": false,
  "country": "US"
}
```

# Actor output Schema

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

No description

## `videos` (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 = {
    "videoUrls": [
        "https://www.tiktok.com/@gordonramsayofficial/video/7229884545150061851"
    ],
    "maxRepliesPerComment": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("calm_builder/tiktok-comments-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 = {
    "videoUrls": ["https://www.tiktok.com/@gordonramsayofficial/video/7229884545150061851"],
    "maxRepliesPerComment": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("calm_builder/tiktok-comments-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 '{
  "videoUrls": [
    "https://www.tiktok.com/@gordonramsayofficial/video/7229884545150061851"
  ],
  "maxRepliesPerComment": 5
}' |
apify call calm_builder/tiktok-comments-scraper --silent --output-dataset

```

## MCP server setup

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