The direct answer: if you already run a Google Cloud project, the official commentThreads.list endpoint is a strong choice, and quota is not an argument against it: 1 unit per call, up to 100 top-level comments per page, from the general 10,000-unit daily pool — in the theoretical extreme, around a million top-level comments a day at no documented fee. Its costs are of a different kind: the project-and-key setup, a documented replies-subset caveat that needs per-thread follow-up calls, a 403 error to catch when a video has comments disabled, and a resource schema that omits watch-page context like pinned and creator-heart flags. The YouTube Comments Scraper trades that allowance for the integration job: a video URL in, one JSON row per comment out, replies opt-in in the same pass (capped together with top-level comments by maxComments, so a thread can be cut off mid-replies), comments-off videos as unbilled coded rows, $0.40 per 1,000 comments, no Google project at all.
Every claim about the Data API below links Google's own documentation, all verified on 2026-07-22. The actor side was run first-hand the same day — the run and its evidence file are below, including two actor defects the run itself surfaced, disclosed rather than hidden.
The quota arithmetic, honestly
Per the commentThreads.list reference and quota documentation: a call costs 1 unit, maxResultsaccepts 1–100 (default 20), and comment methods draw from the general 10,000-unit daily pool — Google's June 2026 bucket revision moved search.list, videos.insert, and videos.batchGetStats into their own buckets and left comments in the pool. So the ceiling arithmetic is 10,000 calls × 100 comments = roughly 1,000,000 top-level comments per day — assuming full pages and the entire pool spent on comments. Unlike our search.list comparison, where the official bucket is 100 calls a day, the general pool allows 10,000 one-unit comment calls a day — 100 times as many calls. This page argues integration mechanics, not scarcity.
What the API returns — and the three documented caveats
- Replies are a subset. The commentThreads resource documents it plainly: "The list contains a limited number of replies, and unless the number of items in the list equals the value of the snippet.totalReplyCount property, the list of replies is only a subset." Complete replies mean one or more paginated
comments.listcalls per thread (1 unit each, up to 100 replies per page, continued vianextPageToken), withparentIdplumbing. The actor removes that plumbing but has its own honest limit:maxCommentscaps top-level comments and replies together, so it does not guarantee complete threads either — the run below delivered 180 of a pinned thread's reported 1,000 replies before hitting its cap. - Text can differ from what was written. Per the comments resource,
textDisplay"may differ from the original comment text" (video links can become titles), andtextOriginal"is only returned to the authenticated user if they are the comment's author." - The schema stops at the API's view. The documented snippet carries author, exact integer
likeCount, timestamps, and moderation fields — and documents no property for pinned status, creator hearts, or verified/creator/artist badges. Those exist on the watch page, not in the resource.
On the other side of that ledger: the API's likeCountis an exact integer where the actor returns a display string ("264K"), and its timestamps are precise where the actor's are relative ("1 year ago") — for precision analytics on comment engagement, the official resource is the stronger dataset.
The disabled-comments contract, side by side
Google documents the failure mode: a video with comments turned off returns HTTP 403 with reason commentsDisabled — an exception your batch code must catch, distinguish from quota and auth failures, and route around. The actor's contract for the same event is a dataset row: unbilled success: false with code COMMENTS_DISABLED, while the rest of the batch continues. The run below exercised exactly this with a made-for-kids video.
The decision, by dimension
| Dimension | Data API commentThreads + comments | YouTube Comments Scraper |
|---|---|---|
| Setup | Google Cloud project + API key (public reads need no OAuth). Google documentation. | Apify API token; one call per batch. By design — Apify platform auth. |
| Quota / volume ceiling | 1 unit per page of up to 100; general 10,000-unit daily pool; ~1,000,000 top-level comments/day in the theoretical extreme. No fees documented, quota-governed. Google documentation; arithmetic from documented costs. | No YouTube Data API quota; runs are bounded by maxComments, the 50-video batch limit, and Apify spend limits. $0.40 per 1,000 delivered comments, failures unbilled. apihq list pricing. |
| Replies | Thread responses carry a documented subset; complete replies need one or more paginated comments.list calls per thread with parentId plumbing. Google documentation. | Opt-in (includeReplies) in the same run; reply rows carry reply_level and parent_comment_id. maxComments caps top-level comments and replies together, so a thread can be cut off mid-replies. apihq documentation; the run below delivered 180 of a pinned thread's reported 1,000 replies. |
| Per-comment data precision | Exact integer likeCount, precise timestamps — stronger for engagement analytics. Google documentation. | Display strings ("264K", "1 year ago"). apihq documentation. |
| Watch-page context flags | Not in the documented resource schema (no pinned, creator-heart, or badge properties). Google documentation (absence in the schema). | is_pinned, author_is_verified, author_is_creator, author_is_artist per row; is_hearted exists but is currently unreliable — a disclosed defect, see the run below. apihq documentation; distributions shown in the run below. |
| Comments disabled | HTTP 403, reason commentsDisabled — an exception to catch. Google documentation. | Unbilled success: false row, code COMMENTS_DISABLED; batch continues. apihq documentation; demonstrated in the run below. |
| Ordering | order: time (default) or relevance. Google documentation. | sort: top or newest. apihq documentation. |
| Terms-of-service posture | Official API under the YouTube API Services Terms of Service. First-party assessment. | Reads public data outside the official API; not affiliated with or endorsed by YouTube. First-party assessment. |
When the Data API is the better choice
- Engagement analytics that need exact numbers: integer like counts and precise timestamps — the actor's display strings are a real limitation for that job.
- Volume without per-result fees: no per-call fee is documented and the general pool's ceiling is large, if you have the Google project to spend it from.
- Relevance-ordered retrieval and moderation workflows (moderation status filtering, with OAuth) — official-surface capabilities the actor does not have.
- Workflows that must stay inside Google's official API surface for compliance reasons.
When the actor is the better choice
- Zero-setup pipelines: no Google Cloud project or key — a video URL or bare ID in, one JSON row per comment out, from one HTTP call in n8n, Make, or a scheduled workflow.
- Batches with a failure contract: up to 50 videos per run, and a comments-off, deleted, or private video costs $0 as a coded
success: falserow instead of an API exception to catch (Google documentscommentsDisabledas 403 andvideoNotFoundas 404). The run below demonstrates the comments-disabled case first-hand. - Replies without plumbing:
includeReplies: truebrings threaded replies into the same dataset with parent IDs attached, instead of paginated follow-up calls per thread — within the sharedmaxCommentscap, not as a complete-thread guarantee. - Watch-page context: pinned status and author badges land on each row (with the
is_hearteddefect disclosed below until fixed).
The first-hand actor run, as evidence
On 2026-07-22 at 17:32 UTC we ran the YouTube Comments Scraper (build 0.1.2) once with two videos in the same batch: dQw4w9WgXcQ with maxComments: 200, sort: newest, and includeReplies: true, plus XqZsoesa55w — a made-for-kids video with comments disabled (Apify run qn7uV8aanG8q1dl7g). The run finished SUCCEEDED in 16 seconds with 201 dataset rows: 200 billed comment rows — 200 unique comment IDs, 20 top-level and 180 replies, every reply carrying its parent_comment_id. All 180 replies belong to the one pinned thread, which reports 1,000 replies: the run hit the shared maxComments: 200cap and delivered 180 of that thread's reported 1,000 — the cap trade-off stated in the replies section, observed live. Alongside them came one unbilled success: false row with code COMMENTS_DISABLED for the kids video, while the batch completed normally. The run emitted 200 comment charge events; at the public list price of $0.0004 per comment that is $0.08 (we ran our own actor, so this is a list-price value, not an observed customer charge).
The run also surfaced two actor defects, which we disclose rather than hide. is_hearted came back true on all 200 rows — implausible, since every other flag varied normally in the same run (1 pinned, 1 verified author, 0 creator rows) — so treat the field as unreliable until fixed. And 31 of the 200 rows carried a whitespace-only like_count rather than the documented empty case — consistent with zero-like comments, where the watch page renders no count. Both are recorded as committed known-issue records in the actor's private source repository (found in build 0.1.2, commits 5e9e237 and 8e8d6e1) and disclosed on the actor's documentation.
The sanitized run output — comment IDs, reply structure, raw like_count display strings, flag values, and relative publish strings; comment text bodies, author names, author channel IDs, and avatars removed — is published with full run metadata (timestamps, build, dataset ID, charge counts, price calculation) at /evidence/youtube-comments-run-2026-07-22.json. Each row's public permalink supports a spot check that the comment exists where we say it does. Text and author fields were removed and cannot be checked from the artifact; the retained mutable values (likes, flags, relative timestamps) are crawl-time observations that cannot be fully re-derived from the live page. It is one run against one video on one date — not a reliability or coverage statistic, and no Data API side-by-side was executed.
Methodology and sources
- No first-hand Data API run:Data API rows rest on Google's documentation — linked at every claim and re-checked on the last-verified date above. The watch-page-flags row states a documented absence in the resource schema, not observed API behavior.
- Actor rows: pricing, output fields, and failure behavior come from the actor's documentation, the canonical copy for this site — it currently includes disclosures not yet synced to the Apify listing; the sync is queued. The comments-disabled contract, reply delivery under the shared
maxCommentscap (180 of a reported 1,000), and flag distributions — including the two disclosed defects — are demonstrated by the first-hand run above; the remaining actor rows are documentation claims, reproducible with one run. - Corrections:if Google's documented behavior changes or a row is wrong, use the support and corrections route; the page carries its last-verified date at the top.