Youtube Comment Scraper
Pricing
from $3.00 / 1,000 results
Youtube Comment Scraper
Scrape YouTube video comments with full metadata. Extracts comment text, author info, likes, timestamps, pinned/hearted status, and reply threads. Supports sorting by Top comments or Newest first.
Pricing
from $3.00 / 1,000 results
Rating
5.0
(1)
Developer
Crawler Bros
Maintained by CommunityActor stats
0
Bookmarked
94
Total users
13
Monthly active users
3.1 hours
Issues response
6 days ago
Last modified
Categories
Share
Scrape YouTube video comments with full metadata including author info, likes, timestamps, pinned/hearted status, and reply threads. Supports sorting by Top comments or Newest first.
Input
| Field | Type | Default | Description |
|---|---|---|---|
videoUrls | array | required | YouTube video URLs, short links (youtu.be), shorts URLs, or plain video IDs |
maxComments | integer | 100 | Max top-level comments per video (1–50,000). Replies don't count toward this limit |
includeReplies | boolean | true | Whether to fetch reply threads for each comment |
maxRepliesPerComment | integer | 5 | Max replies to fetch per comment (0–100) |
sortBy | string | "top" | Sort order: "top" (most relevant) or "newest" (chronological) |
commentKeywordFilter | string | (none) | Only return comments/replies whose text contains this word or phrase (case-insensitive) |
minLikeCount | integer | 0 | Only return comments/replies with at least this many likes |
Supported URL Formats
https://www.youtube.com/watch?v=dQw4w9WgXcQhttps://youtu.be/dQw4w9WgXcQhttps://www.youtube.com/shorts/dQw4w9WgXcQhttps://www.youtube.com/embed/dQw4w9WgXcQhttps://www.youtube.com/live/dQw4w9WgXcQhttps://www.youtube.com/v/dQw4w9WgXcQdQw4w9WgXcQ(bare video ID)
Extra query parameters (&t=30s, &si=..., etc.) and domain casing are both ignored — only the video ID is used. If the same video appears more than once (even in a different URL format), only the first occurrence is scraped; later duplicates are skipped. Within a single video, YouTube can also resurface the same comment more than once during pagination (most commonly a pinned comment, which appears both in its pinned slot and again in its normal chronological position) — the actor tracks comment IDs already returned and skips re-pushing them, so the dataset never contains duplicate comment rows for the same video.
Example Input
{"videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],"maxComments": 100,"includeReplies": true,"maxRepliesPerComment": 5,"sortBy": "top"}
Output
Each dataset row is a top-level comment (replyDepth: 0). When includeReplies is enabled and a comment has replies, they're embedded in that row's replies field — an array of reply objects (replyDepth: 1, same shape as a comment row, plus parentCommentId) — rather than being pushed as separate top-level rows of their own.
| Field | Type | Description |
|---|---|---|
commentId | string | Unique comment identifier |
text | string | Comment text content |
authorName | string | Author's display name |
authorChannelId | string | Author's YouTube channel ID |
authorChannelUrl | string | Author's channel URL |
authorProfileImageUrl | string | Author's profile image URL |
authorIsChannelOwner | boolean | Whether the author is the video's channel owner |
likeCount | integer | Number of likes on the comment |
replyCount | integer | Number of replies (always 0 on reply objects themselves; only meaningful on top-level comments) |
replyCountText | string | Reply count as text, e.g. "963" (present on top-level comments only; a bare number, not a formatted phrase) |
publishedTimeText | string | Relative publish time (e.g., "2 days ago") |
commentUrl | string | Direct link to the comment (https://www.youtube.com/watch?v=VIDEO_ID&lc=COMMENT_ID) |
isHearted | boolean | Whether the creator hearted this comment |
isPinned | boolean | Whether this comment is pinned |
isVerifiedAuthor | boolean | Whether the author's channel is verified |
isCreator | boolean | Alias for authorIsChannelOwner |
isArtist | boolean | Whether the author is a YouTube Music artist |
isReply | boolean | Whether this is a reply (true) or top-level comment (false) |
parentCommentId | string | Parent comment ID (present only on reply objects, absent on top-level comments) |
replyDepth | integer | 0 for top-level comments, 1 for replies |
videoId | string | YouTube video ID |
videoUrl | string | Full video URL |
videoTitle | string | Video title |
videoChannelName | string | Video channel name |
videoChannelId | string | Video channel ID |
videoViewCount | integer | Video's total view count |
videoPublishedDate | string | Video's absolute publish date (e.g., "Oct 24, 2009") |
videoDescription | string | Video's full description text |
totalCommentCount | integer | Video's total comment count (present when available) |
scrapedAt | string | ISO 8601 timestamp of when the data was scraped |
replies | array | Nested reply objects (present only on top-level comment rows, only when includeReplies=true and the comment has replies) |
Example Output
{"commentId": "UgxB...","text": "Great video!","authorName": "John Doe","authorChannelId": "UCxxx...","authorChannelUrl": "https://www.youtube.com/@johndoe","authorProfileImageUrl": "https://yt3.ggpht.com/...","authorIsChannelOwner": false,"likeCount": 42,"replyCount": 3,"publishedTimeText": "2 days ago","isHearted": false,"isPinned": false,"isReply": false,"replyDepth": 0,"videoId": "dQw4w9WgXcQ","videoUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ","videoTitle": "Rick Astley - Never Gonna Give You Up","videoChannelName": "Rick Astley","videoChannelId": "UCuAXFkgsw1L7xaCfnd5JJOw","videoViewCount": 1811547602,"videoPublishedDate": "Oct 24, 2009","videoDescription": "The official video for \"Never Gonna Give You Up\" by Rick Astley...","totalCommentCount": 2400000,"scrapedAt": "2026-02-11T12:00:00.000000+00:00","replies": [{"commentId": "UgxB....AbCdEfGhIj","text": "I agree!","authorName": "Jane Smith","likeCount": 5,"publishedTimeText": "1 day ago","isReply": true,"parentCommentId": "UgxB...","replyDepth": 1,"commentUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ&lc=UgxB....AbCdEfGhIj"}]}
Each reply object actually carries the full same field set as a top-level comment row (all author fields — authorChannelId, authorChannelUrl, authorProfileImageUrl, authorIsChannelOwner, isVerifiedAuthor, isCreator, isArtist, isHearted, isPinned — plus the full video* context block), not just the trimmed set shown above; the example above only highlights the fields that differ meaningfully from a top-level comment. The one exception is totalCommentCount, which is present on top-level comments but never on reply objects.
Error Handling
If a video URL can't be parsed, doesn't resolve to a real video, has comments disabled, or fails to fetch, the actor pushes a single marker row instead of comment rows — so failures are visible in the dataset instead of silently producing nothing. Marker rows use success (boolean) and error (a human-readable message) instead of comment fields. inputUrl is the original raw input string only when the URL couldn't be parsed at all; for every other case (video not found, comments disabled, fetch failure, zero matches) it's the normalized/canonical video URL, since parsing already succeeded by that point:
| Case | success | commentsDisabled | Other fields |
|---|---|---|---|
| URL couldn't be parsed into a video ID | false | false | No videoId/video metadata (never resolved far enough to have any) |
| Video ID doesn't resolve to a real page (deleted, never existed) | false | false | videoId/videoUrl present, but videoTitle and other video metadata are empty |
| Video exists, comments are disabled | false | true | Full video metadata (videoTitle, videoViewCount, etc.) is present |
| Video page/comments fetch failed (bot detection, network error) | false | false | videoId/videoUrl present; video metadata depends on how far the fetch got |
| Comments enabled but the video has zero (or zero matching your filters) | true | false | commentCount: 0, full video metadata present |
Use Cases
- Sentiment analysis — collect comments on product or brand videos to measure audience sentiment at scale
- Community research — surface recurring topics, questions, and audience insights from high-engagement videos
- Moderation dataset building — export comment threads for ML training on toxicity detection or content moderation
- Finding pinned announcements — quickly retrieve creator-pinned comments containing links, dates, or announcements
- Influencer engagement benchmarking — track top-comment like counts to compare engagement quality across creators
- Reply threading for conversation analysis — reconstruct full reply chains for discourse and community interaction studies
FAQ
Why are some comments missing? YouTube loads comments dynamically. The scraper uses the internal YouTube API but may not always see all comments on very large videos due to YouTube's server-side pagination limits.
Are replies included by default?
Yes, when includeReplies=true (the default). You can set includeReplies: false or reduce maxRepliesPerComment to skip or cap reply fetching.
Does this require a YouTube API key or cookies? No. The actor uses YouTube's public InnerTube API and does not require any authentication, API keys, or cookies.
What happens if a video URL is invalid or the video doesn't exist?
The actor still produces one dataset row for that entry instead of silently skipping it, marked with success: false and an error message explaining why — see Error Handling above.
What's the difference between top and newest sort?
top returns comments sorted by YouTube's relevance score (a combination of likes, pins, and reply volume). newest returns comments in reverse chronological order.
Can I scrape comments for private or age-gated videos? No. Only public videos are supported. Age-gated and private videos require a logged-in session, which this actor does not use.
How do the keyword filter and minimum like count work? Both are applied locally to the comments the actor already fetched — they don't change what YouTube returns, only what gets saved to the dataset. Both are checked against a top-level comment before deciding whether to fetch its replies: if a comment fails either filter, its replies are skipped entirely (not fetched at all, to save time) — even if some of those replies would individually have passed. Each reply that does get fetched is then checked against both filters again on its own merits.
YouTube Scraper Suite
This actor is part of a complete YouTube data extraction toolkit. Explore the full suite:
| Actor | Description |
|---|---|
| YouTube Channel Scraper | Channel metadata, subscriber counts, and full video catalogs |
| YouTube Channel Scraper Fast | Streamlined channel scraper for high-volume and speed-sensitive workflows |
| YouTube Comment Scraper | Comments, replies, likes, author info, and pinned/hearted status |
| YouTube Email Scraper | Creator contact emails from channel pages, Instagram, TikTok, and Linktree |
| YouTube Hashtag Scraper | Videos and Shorts tagged with specific hashtags |
| YouTube Playlist Scraper | All videos and metadata from any YouTube playlist |
| YouTube Search Scraper | Search results including videos, channels, and playlists |
| YouTube Shorts Scraper | Shorts from channels or hashtags with full view and like metadata |
| YouTube Transcript Scraper | Timed transcripts and captions with optional Whisper AI fallback |
| YouTube Trending Scraper | Ranked trending videos by category — Gaming, Music, News, Movies |
| YouTube Video Details Scraper | Comprehensive video metadata, chapters, endscreen, captions, and comments |
| YouTube Video Downloader | Download videos, playlists, and channels in any quality with metadata |