YouTube Comments Scraper π¬ Bulk, No API Key
Pricing
from $3.00 / 1,000 comment returneds
YouTube Comments Scraper π¬ Bulk, No API Key
Scrape every comment from any YouTube video. Pass video URLs or IDs; get comment text, author handle, like and reply counts, publish date and reply flag, plus the video title and channel, as JSON or CSV. No YouTube API key, no quota, no cap on comments.
Pricing
from $3.00 / 1,000 comment returneds
Rating
0.0
(0)
Developer
Yaniv van der Stigchel
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
15 hours ago
Last modified
Categories
Share
YouTube Comments Scraper β real numbers, no API key
Every comment from any YouTube video. Text, author, like and reply counts, and relative post time. No API key, no daily quota, no 100-comment cap.
What it does
- Scrape YouTube comments to JSON or CSV
- Export all comments from a YouTube video
- Get YouTube comment sentiment data in bulk
- Download YouTube comments without an API key
- Analyse audience feedback across many videos
Pass many videos in one run. Every comment is tagged with its source video.
Counts are numbers, not "309K"
YouTube returns engagement as abbreviated strings β 309K, 1.2M, 963. Most
scrapers hand those straight through, so you have to parse them yourself before
you can sort or sum anything.
This one returns integers: 309000, 1200000, 963. Sortable and
summable the moment you get them.
Honest failure reporting
reason | Meaning | Charged |
|---|---|---|
β (ok: true) | Comments returned | Yes |
comments-disabled | Video fine, comments off or none posted | No |
video-unavailable | Deleted, private, or region-locked | No |
unparseable-input | Not a recognisable video reference | No |
Feeding a large list? Dead videos and comment-less ones cost you nothing.
Why it keeps working
The extraction route uses the client version the page itself declares rather than a pinned one, and retries on a fresh IP when a residential exit node gets blocked β the two things that most often break YouTube scrapers silently.
Input
| Field | Required | Description |
|---|---|---|
videos | yes | Watch URLs, youtu.be links, shorts, or bare IDs |
maxCommentsPerVideo | no | Default 100. Your cost ceiling. |
maxConcurrency | no | 1β20, default 5 |
proxy | no | Defaults to residential, which YouTube requires |
Output
Every row has the same fields whether it succeeded or failed, so you can select columns without branching. Failed rows are never charged.
| Field | Type | Description |
|---|---|---|
success | boolean | True when this row carries data. Failed rows are never charged. |
videoId | string | YouTube's 11-character video identifier. |
videoUrl | string | Canonical watch URL for the video. |
videoTitle | string | Title of the video the comment is on. |
channel | string | Display name of the channel that published the video. |
commentId | string | YouTube's identifier for this comment. |
text | string | The comment body as posted. |
authorHandle | string | The commenter's @handle. |
authorChannelId | string | The commenter's channel identifier. |
likeCount | integer | Likes on this comment. |
replyCount | integer | Replies to this comment. Always 0 for a reply. |
publishedText | string | How long ago the comment was posted. YouTube exposes no absolute date here. |
isReply | boolean | True when this is a reply rather than a top-level comment. |
errorCode | string | Machine-readable failure reason. Null on success. |
errorMessage | string | Human-readable explanation of the failure. Null on success. |
Example β success
{"success": true,"videoId": "jNQXAC9IVRw","videoUrl": "https://www.youtube.com/watch?v=jNQXAC9IVRw","videoTitle": "Me at the zoo","channel": "jawed","commentId": "UgxKREWxIgDrw8w2e_x4AaABAg","text": "This is where it all started. Wild to think how far the platform has come.","authorHandle": "@some_viewer","authorChannelId": "UCq3B8s7Qk2AbCdEfGhIjKl","likeCount": 4127,"replyCount": 38,"publishedText": "1 year ago","isReply": false,"errorCode": null,"errorMessage": null}
Example β failure
A failure carries the same fields, so nothing downstream has to branch.
{"success": false,"videoId": "s1CFmzZzO4c","videoUrl": "https://www.youtube.com/watch?v=s1CFmzZzO4c","videoTitle": "Board meeting recording","channel": "Example Corp","commentId": null,"text": null,"authorHandle": null,"authorChannelId": null,"likeCount": null,"replyCount": null,"publishedText": null,"isReply": null,"errorCode": "comments-disabled","errorMessage": "The uploader has turned comments off for this video."}
Error codes
comments-disabledvideo-unavailableblockedunparseable-inputerror
A note on dates
YouTube exposes only relative time for comments ("1 year ago"), not a timestamp.
The field is named publishedText rather than publishedAt so it is clear it is
text, not a parseable date. No scraper can give you an exact date here.
Use it for
- YouTube comments export β every comment on a video, as JSON or CSV
- YouTube video comments in bulk, across many videos per run
- Audience research, sentiment and feedback analysis
- Community management and moderation review
- Creator research and training datasets
Related actors
| If you need | Use |
|---|---|
| The spoken text of a video | YouTube Transcript Scraper |
| Every transcript on a channel | YouTube Channel Transcript Scraper |
| Every transcript in a playlist | YouTube Playlist Transcript Scraper |
| A channel's Shorts | YouTube Shorts Transcript Scraper |
| Transcripts from a keyword search | YouTube Search to Transcripts |
Use it from an AI agent (MCP)
This Actor is callable as a tool through the Apify MCP server, so Claude, ChatGPT, Cursor and VS Code can run it directly.
Add the server to your MCP client:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com","headers": {"Authorization": "Bearer <YOUR_APIFY_TOKEN>"}}}}
Then ask for what you want in plain language β for example βget the comments on this YouTube videoβ β and the agent calls cleanfeed/youtube-comments-downloader with the right input. Every output field is described in the dataset schema, so the agent knows what it is getting back before it runs anything.
Call it from code
Python
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("cleanfeed/youtube-comments-downloader").call(run_input={"videos": ["https://www.youtube.com/watch?v=jNQXAC9IVRw"],})for item in client.dataset(run["defaultDatasetId"]).iterate_items():if item["success"]:print(item)
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('cleanfeed/youtube-comments-downloader').call({videos: ["https://www.youtube.com/watch?v=jNQXAC9IVRw"],});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.filter((i) => i.success));
cURL
curl -X POST "https://api.apify.com/v2/acts/cleanfeed~youtube-comments-downloader/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \-H 'Content-Type: application/json' \-d '{"videos": ["https://www.youtube.com/watch?v=jNQXAC9IVRw"]}'
Limitations
- A residential proxy is required. YouTube serves
playabilityStatus: ERRORto datacenter IP ranges while the identical request succeeds from a home connection β measured 12/12 success on residential against 0/12 on a cloud host with no proxy, and 7/12 through a datacenter proxy. The input defaults to residential; changing it will break most runs. Full method and per-environment figures are published in the reliability benchmark. - Comments can be disabled. Videos with comments turned off return
errorCode: comments-disabledand are never charged. - Publish dates are relative. YouTube exposes
"1 year ago"rather than a timestamp on this surface, sopublishedTextis a string, not a date. - Reply threads are included and flagged with
isReply, but very deep threads may be truncated bymaxCommentsPerVideo.
FAQ
Do I need a YouTube API key?
No. No key, no OAuth, and none of the Data API's daily quota.
Are replies included?
Yes. Replies come back alongside top-level comments and are marked with isReply: true.
Why is the publish date a string like "1 year ago"?
That is what YouTube exposes on this surface. There is no absolute timestamp available, so publishedText reports it verbatim rather than inventing a date.
What if comments are turned off?
The row returns errorCode: comments-disabled and is never charged.
Can I get the transcript instead?
Yes β YouTube Transcript Scraper returns the spoken text of the video.
Notes
Only publicly visible comments are collected. No login, no private data.