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

Scrape public TikTok comments and replies from any video — no browser, no login. Provide video URLs or numeric IDs and get comment text, likes, reply counts, timestamps, author info (username, nickname, ID, secUid), and parent-video metadata. Pay-per-comment .

- **URL**: https://apify.com/gopalakrishnan/tiktok-comments.md
- **Developed by:** [Gopalakrishnan](https://apify.com/gopalakrishnan) (community)
- **Categories:** Social media, Automation, AI
- **Stats:** 3 total users, 2 monthly users, 97.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 comment 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/platform/actors/running/actors-in-store#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

## TikTok Comments Scraper

Scrapes public TikTok comments (and optionally replies) from a list of video URLs or numeric IDs. Built as an Apify Actor using `got-scraping` — no browser required, fetching comments via unsigned API requests over plain datacenter proxies.

### Features

- Accepts full TikTok video URLs (e.g. `https://www.tiktok.com/@stoolpresidente/video/7473199106861796654`) or bare numeric video IDs (`7473199106861796654`).
- Returns detailed comment records: text, likes, reply counts, creation timestamp, creator-liked badge (`isAuthorLiked`), author info (username, nickname, avatar, ID, secUid).
- Supports recursive reply thread extraction (sub-comments) matching parent comments.
- Attaches parent-video metadata (`videoId`, `videoUrl`, `videoAuthor`, `videoDesc`) to every comment/reply record.
- Pay-Per-Event pricing: **No start fee** ($0.00) and a floor price of **$0.0003 per comment/reply scraped**.
- Graceful error handling for missing/invalid videos instead of failing the run.

### How it works

1. **Resolve Video details:** For each video, the Actor first fetches the HTML detail page using `got-scraping` + datacenter proxy to extract the video's rehydration JSON (`__UNIVERSAL_DATA_FOR_REHYDRATION__`). This verifies the video exists and obtains metadata (author, description) + the canonical `aweme_id` (video ID).
2. **Fetch Comments:** It paginates the unsigned TikTok comment list API (`/api/comment/list/`) using plain datacenter proxies with rotated session IDs. It implements a retry backoff strategy for transient empty pages to ensure completeness.
3. **Fetch Replies (Optional):** If `includeReplies` is enabled, for each top-level comment that has `reply_comment_total > 0`, it paginates the TikTok comment reply API (`/api/comment/list/reply/`) to extract all replies.
4. **Cap and Push:** Both comments and replies are streamed into the dataset. The total comments count respects `maxCommentsPerPost`.

### Input

| Field | Type | Description |
|-------|------|-------------|
| `postUrls` | array (required) | TikTok videos to scrape. Each item may be a bare numeric video ID (`7473199106861796654`) or a full video URL (`https://www.tiktok.com/@stoolpresidente/video/7473199106861796654`). |
| `maxCommentsPerPost` | integer (optional) | Cap the number of comments (and replies, if included) fetched per video. Defaults to `100`. |
| `includeReplies` | boolean (optional) | When enabled, also fetch replies (sub-comments) for each comment. Defaults to `false`. |
| `proxyConfiguration` | object | Proxy settings. Datacenter proxies are sufficient. Defaults to `{ "useApifyProxy": true }`. |

Example:

```json
{
    "postUrls": [
        "https://www.tiktok.com/@stoolpresidente/video/7473199106861796654",
        "7473199106861796654"
    ],
    "maxCommentsPerPost": 100,
    "includeReplies": true,
    "proxyConfiguration": { "useApifyProxy": true }
}
```

### Output

One flat record per comment/reply:

| Field | Type | Description |
|-------|------|-------------|
| `commentId` | string | Unique TikTok comment ID |
| `text` | string or null | Comment body text |
| `likeCount` | integer or null | Number of likes on the comment |
| `replyCount` | integer or null | Number of replies to this comment |
| `createTime` | integer or null | Unix timestamp (seconds) of creation |
| `createTimeISO` | string or null | ISO 8601 string of creation time |
| `isAuthorLiked` | boolean | `true` if the video creator liked this comment |
| `authorUniqueId` | string or null | Author handle / username |
| `authorNickname` | string or null | Author nickname |
| `authorId` | string or null | Numeric author user ID |
| `authorSecUid` | string or null | Author security UID |
| `authorAvatar` | string or null | URL of the author's avatar thumbnail |
| `parentCommentId` | string or null | Parent comment ID if `isReply` is true |
| `replyToReplyId` | string or null | ID of the specific reply this comment is replying to, if nested |
| `isReply` | boolean | `true` if this record is a reply, `false` if it is a top-level comment |
| `commentUrl` | string or null | Direct URL link to the comment |
| `videoId` | string or null | TikTok Video ID |
| `videoUrl` | string | URL of the TikTok video |
| `videoAuthor` | string or null | Handle of the video creator |
| `videoDesc` | string or null | Description of the video |
| `scrapeStatus` | string | `success` or `error` |
| `scrapeError` | string or null | Error details if `scrapeStatus` is `error` |

### Pay-Per-Event billing

| Event | When charged | No discount | Bronze | Silver | Gold |
|-------|--------------|-------------|--------|--------|------|
| `actor-start` | Once per run (flat start fee). | $0.00 | $0.00 | $0.00 | $0.00 |
| `comment` | Once per comment or reply successfully scraped. | $0.0003 | $0.00027 | $0.00024 | $0.00021 |

Base pricing matches the category floor ($0.0003 per comment) with a $0 flat start fee. The Bronze/Silver/Gold tiers apply automatically based on the user's Apify Store membership level.

Set the prices for these events in the Apify Console. Event names must match the `Actor.charge` calls in `src/main.js` exactly.

### Running locally

```bash
apify run --purge
```

Configure your test input in `storage/key_value_stores/default/INPUT.json`. Local runs store results on disk (`storage/datasets/default/`) and do not sync to the Apify Console.

# Actor input Schema

## `postUrls` (type: `array`):

List of TikTok videos to scrape comments from. Each item can be a full video URL (e.g. 'https://www.tiktok.com/@stoolpresidente/video/7473199106861796654') or a bare numeric video id.

## `maxCommentsPerPost` (type: `integer`):

Maximum number of comments (and replies, if included) to fetch per video. Useful for capping cost.

## `includeReplies` (type: `boolean`):

When enabled, also fetch replies (sub-comments) for each top-level comment that has any. Replies count toward maxCommentsPerPost and are billed the same as comments.

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

Proxy settings for the crawler. Datacenter (basic Apify Proxy) is sufficient for TikTok comments; residential is not required.

## Actor input object example

```json
{
  "postUrls": [
    "https://www.tiktok.com/@stoolpresidente/video/7473199106861796654"
  ],
  "maxCommentsPerPost": 100,
  "includeReplies": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `comments` (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 = {
    "postUrls": [
        "https://www.tiktok.com/@stoolpresidente/video/7473199106861796654"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("gopalakrishnan/tiktok-comments").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 = { "postUrls": ["https://www.tiktok.com/@stoolpresidente/video/7473199106861796654"] }

# Run the Actor and wait for it to finish
run = client.actor("gopalakrishnan/tiktok-comments").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "postUrls": [
    "https://www.tiktok.com/@stoolpresidente/video/7473199106861796654"
  ]
}' |
apify call gopalakrishnan/tiktok-comments --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=gopalakrishnan/tiktok-comments",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/dLScxSBGaU0bnv3rc/builds/fkkxDgV0UFaTnq7vq/openapi.json
