# TikTok Comments Scraper (`sfoln/tiktok-video-comments`)

Scrape comments from public TikTok videos and photo posts: text, date, likes, reply count, pinned flag and commenter handle, one JSON record per comment. Paste video URLs, short links or IDs. $0.30 per 1,000 comments + $0.003 per page of ~20. No login or cookies needed.

- Family: Social media data
- Categories: Social media, Videos, Automation
- Availability: on request (private on Apify). Email contact@sfoln.com with subject "Access request: TikTok Comments Scraper (sfoln/tiktok-video-comments)" before calling; calls fail until it is public.
- JSON: https://www.sfoln.com/actors/tiktok-video-comments.json
- MCP: https://mcp.apify.com?tools=sfoln/tiktok-video-comments
- REST (sync): POST https://api.apify.com/v2/actors/sfoln~tiktok-video-comments/run-sync-get-dataset-items
- REST (async): POST https://api.apify.com/v2/actors/sfoln~tiktok-video-comments/runs

TikTok Comments Scraper gets comments from public TikTok videos and photo posts, one normalized record per comment: comment ID, text, date, likes, reply count, pinned flag, language, and the commenter's handle, nickname and IDs. The video summary also reports TikTok's total comment count. It's built for audience and sentiment research, community management, giveaway draws, product feedback mining and AI agents.

## Price per delivered record

| Event | Price | Per 1,000 | Charged for |
| --- | --- | --- | --- |
| TikTok comment (`tiktok-comment`) | $0.0003 | $0.30 / 1,000 | Charged once per comment delivered as a dataset record. Video summary records are never charged. |
| TikTok comments page (`tiktok-comments-query`) | $0.003 | $3 / 1,000 | Charged once per page of comments (about 20) that delivered at least one new comment. Covers the per-request upstream fee. Also charged for an empty page the upstream billed (when the budget covers it). |

Pay-per-event, USD, billed by Apify; no platform usage charge. Only records with status `ok` are charged. Cap a run with `maxTotalChargeUsd`. Apify free plan: up to 10 per run.

## Run

```bash
curl -X POST "https://api.apify.com/v2/actors/sfoln~tiktok-video-comments/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"videos":["https://www.tiktok.com/@randomspamvideos25/video/7251387037834595630"],"maxCommentsPerVideo":20}'
```

MCP client configuration:

```json
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=sfoln/tiktok-video-comments"
    }
  }
}
```

Example prompt: Get up to 100 comments of https://www.tiktok.com/@randomspamvideos25/video/7251387037834595630 and summarize what viewers like and dislike.

## Input

Enter TikTok video URLs. Each video produces one dataset record per comment plus one summary record per video.

