# TikTok Comments API: Export Comments & Replies (`deepmine/tiktok-comments-scraper`) Actor

TikTok comments scraper: get the comments and replies of TikTok videos from video URLs, IDs, short links or creators' profiles. Text, likes, replies, time, the commenter's name, photo, username and badge, language and mentions when shown, buyers flagged, optional bio and followers. No login.

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

## Pricing

from $0.25 / 1,000 comments

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 API

A **TikTok comments scraper** for any video: paste video URLs, IDs or short links (or a creator's profile) and get **the comments and their replies that TikTok shows** as clean rows: likes, reply counts, post time, each comment's share link, the commenter's name, photo, username and badge, language, mentions, images, stickers and photo or video replies when the comment has them, and (optional) the commenter's bio, follower counts and large photo.

| 💬 Comment | 🧩 Type | ↪️ Reply | ❤️ Likes | ↩️ Replies | 📅 Posted | 🛒 Purchase Intent | 🔗 Video |
|---|---|---|---:|---:|---|---|---|
| Bro was ai before ai | Text | – | 1,708,011 | 815 | 2026-06-25 | – | [@zachking](https://www.tiktok.com/@zachking/video/7655004069190192398) |
| 2m | Text | ✔️ | 2,360 | – | 2026-06-25 | – | [@zachking](https://www.tiktok.com/@zachking/video/7655004069190192398) |
| Ninja doesn’t want us to have any money.😩 | Text | – | 776 | 10 | 2026-06-22 | – | [@ninjakitchen](https://www.tiktok.com/@ninjakitchen/video/7653941272524115231) |
| Just got mine today!!! It’s like Christmas | Image | – | 90 | 13 | 2026-06-25 | – | [@ninjakitchen](https://www.tiktok.com/@ninjakitchen/video/7653941272524115231) |
| Price please | Text | – | 0 | 2 | 2026-09-04 | ✔️ | [@ninjakitchen](https://www.tiktok.com/@ninjakitchen/video/7653941272524115231) |
| 299 I just bought it at Costco | Text | ✔️ | 0 | – | 2026-09-04 | – | [@ninjakitchen](https://www.tiktok.com/@ninjakitchen/video/7653941272524115231) |

<sub>Collected 2026-10-01 with the prefilled input: 91 rows (50 comments, 41 replies) from 2 videos in a 46-second run, 83 of them in English. The commenter's name, photo, username, profile link and ids and the comment link came on 91 of 91 rows, the video caption on 91 of 91; text on 89 of 91 (the other 2 are 1 sticker and 1 image, labelled in `commentType`); 2 buyer comments were marked as purchase intent, all real buying questions. Commenters are left out of this page only.</sub>

**$0.29 per 1,000 comments on the Starter plan ($0.29 Free, $0.28 Scale, $0.28 Business)**, replies counted as comments, commenter profiles included. The prefilled run (2 videos, 25 comments and 1 reply each) costs about $0.03.

### Why this one

- **Comments and replies in one table.** Each reply sits right under its comment, marked `isReply`, with `parentCommentId` pointing at the comment (and `replyToCommentId` at the reply it answers, when it answers one), so threads stay readable in a spreadsheet.
- **Videos or whole profiles.** Paste video links, or usernames to get the comments of each creator's latest, most popular or oldest videos (reposts too), with date filters and pinned videos in or out. Looking up the profiles and their videos is free.
- **TikTok's own order.** Top comments first, as the app shows them, with `rank` for each; replies in the order TikTok lists them.
- **No login, no cookies.** Only what TikTok shows logged-out visitors. No account of yours is ever used.
- **Everything about the comment and the commenter.** The comment's share link, the video's caption, the commenter's name, photo, username, verified badge and secUid (on 99.8% of test rows; the rest came without an account); mentions (with the mentioned people's ids), images, stickers, and the photo or video post a commenter answered with, labelled in `commentType`, so no row is a blank you can't explain. Turn on **Commenter profiles** to add each commenter's large photo, bio, bio link, followers, following, likes, video count, join date and whether the bio shows an email or phone, at no extra charge.
- **Spot buyers.** `isHighPurchaseIntent` marks comments that ask where or how to buy, the price, a link, shipping or a catalog, or say the writer wants to buy. It's our own strict check of the text, not TikTok's flag: on 23 product videos it marked 312 of 1,518 comments, and about 99% of those really were buying questions; on 1,142 comments of entertainment videos it marked none (TikTok's own flag marked 162 there, none about buying). "I need this" alone doesn't count.
- **$0.28 to $0.29 per 1,000 comments.** No start fee, and commenter profiles cost nothing extra.
- **Pay for rows, not attempts.** Deleted videos, videos with comments off and invalid links are listed in the run summary and cost nothing; so would a comment with nothing in it (no text, image, sticker or post): it's counted as `emptySkipped` and doesn't use up a place in `maxCommentsPerVideo`.

### Input

| Field | What it does | Default |
|---|---|---|
| `videos` | Video URLs, vm.tiktok.com short links or video IDs, one per line. | 2 example videos when neither `videos` nor `profiles` is given |
| `maxCommentsPerVideo` | Top-level comments per video, top comments first. Replies come on top. | 25 |
| `includeReplies` | Also get the replies to each comment, right under it. | off (on in the form) |
| `maxRepliesPerComment` | With `includeReplies`: replies per comment. | 5 (1 in the form) |
| `commenterProfiles` | Also read each commenter's profile: large photo, bio, bio link, followers, following, likes, videos, join date, email or phone in the bio. Free but slower (1-2 seconds per new commenter). | off |
| `profiles` | Usernames or profile URLs: the comments of each creator's newest videos. | none |
| `videosPerProfile` | Videos per profile. | 10 |
| `profileSorting` | `latest` (newest first, pinned on top), `popular` (most played first) or `oldest`, as the profile's tabs. A date range with `popular` still applies but reads the whole Popular list (slower). | `latest` |
| `profileSections` | `videos`, `reposts` (videos they reposted) or both. | `["videos"]` |
| `postedAfter` | Profiles: only videos posted after this date (`YYYY-MM-DD`) or within a relative time (`7 days`). | all |
| `postedBefore` | Profiles: only videos posted before this date (the whole day counts). | all |
| `excludePinnedPosts` | Profiles: leave out pinned videos. | off |
| `proxyConfiguration` | Apify Proxy. Datacenter (the default) works; switch to residential only if a run reports blocks. | Apify datacenter |

Example:

```json
{
  "videos": [
    "https://www.tiktok.com/@zachking/video/7655004069190192398",
    "https://vm.tiktok.com/ZMabc1234/"
  ],
  "maxCommentsPerVideo": 500,
  "includeReplies": true,
  "maxRepliesPerComment": 10
}
```

Or the newest videos of creators:

```json
{
  "profiles": ["zachking", "https://www.tiktok.com/@nativetyfood"],
  "videosPerProfile": 5,
  "postedAfter": "2026-09-01",
  "maxCommentsPerVideo": 100
}
```

### Output

One row per comment or reply, video by video in the order of your links (then each profile's videos, newest first). Three table views in the Console:

- **📊 Overview**: 🖼️ Photo, 🏷️ Username, 💬 Comment, 🧩 Type, 🔗 Comment, 🔗 Video, ↪️ Reply, ❤️ Likes, ↩️ Replies, 📅 Posted, 🏅 Rank, 🌐 Language
- **📈 Stats**: 🏷️ Username, 🔗 Video, ↪️ Reply, 💖 Creator Liked, 🛒 Purchase Intent, ✔️ Verified, ❤️ Likes, ↩️ Replies, 📅 Posted, 🏅 Rank
- **👤 Commenter Profiles** (with Commenter profiles on): 🖼️ Photo, 🏷️ Username, 👤 Commenter, ✔️ Verified, 👥 Followers, ❤️ Commenter Likes, 🎬 Commenter Videos, 🔒 Private, 📝 Commenter Bio, 📅 Joined, 💬 Comment

#### Output fields

Every row has these keys, in this order (the `commenter...` profile keys only with Commenter profiles on). A value TikTok didn't send is `null` (never an empty string or a made-up 0).

- `commenterAvatar`: the commenter's profile picture (TikTok's signed link; it stops working about a day after the run, so save the image the same day if you need it).
- `commenterName`: the commenter's display name.
- `text`: the comment's full text, emoji included (`null` when the comment is only a sticker, an image or a post; `commentType` says which).
- `textSnippet`: its first 50 characters on one line, for tables.
- `commenterUsername`: the commenter's TikTok username, without @.
- `commenterUrl`: the commenter's profile on TikTok.
- `videoUrl`: the video the comment is on.
- `commentUrl`: the comment's share link, as TikTok's own Share button gives it: the video's page with the comment's id (`share_comment_id`). TikTok's website opens the video with it, not the comment itself (checked in a logged-out browser, 2026-10-01).
- `commentType`: what the comment is: `Text`, `Image`, `Sticker`, or `Photo post` / `Video post` (the commenter answered with a TikTok post of their own; `text` is then empty and `imageUrls` or `commentPostUrl` hold it). A comment with text and an image or sticker says `Image` or `Sticker`.
- `isReply`: `true` for a reply to another comment.
- `isPinned`: pinned to the top of the comments by the video's creator, when TikTok says so; TikTok rarely tells logged-out visitors (0 of 2,660 test comments on 47 videos were marked pinned).
- `isLikedByCreator`: the video's creator liked the comment.
- `commenterVerified`: the commenter has a TikTok badge (verified account or popular creator).
- `isHighPurchaseIntent`: the comment asks where or how to buy it, its price, a link, shipping or a catalog, or says the writer wants to buy or order it. Our own check of the text, in English, Spanish, Portuguese, French, Italian, German, Russian, Arabic and Indonesian; strict on purpose ("I need this" alone or "I bought one" doesn't count; comments in other languages are never marked). TikTok's own purchase-intent flag isn't used: it marks ordinary chatter.
- `likes`: likes on the comment.
- `replies`: replies to the comment, as TikTok counts them (`null` on a reply).
- `postedAt`: when it was posted (UTC).
- `postedAtTimestamp`: the same time as a Unix timestamp (seconds).
- `rank`: a comment's place among the video's comments in TikTok's order; a reply's place among its comment's replies. 1 = first.
- `language`: the comment's language as TikTok detects it (`en`, `es`, ...); `null` when TikTok can't tell.
- `replyToUsername`: on a reply to another reply, the username of the person it answers; otherwise `null`.
- `mentions`: names mentioned in the comment, as written, without @ (TikTok writes a mention as the person's display name).
- `mentionedUsers`: each person mentioned: `name`, `userId`, `secUid`, and `username` + `profileUrl` when TikTok gives them (for the person a reply answers).
- `hashtags`: hashtags written in the comment, without #; `null` when there are none, which is almost always (2 of 2,660 test comments had any).
- `imageUrls`: the pictures in the comment: an image comment's images, or the pictures of a photo post the commenter answered with (TikTok's signed links: comment images stop working 30 days after the run, photo-post pictures about 15 days after).
- `stickerUrl`: the sticker of a sticker comment, an animated WebP image (TikTok's signed link; it stops working 30 days after the run); otherwise `null`.
- `commentPostUrl`: for a `Photo post` / `Video post` comment, the TikTok post the commenter answered with; otherwise `null`.
- `commenterAvatarLarge`: the commenter's profile picture in the largest size their profile page shows (1080 px on all 42 readable test profiles; `commenterAvatar` is 100 px; TikTok's signed link, it stops working about 2 days after the run). Only with `commenterProfiles`.
- `commenterBio`: the commenter's bio. Only with `commenterProfiles`.
- `commenterBioLinkUrl`: the link in their bio. Only with `commenterProfiles`.
- `commenterFollowers`: their followers (exact). Only with `commenterProfiles`.
- `commenterFollowing`: accounts they follow. Only with `commenterProfiles`.
- `commenterLikes`: total likes on all their videos. Only with `commenterProfiles`.
- `commenterVideos`: their public videos. Only with `commenterProfiles`.
- `commenterPrivate`: their account is private (TikTok then shows nothing else). Only with `commenterProfiles`.
- `commenterHasEmail`: their bio shows an email address. Only with `commenterProfiles`.
- `commenterHasPhone`: their bio shows a phone number. Only with `commenterProfiles`.
- `commenterLanguage`: their TikTok app language (`en`, `es`, ...). Only with `commenterProfiles`.
- `commenterJoinedAt`: when their account was created (UTC). Only with `commenterProfiles`.
- `commentId`: TikTok's comment ID.
- `parentCommentId`: on a reply, the ID of the comment it replies to; `null` on a comment.
- `replyToCommentId`: on a reply to another reply, the ID of that reply (TikTok shows it as @name); otherwise `null`.
- `commenterId`: TikTok's user ID of the commenter.
- `commenterSecUid`: the commenter's secUid, the ID TikTok's own web API uses.
- `videoId`: TikTok's video ID.
- `videoCaption`: the caption of the video the comment is on, hashtags included. It comes with the comments; when TikTok leaves it out of a whole page, the Actor reads it from the video's page once, while the comments keep coming (`captionFromVideoPage` in the run summary). The video's first row doesn't wait for that read, so it can come without the caption (`rowsBeforeCaption`).
- `commentStatus`: TikTok's own status code for the comment: `1` on most comments, `11` on some replies (often spam or rude ones). TikTok doesn't document the codes.
- `input`: what you entered for this row, exactly as entered: the video URL or ID, a short link, or the profile the video was found on.
- `profileSection`: for a video found through a profile, the tab it came from: `videos`, or `reposts` (a video the creator reposted; its `videoUrl` names its own creator). `null` for videos you entered.
- `scrapedAt`: when it was collected (UTC).

Example rows (a buyer's question and the reply under it, from the prefilled run; the commenters' names, usernames, links, ids and photos are replaced here for privacy):

```json
[
  {
    "commenterAvatar": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/commenter_1.jpeg",
    "commenterName": "Commenter 1",
    "text": "Price please",
    "textSnippet": "Price please",
    "commenterUsername": "commenter_1",
    "commenterUrl": "https://www.tiktok.com/@commenter_1",
    "videoUrl": "https://www.tiktok.com/@ninjakitchen/video/7653941272524115231",
    "commentUrl": "https://www.tiktok.com/@ninjakitchen/video/7653941272524115231?share_comment_id=7681797564283355934&share_item_id=7653941272524115231",
    "commentType": "Text",
    "isReply": false,
    "isPinned": false,
    "isLikedByCreator": false,
    "commenterVerified": false,
    "isHighPurchaseIntent": true,
    "likes": 0,
    "replies": 2,
    "postedAt": "2026-09-04T21:38:27Z",
    "postedAtTimestamp": 1788557907,
    "rank": 24,
    "language": "en",
    "replyToUsername": null,
    "mentions": null,
    "mentionedUsers": null,
    "hashtags": null,
    "imageUrls": null,
    "stickerUrl": null,
    "commentPostUrl": null,
    "commentId": "7681797564283355934",
    "parentCommentId": null,
    "replyToCommentId": null,
    "commenterId": "7000000000000000001",
    "commenterSecUid": "MS4wLjABAAAAcommenter1",
    "videoId": "7653941272524115231",
    "videoCaption": "Hear that? That's the sound of perfectly crisp meals and easy cleanup. 🔥   With dishwasher-safe baskets and Dual Zone cooking, the NEW Ninja Crispi™ makes every meal a win. 🏆   #NinjaCRISPiDualZone #AirFryer #GlassAirFryer",
    "commentStatus": 1,
    "input": "https://www.tiktok.com/@ninjakitchen/video/7653941272524115231",
    "profileSection": null,
    "scrapedAt": "2026-10-01T19:11:57Z"
  },
  {
    "commenterAvatar": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/commenter_2.jpeg",
    "commenterName": "Commenter 2",
    "text": "299 I just bought it at Costco",
    "textSnippet": "299 I just bought it at Costco",
    "commenterUsername": "commenter_2",
    "commenterUrl": "https://www.tiktok.com/@commenter_2",
    "videoUrl": "https://www.tiktok.com/@ninjakitchen/video/7653941272524115231",
    "commentUrl": "https://www.tiktok.com/@ninjakitchen/video/7653941272524115231?share_comment_id=7681812021696185101&share_item_id=7653941272524115231",
    "commentType": "Text",
    "isReply": true,
    "isPinned": false,
    "isLikedByCreator": false,
    "commenterVerified": false,
    "isHighPurchaseIntent": false,
    "likes": 0,
    "replies": null,
    "postedAt": "2026-09-04T22:34:31Z",
    "postedAtTimestamp": 1788561271,
    "rank": 1,
    "language": "en",
    "replyToUsername": null,
    "mentions": null,
    "mentionedUsers": null,
    "hashtags": null,
    "imageUrls": null,
    "stickerUrl": null,
    "commentPostUrl": null,
    "commentId": "7681812021696185101",
    "parentCommentId": "7681797564283355934",
    "replyToCommentId": null,
    "commenterId": "7000000000000000002",
    "commenterSecUid": "MS4wLjABAAAAcommenter2",
    "videoId": "7653941272524115231",
    "videoCaption": "Hear that? That's the sound of perfectly crisp meals and easy cleanup. 🔥   With dishwasher-safe baskets and Dual Zone cooking, the NEW Ninja Crispi™ makes every meal a win. 🏆   #NinjaCRISPiDualZone #AirFryer #GlassAirFryer",
    "commentStatus": 1,
    "input": "https://www.tiktok.com/@ninjakitchen/video/7653941272524115231",
    "profileSection": null,
    "scrapedAt": "2026-10-01T19:11:57Z"
  }
]
```

With `commenterProfiles` on, each row also has (a real commenter, their bio and link replaced):

```json
{
  "commenterAvatarLarge": "https://p16-common-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/commenter_1~tplv-tiktokx-cropcenter:1080:1080.jpeg",
  "commenterBio": "(their bio)",
  "commenterBioLinkUrl": null,
  "commenterFollowers": 554,
  "commenterFollowing": 117,
  "commenterLikes": 1087,
  "commenterVideos": 47,
  "commenterPrivate": false,
  "commenterHasEmail": false,
  "commenterHasPhone": false,
  "commenterLanguage": "en",
  "commenterJoinedAt": "2022-02-05T12:54:45Z"
}
```

#### Run summary (`OUTPUT`)

```json
{
  "results": 99,
  "inputs": [
    {"input": "https://www.tiktok.com/@zachking/video/7655004069190192398", "status": "ok", "results": 49, "stopReason": "max_results", "videoComments": 105311, "comments": 25, "replies": 24},
    {"input": "7600000000000000999", "status": "not_found", "results": 0, "stopReason": "not_found", "error": "video not found"}
  ],
  "profiles": [
    {"input": "zachking", "status": "ok", "results": 125, "stopReason": "max_results", "username": "zachking", "videos": 5}
  ],
  "commenterProfiles": {"read": 25, "private": 7, "missing": 0, "failed": 0, "gaveUp": false}
}
```

`status` per video: `ok`, `partial` (TikTok stopped answering partway, on every retry: the comments read before it are delivered, `error` says where, and the status message counts it; a comment whose replies TikTok refused comes without them, `threadsWithoutReplies` counts those), `no_results` (the video has no comments, or TikTok lists none: free), `not_found` (deleted or unavailable), `invalid`, `blocked` (TikTok refused it on every retry; the run fails so you notice, and rows already collected stay), `stopped` (your spending limit), `timed_out` (the run's time limit; see below). `videoComments` is TikTok's own count for the video, replies included. The same video given twice (a URL and a short link, or a link and a profile) comes back, and is charged, once. Videos found on a profile carry `"profile"` and `"profileSection"` in their entry (and their rows say the same in `input` and `profileSection`), and `profiles` lists each profile (`ok`, `no_results` when no video matches your filters, `not_found`, `private`, `invalid`, `blocked`) with the videos found and the rows delivered. With Commenter profiles on, `commenterProfiles` counts the profiles read, private (only that flag is known), missing (deleted accounts) and failed (TikTok refused the page; after 10 refusals in a row the run stops asking and the comments still all come back).

### Good to know

- **Not every comment.** You get the comments TikTok shows logged-out visitors. TikTok's comment count for a video (`videoComments`) includes comments it hides or has deleted, so a full run returns fewer: on 12 product videos read to the end (2026-10-01), between 38% and 100% of the count came back, 82% for the median video. Those runs read comments only, and the count includes replies, which they didn't read.
- **How deep can it go?** TikTok pages comments 50 at a time and drops some from each page (deleted or hidden ones), so a page brings 25-36 comments; reply pages bring 16-25. `maxCommentsPerVideo` goes up to 50,000 and `maxRepliesPerComment` up to 1,000. A test run read 12,000 comments of one video in about 6.5 minutes (roughly 1,800 a minute per video; several videos run side by side). With replies on, count about one second per comment that has replies; with commenter profiles, 1-2 seconds per new commenter.
- **Big runs stop cleanly.** The default timeout is 6 hours. If a run gets near its timeout, it stops asking TikTok, delivers every comment already read, and says so in the status message (`timeLimitReached` in OUTPUT); raise the timeout in the run options or split the input to get the rest. Comments come back video by video in your order; while one video is being read, the next ones read ahead only a few thousand comments, so memory stays flat at 256 MB however deep you go.
- **Reply counts include deleted replies.** TikTok's `replies` number counts replies it no longer shows, so a comment can list fewer replies than its count.
- **Photo and video replies.** TikTok lets people answer a comment with a post of their own. Those replies have no text: the row says `Photo post` or `Video post`, with the post's link and, for a photo post, its pictures. On product videos many of them come from other sellers advertising.
- **Commenter profiles cost time, not money.** Each new commenter's profile is one more page (1-2 seconds; a live run read 63 profiles for 69 comments in under 2 minutes); a commenter who shows up twice is read once. TikTok doesn't show a commenter's region on its website to logged-out visitors, so rows don't include it.
- **Counts are exact.** Likes and reply counts come as TikTok sends them for comments, not rounded.

### Pricing

Pay per result, no start fee and no minimum. Example: 1,000 comments cost $0.29 on the Starter plan, with or without commenter profiles.

| Your Apify plan | Per 1,000 comments |
|---|---|
| Free | $0.29 |
| Starter | $0.29 |
| Scale | $0.28 |
| Business | $0.28 |

Each comment and each reply is one row. Videos without comments, deleted videos and invalid inputs cost nothing. When your spending limit is reached, the run stops.

### FAQ

**Do I need a TikTok account?** No. The Actor reads only what TikTok shows logged-out visitors.

**Can I get comments for every video of a creator or a hashtag?** For a creator, yes: put the username in `profiles` and set `videosPerProfile` (up to 1,000). For a hashtag or a search, get the video links first with [TikTok Profile & Videos API](https://apify.com/deepmine/tiktok-profile-videos), [TikTok Hashtag Videos API](https://apify.com/deepmine/tiktok-hashtag-videos) or [TikTok Video Search API](https://apify.com/deepmine/tiktok-video-search), then pass their `videoUrl` fields in here.

**What about what people say in the video itself?** Use [TikTok Transcript API](https://apify.com/deepmine/tiktok-transcripts) for the spoken words.

**Is it legal?** The Actor collects only public comments and never logs in. Comments are personal data under laws such as the GDPR: use them only for a legitimate purpose, and check with a lawyer if unsure.

### Feedback

Missing a field, or a result that doesn't look right? Open an issue on the **Issues** tab and we'll look into it. If the data helps you, a short review on this page helps other people find it.

# Actor input Schema

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

TikTok video links, vm.tiktok.com short links or video IDs, one per line. Or leave empty and add profiles below.

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

Top-level comments per video, top comments first (TikTok's order). Replies come on top. You pay per comment and per reply.

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

Each reply is its own row, right under its comment, and costs the same as a comment.

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

Used with Include replies. In TikTok's order.

## `commenterProfiles` (type: `boolean`):

Adds each commenter's large photo, bio, bio link, followers, following, likes, video count, join date and whether the bio shows an email or phone. Free, but slower (one lookup per commenter). Name, photo and verified badge come with every comment anyway.

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

TikTok usernames or profile links, one per line: the comments on each creator's newest videos. You pay per comment only.

## `videosPerProfile` (type: `integer`):

Newest first; pinned videos come first, as on TikTok.

## `profileSorting` (type: `string`):

As the profile's tabs on TikTok. With a date range, Popular reads the whole list (slower).

## `profileSections` (type: `array`):

Reposts are other creators' videos the profile reposted. Videos per profile counts both together.

## `postedAfter` (type: `string`):

A date, or a relative time such as 7 days. Empty = all.

## `postedBefore` (type: `string`):

A date (the whole day counts), or a relative time such as 1 day. Empty = all.

## `excludePinnedPosts` (type: `boolean`):

Leave out the videos the creator pinned to the top of the profile.

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

Leave as is: datacenter proxies work for comments. Switch to residential only if a run reports blocks.

## Actor input object example

```json
{
  "videos": [
    "https://www.tiktok.com/@zachking/video/7655004069190192398",
    "https://www.tiktok.com/@ninjakitchen/video/7653941272524115231"
  ],
  "maxCommentsPerVideo": 25,
  "includeReplies": true,
  "maxRepliesPerComment": 1,
  "commenterProfiles": false,
  "videosPerProfile": 10,
  "profileSorting": "latest",
  "profileSections": [
    "videos"
  ],
  "excludePinnedPosts": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (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 = {
    "videos": [
        "https://www.tiktok.com/@zachking/video/7655004069190192398",
        "https://www.tiktok.com/@ninjakitchen/video/7653941272524115231"
    ],
    "maxCommentsPerVideo": 25,
    "includeReplies": true,
    "maxRepliesPerComment": 1,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("deepmine/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 = {
    "videos": [
        "https://www.tiktok.com/@zachking/video/7655004069190192398",
        "https://www.tiktok.com/@ninjakitchen/video/7653941272524115231",
    ],
    "maxCommentsPerVideo": 25,
    "includeReplies": True,
    "maxRepliesPerComment": 1,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("deepmine/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 '{
  "videos": [
    "https://www.tiktok.com/@zachking/video/7655004069190192398",
    "https://www.tiktok.com/@ninjakitchen/video/7653941272524115231"
  ],
  "maxCommentsPerVideo": 25,
  "includeReplies": true,
  "maxRepliesPerComment": 1,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call deepmine/tiktok-comments-scraper --silent --output-dataset

```

## MCP server setup

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