TikTok Comments Scraper — Replies, Likes & Commenters
Pricing
$0.25 / 1,000 per comment returneds
TikTok Comments Scraper — Replies, Likes & Commenters
Scrape every comment on any TikTok video or photo post: text, like count, reply count, timestamp, language, pinned and creator-liked flags, mentions, hashtags, comment images, and the commenter's handle, nickname, id, secUid and avatar. Optional threaded replies. No login, no cookies.
Pricing
$0.25 / 1,000 per comment returneds
Rating
0.0
(0)
Developer
Scrapers Delight
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
💬 TikTok Comments Scraper
Paste a TikTok video URL, get every comment as clean rows. Text, like count, reply count, exact timestamp, language, thread position, and the full commenter profile — handle, nickname, user id, secUid, avatar and profile URL. Replies included on a toggle, flagged and linked to their parent so you can rebuild the thread from a flat CSV.
No login. No cookies. No browser. One plain HTTP request per 50 comments — which is why this is priced at $0.00025 per comment, the lowest per-comment price measured in the lane (see the pricing table below for the live ladder it was measured against on 2026-09-02).
🎯 What does TikTok Comments Scraper do?
It reads TikTok's own public comment feed for a post and turns it into a dataset — one row per comment, ready for CSV, Excel, JSON, or straight into a Google Sheet.
- 💬 Every comment, paged until TikTok stops serving more
- ↩️ Threaded replies on a toggle —
isReply+parentCommentIdon every row - ❤️ Like count and reply count per comment, as numbers you can sort on
- 👤 Commenter identity:
@handle, display name, user id, secUid, avatar, profile URL - 🕒 Exact timestamps — ISO 8601 and raw Unix, so date filters just work
- 📌 Pinned by creator and liked by creator flags — the two strongest engagement signals
- 🏷️ Author labels (e.g.
Creator) and verified badges - 🔗 Mentions parsed out of the text with the mentioned user's id and secUid
- 🖼️ Comment images/stickers as direct URLs
- 🎬 The video caption joined onto every row, free — no second request
Works on video posts and photo posts, full URLs, vm.tiktok.com / vt.tiktok.com short links
(resolved for you), and bare numeric video ids.
📊 Measured field fill — real numbers, not claims
Measured 2026-09-02 on 576 unique comments across 3 real videos (12 pages, 50 per page, zero duplicate comment ids across the whole set), and confirmed on a live 723-row run on Apify (2 videos, replies on: 300 top-level + 423 replies, 723/723 unique ids, 105 seconds):
| Field | Fill | Notes |
|---|---|---|
commentId, likeCount | 100% | |
text | 99.8% offline / 97.4% live | the misses are image-only comments, which have no text |
createdAt, createdAtTimestamp, language | 100% | ISO 8601 + Unix seconds |
commenterUsername, commenterNickname | 100% | @handle and display name |
commenterId, commenterSecUid | 100% | secUid is the key TikTok's own profile endpoints take |
commenterProfileUrl, commenterAvatarUrl | 100% | |
videoId, videoUrl, videoCaption | 100% | caption comes free with the comments |
commentShareUrl | 100% offline / 90.3% live | TikTok's own share link; TikTok's share service intermittently blanks it for a whole page. Reported honestly, not faked |
pinnedByCreator, likedByCreator, isReply | 100% | always a real boolean, never null |
commenterVerificationLabel | 2.3% / 1.2% live | only verified and institution accounts have one |
authorLabel | 0.5% / 0.7% live | TikTok only labels a few authors (e.g. Creator) |
imageUrls | 1.6% / 2.1% live | only comments that attached an image |
mentions | 0.2% / 3.6% live | only comments that @-tag someone |
hashtags | 0% in both samples | comment hashtags are genuinely rare; parsed from the same text_extra structure that produced the mentions above, so the code path is exercised — but we will not quote a fill rate we have not observed |
replyCount is 100% on top-level comments. Reply rows carry null there — TikTok's reply
endpoint does not return a nested-reply count, and inventing a 0 would be a lie.
🚀 Input
| Field | Type | Default | What it does |
|---|---|---|---|
videoUrls | array | (sample videos) | Video URLs, photo-post URLs, short links, or bare ids |
maxCommentsPerVideo | integer | 100 | Top-level comments per video. 0 = everything TikTok pages |
includeReplies | boolean | false | Also fetch replies under each comment that has them |
maxRepliesPerComment | integer | 20 | Cap per comment when replies are on. 0 = all |
proxyConfiguration | object | Apify Proxy on | Rotates the exit IP. Switch to RESIDENTIAL if you see blocked videos |
{"videoUrls": ["https://www.tiktok.com/@zachking/video/7095025543627705643","https://www.tiktok.com/@guinnessworldrecords/video/7172183875538488582"],"maxCommentsPerVideo": 200,"includeReplies": false,"proxyConfiguration": { "useApifyProxy": true }}
Leaving videoUrls empty is safe: the run falls back to the two documented sample videos and still
produces output, rather than failing.
📦 Output
{"videoId": "7095025543627705643","videoUrl": "https://www.tiktok.com/@zachking/video/7095025543627705643","videoCaption": "#answer to @spidermark790","commentId": "7521666400186221368","text": "Search: original video 7 billion views","likeCount": 104,"replyCount": 2,"createdAt": "2025-06-30T09:07:40.000Z","createdAtTimestamp": 1751274460,"language": "en","isReply": false,"parentCommentId": null,"replyToCommentId": null,"pinnedByCreator": false,"likedByCreator": false,"authorLabel": null,"commenterUsername": "warukaxender","commenterNickname": "WarukA Xender","commenterProfileUrl": "https://www.tiktok.com/@warukaxender","commenterId": "7124324677996381190","commenterSecUid": "MS4wLjABAAAApLC7tj0vaAVzpRNua7nJXsBlXK1XcKgo7...","commenterAvatarUrl": "https://p16-common-sign.tiktokcdn.com/...","commenterVerified": false,"commenterVerificationLabel": null,"mentions": [],"hashtags": [],"imageUrls": [],"commentShareUrl": "https://m.tiktok.com/v/7095025543627705643.html?...","scrapedAt": "2026-09-02T04:23:24.839Z"}
💰 Pricing
$0.00025 per comment delivered. Pay per event, no monthly fee, no charge for starting a run.
You are billed as rows are delivered, not before — so if you set a spend cap, the run stops at your cap instead of handing you rows you already paid past. Blocked or unreadable videos return no rows and cost nothing.
| Comments | Cost |
|---|---|
| 1,000 | $0.25 |
| 10,000 | $2.50 |
| 100,000 | $25.00 |
Replies are billed as comments, because they are comments.
The live ladder this was priced against (read from each actor's pricingInfos on the Apify
Store API, 2026-09-02): $0.00028 + $0.00005/start · $0.0003 · $0.0003 + $0.003 per query ·
$0.0005 + $0.02 per video · $0.0005 · $0.00198 · $0.0025 · $0.00499 + $0.09/start, with
the lane leader at $0.00125 per result. $0.00025 is under all of them, with no start fee.
⚙️ How it works (and why it stays cheap)
TikTok's comment feed is served by a public JSON endpoint that takes four parameters and a
referer header. That is the entire request — no signature, no msToken, no X-Bogus, no cookie,
no headless browser. A browser-based competitor pays for 4 GB of Chromium on every run; this pays
for one HTTP GET per 50 comments. That cost difference is the price difference.
Three things were measured and built around, rather than assumed:
- Sending empty signature parameters is worse than sending none. The long browser-style query string returns HTTP 200 with a zero-byte body; the minimal four-parameter query returns 65 KB of comments. The query string here is built from a fixed key set and nothing is appended.
- A page size above ~50 silently loses comments. Measured on one video:
count=20→ 19 rows,count=50→ 48 rows,count=100→ still 48 rows but the cursor advances 100,count=200→ 48 rows and the cursor advances 200. Delivery is capped near 50 while the cursor moves by the requested count, so a bigger page skips roughly half the comment section every time. The page size is pinned to 50. - A zero-byte HTTP 200 is a block, not an empty comment section. Those two outcomes are counted separately and named separately in the run summary. A blocked video is reported as blocked, never quietly as "this video has no comments".
Reliability details: retries with backoff and a fresh proxy session on every soft block or 5xx; a wall-clock budget derived from the run's own timeout so a big job stops cleanly instead of being killed mid-page; and crash handlers that end the run cleanly with an explanatory status message. The run only fails when the output would be genuinely invalid — nothing read at all and every video blocked.
🌍 Proxies
Apify Proxy is on by default (automatic/datacenter group). Verified working 2026-09-02 from a
residential home IP and through Apify Proxy auto, BUYPROXIES94952 (datacenter) and
RESIDENTIAL — all three returned HTTP 200 with full comment payloads.
If a long, high-volume run starts reporting blocked videos in the status message, switch
proxyConfiguration to RESIDENTIAL. That is the documented escalation, and the status message
tells you when you need it.
❓ FAQ
Do I need a TikTok account, cookies, or an API key? No. Nothing is authenticated. You paste a public video URL.
Can it scrape replies to comments?
Yes — turn on includeReplies. Replies come back as ordinary rows with isReply: true and
parentCommentId pointing at the comment they answer, so a flat CSV still reconstructs the thread.
Will it get ALL the comments on a video with 60,000 of them?
It pages until TikTok stops returning more. TikTok itself caps how deep the public feed goes, and
that depth varies by video — so treat very large videos as "as many as TikTok will serve", not a
guaranteed 100%. Set maxCommentsPerVideo: 0 to take everything available.
Does it work on photo posts (image carousels)?
Yes. /photo/<id> URLs use the same comment endpoint.
Do short links work?
Yes. vm.tiktok.com and vt.tiktok.com links are redirect-resolved to the numeric video id first.
What happens if a video is private, deleted, or has comments turned off? It returns no rows for that video, the run still succeeds, and the status message names the video and says it returned zero comments — separately from any video that was actually blocked.
Do I get commenter email addresses? No. TikTok does not publish them, and this actor does not guess or enrich them. What you get is the handle, secUid and profile URL — which is what you need to look a commenter up.
What is secUid and why should I care?
It is TikTok's stable, non-numeric user key. TikTok's own profile and feed endpoints accept it,
so it is the field that makes a comment row joinable to anything else you scrape.
Can I run this on many videos at once?
Yes — pass as many URLs as you like in videoUrls. Each is capped independently by
maxCommentsPerVideo.
Is the output stable enough to schedule? Yes. It is a normal Apify Actor: schedule it, pipe it to a webhook, or call it from the API. Field names do not change without a version bump.
How is a comment counted for billing? One charge per row actually written to your dataset. Duplicates are removed before delivery, and rows past your spend cap are never delivered or charged.
⚖️ Legal & fair use
This actor reads publicly visible comments — the same data any logged-out visitor sees on the video page. It does not log in, does not bypass a paywall or an age gate, does not touch private accounts, and does not collect email addresses, phone numbers or any contact data (TikTok does not publish those).
You are responsible for how you use the output: comply with TikTok's Terms of Service, and with GDPR/CCPA and any other applicable privacy law where personal data is involved. Comment text and usernames are personal data in many jurisdictions — have a lawful basis before you store or process them, and honour deletion requests. Do not use the output to harass, profile or target individuals.
For scraping research and dataset use, see Apify's guidance on web scraping and the law.