| Field | Type | Default | Meaning |
| --- | --- | --- | --- |
| `videos` (required) | array | — | Video URLs: TikTok video or photo URLs (https://www.tiktok.com/@user/video/…), vm.tiktok.com short links, or numeric video IDs. Full URLs work best. Duplicates are removed. Accounts on the Apify free plan can process up to 10 videos per run. |
| `maxCommentsPerVideo` | integer | `50` | Max comments per video: How many comments to return per video (1–500). Each delivered comment is one charged event, plus one page event per page of about 20. |
| `maxVideos` | integer | `100` | Max videos: Safety cap on the number of videos processed in this run. |
| `concurrency` | integer | `4` | Concurrency: How many videos are fetched in parallel (1–8). |
| `itemTimeoutSecs` | integer | `600` | Time limit per input (seconds): Pagination for one video stops cleanly shortly before this limit (60–3600). Raise it for very large per-input limits. |
| `includeRaw` | boolean | `false` | Include raw upstream response: Attach the unmodified provider object to each result record. |

Example input:

```json
{
  "videos": [
    "https://www.tiktok.com/@randomspamvideos25/video/7251387037834595630"
  ],
  "maxCommentsPerVideo": 20
}
```

## Output

One record per input item with `status` (`ok` is charged; `not_found`, `error`, `skipped_*` are free) and `charged`. The run stores an `OUTPUT` summary record.

| Field | Type | Meaning |
| --- | --- | --- |
| `input` | string | object | Input: The video URL or ID as provided. |
| `recordType` | string | Record type: comment (one per delivered comment, charged) \| video (one summary per video, never charged) |
| `position` | integer | Position: 1-based position of the comment within its input |
| `videoId` | string | null | Video ID |
| `videoUrl` | string | null | Video URL: URL sent upstream |
| `totalComments` | number | null | Total comments: Summary records only: TikTok's reported comment count. |
| `commentId` | string | null | Comment ID |
| `text` | string | null | Text |
| `createdAt` | string | null | Created at: ISO 8601 UTC |
| `likes` | number | null | Likes |
| `repliesCount` | number | null | Replies |
| `isPinned` | boolean | null | Pinned |
| `isLikedByCreator` | boolean | null | Liked by creator |
| `language` | string | null | Language |
| `authorHandle` | string | null | Author handle |
| `authorNickname` | string | null | Author nickname |
| `authorId` | string | null | Author ID |
| `authorSecUid` | string | null | Author secUid |
| `rowsDelivered` | integer | Comments delivered: Summary records only. |
| `pagesFetched` | integer | Pages fetched: Summary records only. |
| `pagesCharged` | integer | Pages charged: Summary records only. |
| `reachedEnd` | boolean | Reached end: Summary records only: the upstream reported no further pages. |
| `stopReason` | string | Stop reason: Summary records only: limit \| end \| budget \| max_pages \| deadline \| empty_pages \| error |
| `status` | string | Status: ok \| not_found \| error \| skipped_invalid \| skipped_budget \| skipped_free_plan |
| `charged` | boolean | Charged |
| `chargedEvent` | string | Charged event |
| `error` | object | Error |
| `warnings` | array | Warnings |
| `source` | string | Source |
| `fetchedAt` | string | Fetched at |

Example record:

```json
{
  "input": "https://www.tiktok.com/@stoolpresidente/video/7517114944362499342",
  "recordType": "comment",
  "position": 1,
  "videoId": "7517114944362499342",
  "videoUrl": "https://www.tiktok.com/@stoolpresidente/video/7517114944362499342",
  "commentId": null,
  "text": "DAVE BUY A TEAM",
  "createdAt": "2025-06-18T03:22:12.000Z",
  "likes": 3322,
  "repliesCount": 14,
  "isPinned": null,
  "isLikedByCreator": null,
  "language": "en",
  "authorHandle": "dimebag.duster",
  "authorNickname": "Robert Lessner",
  "authorId": "6958917445306926086",
  "authorSecUid": "MS4wLjABAAAA9rB4k_Ei3NexA5p2lb8naaa4LTgNCOdY0W9NHVo63016XkdsuZgvjkgolBnUkG8W",
  "status": "ok",
  "charged": true,
  "chargedEvent": "tiktok-comment",
  "source": "scrapecreators",
  "fetchedAt": "2026-10-14T10:00:00.000Z"
}
```

## Related

- [TikTok User Videos Scraper](https://www.sfoln.com/actors/tiktok-user-videos.md) (`sfoln/tiktok-user-videos`)
- [TikTok Search Scraper – Videos by Keyword](https://www.sfoln.com/actors/tiktok-search.md) (`sfoln/tiktok-search`)
- [YouTube Comments Scraper](https://www.sfoln.com/actors/youtube-video-comments.md) (`sfoln/youtube-video-comments`)
- [Instagram Comments Scraper (No Login)](https://www.sfoln.com/actors/instagram-post-comments.md) (`sfoln/instagram-post-comments`)

Publisher: SFOLN LLC, contact@sfoln.com. Catalogue: https://www.sfoln.com/catalog.json. Agent guide: https://www.sfoln.com/agents.md.
