TikTok Comments Scraper - Comments, Authors & Likes
Pricing
from $1.00 / 1,000 results
TikTok Comments Scraper - Comments, Authors & Likes
Scrape comments from TikTok videos using one or more video URLs or IDs. Extract comment text, author, likes, reply count and timestamp in clean structured data. Supports multiple videos in a single run with no login required.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
13
Total users
5
Monthly active users
13 days ago
Last modified
Categories
Share
TikTok Comments Scraper: Video Comments, Replies & Recurring Monitoring
TikTok Comments Scraper turns a video, or a creator's recent videos, into a clean comments dataset. Paste video links or ids, or give usernames and let the actor walk each account's recent videos, then filter by likes, a keyword, replies or age before anything is written. Every run can resume a large crawl, track changes across a schedule, and optionally pipe results into your own apps.
Why This Scraper?
- Two ways to pick videos. Paste video links or ids, or give usernames and let the actor discover each account's recent videos.
- Filters that save money. A minimum like count, a required keyword, a reply exclusion or a days-old cutoff are all applied before a row is written, so filtered-out comments are never billed.
- Reply capture, honestly reported. Reply fetching is attempted per comment and switches itself off for a video once it is clear nothing is coming back, so you are never billed for a long stream of empty attempts.
- Recurring monitoring. Incremental mode classifies every comment NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED against a remembered baseline, so a scheduled run returns only what changed.
- Resume big crawls. Paste a previous run or dataset id and comments already collected there are skipped, so you never pay twice.
- Export to your apps. Optionally pipe results into Notion, Linear, Airtable or Apify through connectors, without changing the dataset.
- A quiet zero is never called a success. A run that collects nothing is reported clearly, so a scheduled job cannot fail silently.
Use Cases
- Brand and campaign teams: track sentiment and engagement on your own or a competitor's TikTok videos.
- Community managers: pull recent comments for moderation review, filtered to a keyword or a minimum like count.
- Researchers and analysts: build a dataset of comment text, likes and timestamps across a set of videos or creators.
- Growth and marketing teams: monitor a creator's newest videos on a schedule and get only new or changed comments.
- Customer feedback teams: search a brand account's videos for comments that mention a product or keyword.
Data You Get
Sample shape: values are illustrative placeholders, not from a live video.
| Field | Example |
|---|---|
recordType | "comment" |
sourceMode | "comments" |
commentId | "7685134583982015250" |
videoId | "7673909736131038495" |
videoUrl | "https://www.tiktok.com/video/7673909736131038495" |
isReply | false |
replyToCommentId | null |
text | "This made my day" |
authorUsername | "sampleuser" |
authorNickname | "Sample User" |
authorUid | "7000000000000000002" |
authorAvatarUrl | "https://p16-sign-va.tiktokcdn.com/sample-avatar.jpeg" |
authorRegion | "US" |
diggCount | 12 |
replyCommentTotal | 3 |
createTime | 1700000000 |
createTimeIso | "2023-11-14T22:13:20.000Z" |
scrapedAt | "2026-01-01T00:00:00.000Z" |
changeType | "NEW" (incremental mode only) |
changedFields | ["diggCount"] (incremental mode only, UPDATED rows) |
firstSeenAt | "2026-01-01T00:00:00.000Z" (incremental mode only) |
lastSeenAt | "2026-01-01T00:00:00.000Z" (incremental mode only) |
Every comment is one record of this shape; there is no separate record type for videos or authors. A video's own metadata is not scraped, only the comment fields above, and authorUsername, diggCount and a few other fields can come back null when the source omits them for a particular comment.
How to Use
- Pick a mode:
videos(paste the exact videos you care about) orsearch(give usernames and let the actor walk their recent videos). Search mode only follows a given account's own videos; it does not run a keyword or hashtag search across TikTok. - Add your video URLs or ids, or your usernames. Paste the full video URL or the numeric video id; short share links (vm.tiktok.com, vt.tiktok.com) are not resolved. A private or removed video returns no comments.
- Turn on any filters you want (minimum likes, a keyword, replies on or off, a days window), and set Max comments per video (and Max videos per username in search mode) to control run size and cost.
- Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.
Videos mode, the exact videos you care about:
{"mode": "videos","videoUrls": ["https://www.tiktok.com/@tiktok/video/7673909736131038495"],"maxCommentsPerVideo": 50}
Search mode, walk an account's recent videos:
{"mode": "search","usernames": ["tiktok"],"maxVideosPerUser": 10,"maxCommentsPerVideo": 50}
Filtered comments, only what matters:
{"mode": "videos","videoUrls": ["https://www.tiktok.com/@tiktok/video/7673909736131038495"],"minCommentLikes": 10,"commentKeyword": "love","excludeReplies": true,"commentsSinceDays": 30}
Recurring monitoring, only what changed since last time:
{"mode": "videos","videoUrls": ["https://www.tiktok.com/@tiktok/video/7673909736131038495"],"incrementalMode": true,"stateKey": "my-campaign"}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/tiktok-comments-scraper").call(run_input={"mode": "videos","videoUrls": ["https://www.tiktok.com/@tiktok/video/7673909736131038495"],"maxCommentsPerVideo": 50,})for comment in client.dataset(run["defaultDatasetId"]).iterate_items():print(comment["authorUsername"], comment["text"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/tiktok-comments-scraper').call({mode: 'videos',videoUrls: ['https://www.tiktok.com/@tiktok/video/7673909736131038495'],maxCommentsPerVideo: 50,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
About patience and caps
The source answers only a share of requests, and only during certain windows, some of which let almost nothing through. concurrency is how many requests the actor tries at once for a page, and pagePatienceSeconds is how long it keeps sampling before giving up on that page, so a window that opens partway through is still caught. maxAttemptsPerPage is an optional hard ceiling on top of that budget; leave it at 0 to let the patience budget alone decide. If a video keeps coming back as unreadable, raising pagePatienceSeconds (for example to 240) usually helps more than adding retries.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one interrupted run: paste its run or dataset id and the actor skips every comment id already collected there, so you don't pay twice. It cannot be combined with Incremental mode in the same run. - Incremental mode (
incrementalMode) is for scheduled runs over the same videos or accounts. Each comment is classifiedNEW,UPDATED(withchangedFields),UNCHANGED(suppressed and not billed unlessemitUnchangedis on),REAPPEAREDorEXPIRED. A comment is only markedEXPIRED, and only whenemitExpiredis on, after a run that reached the natural end of every tracked video or account, with no block or resume, and with Max comments per video (and, in search mode, Max videos per username) set to0or high enough that the cap was never reached.REAPPEAREDonly follows a comment that was previously tombstonedEXPIREDand is then seen again.stateKeynames or shares the stored baseline; leave it empty to let the actor derive one from the videos, usernames and filters. With Incremental mode off, output is exactly as before.
Send results into your apps (MCP connectors)
Optionally pipe the scraped comments into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each comment, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify, Settings, Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | videos | videos = scrape the URLs/ids you paste; search = walk usernames' videos. |
videoUrls | array | [] (prefill: sample video URL) | Video URLs or numeric video ids. Videos mode. Short share links are not supported. |
usernames | array | [] (prefill: tiktok) | TikTok usernames, with or without @. Search mode. |
maxVideosPerUser | integer | 10 | How many of each account's recent videos to scan. 0 = unlimited. Search mode. |
minCommentLikes | integer | 0 | Only keep comments with at least this many likes. 0 = no minimum. |
commentKeyword | string | (none) | Only keep comments containing this word or phrase, case-insensitive. |
excludeReplies | boolean | false | Drop replies and keep only top-level comments. |
commentsSinceDays | integer | 0 | Drop comments older than this many days. 0 = no date filter. |
fetchReplies | boolean | false | Also try to collect replies. The source usually returns none to automated requests. |
maxRepliesPerComment | integer | 5 | Reply cap per comment when reply fetching is on. 0 = unlimited. |
replyPatienceSeconds | integer | 10 | Time budget per reply request. |
maxCommentsPerVideo | integer | 20 | Comments to collect per video. 0 = unlimited. |
maxPagesPerVideo | integer | 0 | Reserved; currently has no effect. Use Max comments per video to limit run size. |
pagePatienceSeconds | integer | 120 | Per-page time budget; a page keeps being requested until it succeeds or this runs out. |
maxAttemptsPerPage | integer | 0 | Optional hard ceiling on requests per page. 0 = no ceiling. |
concurrency | integer | 20 | Parallel requests per page, 1 to 20. |
resumeFromRunId | string | (none) | Previous run or dataset id; comments already collected there are skipped. |
incrementalMode | boolean | false | Classify each comment against the remembered baseline and suppress unchanged rows. |
stateKey | string | (none) | Optional name for this monitoring campaign. Leave empty to derive one automatically. |
emitUnchanged | boolean | false | Also return (and bill) comments that did not change. |
emitExpired | boolean | false | Also return (and bill) comments that are gone, only after a complete tracked scan. |
mcpConnectors | array | (none) | Optional MCP connectors to also send results to. Never changes the dataset. |
notionParentPageUrl | string | (none) | Notion parent page for the Notion connector only. |
maxNotifyListings | integer | 50 | Cap on items sent to each connector per run. |
proxyTier | string | datacenter | datacenter or residential. Datacenter is enough for this source. |
proxy | object | (none, prefill: {"useApifyProxy": true}) | Leave unset to use Apify Proxy automatically; proxyTier above picks the group. |
Output Example
Sample shape: values are illustrative placeholders, not from a live video.
{"recordType": "comment","sourceMode": "comments","commentId": "7685134583982015250","videoId": "7673909736131038495","videoUrl": "https://www.tiktok.com/video/7673909736131038495","isReply": false,"replyToCommentId": null,"text": "This made my day","authorUsername": "sampleuser","authorNickname": "Sample User","authorUid": "7000000000000000002","authorAvatarUrl": "https://p16-sign-va.tiktokcdn.com/sample-avatar.jpeg","authorRegion": "US","diggCount": 12,"replyCommentTotal": 3,"createTime": 1700000000,"createTimeIso": "2023-11-14T22:13:20.000Z","scrapedAt": "2026-01-01T00:00:00.000Z"}
Plan Requirement
This actor is pay-per-event: a charge when the run starts, a charge for each comment written to the dataset, and a small charge each time the actor attempts a reply fetch, whether or not any reply rows come back. The Pricing tab shows the current per-event rates. The default proxy tier is enough for this source; switch to the residential tier under Connection only if a run is returning too few comments.
FAQ
How much does it cost?
This actor uses pay-per-event pricing: a charge when the run starts, a charge for each comment written to the dataset, and a small charge each time the actor attempts to fetch replies for a comment (only when Fetch replies is on), whether or not any reply rows come back. The Pricing tab shows the current rates. Use Max comments per video to cap the size, and cost, of any run.
Is it legal to scrape TikTok comments?
This actor collects only comments that are publicly visible on TikTok. You are responsible for how you use the data: follow TikTok's terms and the laws that apply to you, and get legal advice before any commercial use, especially one that stores or republishes personal data such as usernames or comment text.
Can I get only new or changed comments on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then classifies every comment against what was remembered from earlier runs on the same State key: NEW, UPDATED (with the changed fields listed), or UNCHANGED (suppressed and not billed unless Emit unchanged is on). A comment is only reported EXPIRED after a run that reached the natural end of every tracked video or account, with no block or resume, and with Max comments per video (and, in search mode, Max videos per username) set to 0 or high enough that the cap was never reached, and only when Emit expired is on. A comment is only reported REAPPEARED once it was previously tombstoned EXPIRED and is then seen again. Because the source can return a slightly different comment list from one request to the next, a schedule may legitimately report a few new rows every run.
Why does turning on Fetch replies usually add nothing?
The source rarely returns reply rows to automated requests, even with Fetch replies on. The actor still tries, since some accounts and windows do return them, but gives up on a video after three attempts in a row come back empty. Every attempt is billed once, whether or not it returns a row, because the request itself has a real cost; any reply rows that do come back are billed separately as ordinary results.
Why did my run fail instead of returning an empty dataset?
A run that collects zero comments is reported as failed, not as a quiet empty success, whenever at least one video could not be read or returned no comments at all from the source. If every video was read and returned comments, but none were written because your filters removed them, a resumed run had already collected them, or incremental mode found nothing changed, the run finishes successfully with a message saying the result is genuinely empty.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
π Want more TikTok data?
Pair this actor with these related scrapers from the same team:
| π± TikTok Profile, Hashtag, Search, Video & Trending Scraper Scrape TikTok without login. Extract profiles, bios, follower stats and videos; search by... | π± Tiktok Live Recorder Record TikTok live streams to MP4 with full metadata, all stream quality URLs, and... |
| π§© Pikabu Scraper Scrape Pikabu (ΠΠΈΠΊΠ°Π±Ρ): keyword search, hot/new/best feeds, communities, tags, full story... | π± Lemon8 Media Scraper Lightweight Lemon8 scraper for extracting image and video URLs from posts, with optional... |
| π± Wattpad Scraper Scrape Wattpad stories by keyword, tag, category, language or URL. Extract authors... | π§© Stocktwits Scraper Scrape Stocktwits message streams with bull/bear sentiment labels, bodies, likes... |
π Browse all abotapi scrapers
π¬ Support & custom scrapers
- π Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- π οΈ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
- β Enjoying it? A quick review on the actor page helps other users find it.