YouTube Comments Scraper avatar

YouTube Comments Scraper

Pricing

from $1.50 / 1,000 results

Go to Apify Store
YouTube Comments Scraper

YouTube Comments Scraper

Fast YouTube comments scraper. Paste any video URLs and extract every comment plus full reply threads. Author handle, channel id, exact like count, reply count, hearted, pinned, verified, edited flags, published time. Direct InnerTube API reads, no browser. PPE pricing.

Pricing

from $1.50 / 1,000 results

Rating

0.0

(0)

Developer

Crikit

Crikit

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Fast, exhaustive YouTube comments scraper. Paste any YouTube video URLs and extract every comment plus the full reply thread under each one. Direct reads of YouTube's InnerTube API, no headless browser. Built in Python with curl_cffi for clean TLS impersonation.

What you get

One record per comment or reply, in flat row format. Top-level comments have replyLevel = 0, replies have replyLevel = 1 and a parentCommentId linking back to the comment they reply to.

Every field is parsed directly from YouTube's structured comment payload, including:

  • commentId, parentCommentId, replyLevel
  • text (plain text rendered from YouTube's run-based content)
  • publishedTimeRelative ("1 day ago", "3 weeks ago (edited)")
  • isEdited
  • likeCount (exact integer, parsed from YouTube's accessibility label, not the 1.1K cosmetic string)
  • replyCount (exact integer; 0 on reply rows)
  • authorChannelId, authorHandle, authorDisplayName, authorThumbnailUrl
  • authorIsVerified, authorIsCreator, authorIsArtist
  • isHearted (creator gave this comment the heart icon)
  • isPinned (top-level only; pinned comments only)
  • videoId, videoUrl
  • scrapedAt (ISO-8601 UTC timestamp)

Input

{
"videoUrls": [
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"https://youtu.be/jNQXAC9IVRw",
"dQw4w9WgXcQ"
],
"sortBy": "TOP",
"maxCommentsPerVideo": 500,
"includeReplies": true,
"maxRepliesPerComment": 50,
"proxyConfiguration": { "useApifyProxy": true }
}
FieldTypeDescription
videoUrlsarray, requiredYouTube watch URLs, Shorts URLs, youtu.be short links, or raw 11-character video IDs. Each video is scraped independently.
sortByenum, default TOPTOP returns YouTube's ranked order. NEWEST returns reverse-chronological.
maxCommentsPerVideointeger, optionalHard cap on top-level comments per video. Leave empty to scrape the entire comment section.
includeRepliesboolean, default trueIf on, fetch the full reply thread under every top-level comment.
maxRepliesPerCommentinteger, optionalHard cap on replies per top-level comment. Leave empty for unlimited.
proxyConfigurationobjectDatacenter proxy is sufficient for steady-state scraping. Use Residential only if you hit throttling at very high volume.

Output

One JSON object per dataset row. Example (top-level comment):

{
"videoId": "dQw4w9WgXcQ",
"videoUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"commentId": "Ugzge340dBgB75hWBm54AaABAg",
"parentCommentId": null,
"replyLevel": 0,
"text": "can confirm: he never gave us up",
"publishedTimeRelative": "1 year ago",
"isEdited": false,
"likeCount": 241,
"replyCount": 960,
"authorChannelId": "UCBR8-60-B28hp2BmDPdntcQ",
"authorHandle": "YouTube",
"authorDisplayName": "@YouTube",
"authorThumbnailUrl": "https://yt3.ggpht.com/...",
"authorIsVerified": true,
"authorIsCreator": false,
"authorIsArtist": false,
"isHearted": true,
"isPinned": true,
"scrapedAt": "2026-05-19T01:16:49Z"
}

A reply has the same shape with replyLevel: 1, a populated parentCommentId, and replyCount: 0.

How it works

The actor calls YouTube's InnerTube API directly (POST /youtubei/v1/next) using curl_cffi with Chrome 131 TLS impersonation. For each input video it:

  1. Fetches the watch-page HTML once to extract the current INNERTUBE_CLIENT_VERSION and the comments-section entry continuation token.
  2. Walks comment pages 20-at-a-time until the comment section ends (or maxCommentsPerVideo is hit).
  3. For each top-level comment with replies, fires a parallel reply-thread fetch (10 replies per page; paginates until the reply thread ends or maxRepliesPerComment is hit).
  4. Pushes each comment to the dataset as a flat record.

No browser, no captcha challenge, no signed requests. The whole flow runs at roughly 1-2 requests per second per IP and is safe to run unattended for hours.

Pricing

Pay per comment scraped (Pay Per Event). Replies and top-level comments are both billable rows. Failed videos (private, unavailable, comments disabled) emit nothing and cost nothing.

Edge cases handled

  • Comments disabled. Detected; the video is skipped and no rows are emitted.
  • Private or unavailable videos. Detected; the video is skipped.
  • YouTube Shorts. Same comment endpoint as regular videos; works out of the box.
  • Bumped client version. Re-extracted from a fresh watch-page HTML on each run, so it always uses the live version YouTube expects.
  • Mid-run rate limiting. Exponential backoff on 429 and 5xx; rotates between chrome131 and chrome124 TLS profiles on persistent failures.

Example: scrape every comment on a single video

{
"videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
"sortBy": "TOP",
"includeReplies": true
}

Example: TOP 100 comments per video, no replies, multiple videos

{
"videoUrls": [
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"https://www.youtube.com/watch?v=jNQXAC9IVRw"
],
"sortBy": "TOP",
"maxCommentsPerVideo": 100,
"includeReplies": false
}

Example: NEWEST 50 comments, plain integer video IDs

{
"videoUrls": ["dQw4w9WgXcQ", "jNQXAC9IVRw"],
"sortBy": "NEWEST",
"maxCommentsPerVideo": 50,
"includeReplies": true,
"maxRepliesPerComment": 5
}

Notes on data freshness

The comments returned reflect the state of the comment section at scrape time. Re-running an hour later will pick up any new comments posted since (and any comments that were deleted will disappear). The scrapedAt timestamp is your reference for when the snapshot was captured.