# YouTube Comments Scraper (top or newest, with replies) (`scrapemole/youtube-comments-scraper`) Actor

Scrape public YouTube comments and replies from any video or Short: text, likes, reply count, date, pinned, hearted and creator flags, sorted by top or newest. Privacy-first (no commenter names or IDs). Pay only per comment delivered.

- **URL**: https://apify.com/scrapemole/youtube-comments-scraper.md
- **Developed by:** [ScrapeMole](https://apify.com/scrapemole) (community)
- **Categories:** Social media, Videos
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 comment or replies

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## YouTube Comments Scraper: comments and replies, top or newest

Scrape **public YouTube comments and replies** from any video or Short. Every row has the **comment text, like count, reply count, when it was posted, and pinned / hearted-by-creator / posted-by-creator flags**, plus the video title, channel and total comment count. Sort by **Top comments** or **Newest first**, add **replies** if you want them, and export to JSON, CSV, Excel or Google Sheets, or call it from Python, n8n, Make, Zapier or an AI agent.

**You only pay per comment delivered.** Videos with comments turned off, private or deleted videos and invalid links come back as clear error rows and are never charged.

**Privacy-first by design.** The Actor returns *what people say*, not *who they are*: commenter names, @handles, channel IDs and avatars are never collected or returned, and e-mail addresses inside comment text are redacted. That keeps your sentiment, feedback and research datasets clear of personal data (GDPR-friendly), which is what most comment analysis needs anyway.

### Why this comments scraper gets all the comments

- **Reads the same JSON the YouTube website loads** (no headless browser): 300 comments take about 7 seconds, 2,500 newest comments about 25 seconds.
- **Goes past YouTube's "Top comments" ceiling.** YouTube only lists about 1,000 comments under *Top comments*. Pick **Newest first** and the Actor pages through the full history. In our tests it pulled 2,500 of 2,500 requested on a video with millions of comments. When a Top run hits the ceiling, the log tells you.
- **No duplicates, no blank rows.** Comments are de-duplicated across pages, and a run never "succeeds" with zero rows silently: you get `NO_DATA` ("comments are turned off") or `NOT_FOUND` instead.
- **Retries with backoff and a fresh IP** on rate limits, escalates to residential IPs only if YouTube keeps blocking, and gives rate-limited videos a slower second pass at the end.
- **Exact billing.** One `comment` event per row in your dataset (comment or reply), charged only after the row is saved. Set *Max cost per run* and the Actor stops cleanly at your budget.

**Live tests, 19 Oct 2026** (real YouTube, cloud server, **no proxy**): see [Test results](#test-results).

### What you get

| Field | Description |
|---|---|
| `type` | `comment` (top-level) or `reply` |
| `text` | Comment text (e-mails redacted) |
| `likeCount`, `replyCount` | Engagement numbers ("1.2K" converted to 1200) |
| `publishedText`, `publishedAtApprox`, `isEdited` | "3 weeks ago", the approximate date (YYYY-MM-DD) and the edited flag |
| `isPinned`, `isHeartedByCreator`, `isByVideoCreator` | Creator signals |
| `commentId`, `parentCommentId`, `commentUrl`, `position` | IDs, a direct link that highlights the comment, and its order |
| `videoId`, `videoUrl`, `videoTitle`, `videoChannelName`, `totalCommentsOnVideo` | Video context on every row |

### How to scrape YouTube comments

1. Paste one or more **video links or IDs** (watch links, `youtu.be`, Shorts, live and embed URLs all work).
2. Set **Max comments per video**, pick **Top** or **Newest first**, and turn on **Include replies** if you need them.
3. Click **Start** and download the comments as JSON, CSV or Excel, or read them through the API.

#### Input example

```json
{
  "videos": ["https://www.youtube.com/watch?v=aircAruvnKk", "https://www.youtube.com/shorts/VIDEO_ID"],
  "maxComments": 500,
  "sortBy": "newest",
  "includeReplies": true,
  "maxRepliesPerComment": 10
}
```

#### Output example

```json
{
  "status": "ok",
  "type": "comment",
  "videoId": "aircAruvnKk",
  "videoUrl": "https://www.youtube.com/watch?v=aircAruvnKk",
  "videoTitle": "But what is a neural network? | Deep learning chapter 1",
  "videoChannelName": "3Blue1Brown",
  "totalCommentsOnVideo": 9418,
  "sortBy": "top",
  "position": 2,
  "parentCommentId": null,
  "commentUrl": "https://www.youtube.com/watch?v=aircAruvnKk&lc=Ugwedfi--9yZVC0eefl4AaABAg",
  "commentId": "Ugwedfi--9yZVC0eefl4AaABAg",
  "text": "I study mathematics, physics and architecture. By definition this man is an ORACLE in the strict meaning of the word...",
  "publishedText": "7 years ago (edited)",
  "publishedAtApprox": "2019-10-19",
  "isEdited": true,
  "likeCount": 13000,
  "replyCount": 173,
  "isHeartedByCreator": false,
  "isByVideoCreator": false,
  "isPinned": false
}
```

#### Videos with comments turned off

```json
{ "status": "error", "videoId": "XXXXXXXXXXX", "errorCode": "NO_DATA", "errorMessage": "Comments are turned off or unavailable for this video." }
```

Not charged.

### Switching from another YouTube comments Actor

Already calling **streamers/youtube-comments-scraper** from code, a schedule or Make/Zapier? Change the Actor ID and keep your input JSON: this Actor accepts the same field names.

| Their input | Here |
|---|---|
| `startUrls` (`[{ "url": "https://www.youtube.com/watch?v=..." }]`) | Same |
| `maxComments` | Same (per video, top-level comments) |
| `sortCommentsBy: "TOP_COMMENTS"` / `"NEWEST_FIRST"` | Same values (`sortBy: "top"` / `"newest"`) |
| `oldestCommentDate` | Ignored for now; use `sortBy: "newest"` with `maxComments` |

Newest-first paging goes past YouTube's ~1,000-comment cap on the Top list, so long videos return their full comment history.

### Pricing

Pay per comment (replies count as comments). Proxy and platform costs are included, with no start fee.

| Apify plan | Price per comment | 1,000 comments |
|---|---|---|
| Free | $0.001 | $1.00 |
| Starter (Bronze) | $0.0008 | $0.80 |
| Scale (Silver) | $0.0006 | $0.60 |
| Business (Gold) | $0.0005 | $0.50 |

### Use cases

- **Sentiment and audience research:** what viewers love, hate and ask about a product, launch, trailer or creator.
- **Product feedback mining:** feature requests and complaints under review and tutorial videos.
- **Content ideas and FAQs:** the questions your audience keeps asking.
- **AI and LLM pipelines:** clean, identity-free comment text for classification, topic modelling, RAG or fine-tuning.
- **Brand and campaign monitoring:** track reactions on your own and competitors' videos over time (schedule the Actor with *Newest first*).

### API, Python and AI agents

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("scrapemole/youtube-comments-scraper").call(run_input={
    "videos": ["https://www.youtube.com/watch?v=aircAruvnKk"], "maxComments": 200, "sortBy": "newest"
})
for c in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(c.get("likeCount"), c.get("text", c.get("errorMessage"))[:120])
```

Works with n8n, Make, Zapier, LangChain, LlamaIndex and the Apify MCP server, so Claude, ChatGPT or Cursor agents can pull comments on their own.

### Test results

Live tests on 2026-10-19 against real YouTube from a cloud server with **no proxy**: 8 runs over 11 videos (lectures, music videos, tutorials, news, the first YouTube video), Top and Newest, with and without replies.

| Metric | Result |
|---|---|
| Runs finished OK | **8/8** |
| Comments delivered | **2,250** top-level + **343** replies |
| Duplicate rows | **0** |
| Rows with commenter identity fields | **0** |
| Billing | Charged exactly once per row delivered (2,593 events) |
| Newest-first deep paging | 2,500/2,500 comments on a video with millions of comments |
| Edge cases | not-found and invalid links (not charged), empty input, budget cap stops at exactly 7 of 100: **all pass** |
| Blocks | 0 |

### FAQ

**Why do I get about 1,000 comments with "Top comments"?** That's a YouTube limit: the Top list stops around 1,000. Choose **Newest first** to get everything.

**Can I get commenter names or channel IDs?** No, on purpose. This Actor is built for analysing what is said without collecting personal data. If you need to know who commented, this isn't the right tool.

**Are replies included?** Only if you turn on **Include replies**. Each reply is one row with `type: "reply"` and the `parentCommentId`.

**Does it work for Shorts and live streams?** Yes for Shorts and finished streams with comments. Live chat isn't comments, so it isn't included.

**Age-restricted or members-only videos?** YouTube requires sign-in for these. The Actor doesn't log in, so they return a clear error and aren't charged.

**Is it legal?** The Actor only reads publicly visible comments and doesn't collect commenter identities. Respect YouTube's terms and applicable law when you reuse the data.

**Found a problem?** Open an issue with the run link. Each run stores a `RUN_SUMMARY` (requests, retries, errors) to help debug it.

### More from ScrapeMole

ScrapeMole builds focused, reliable scrapers for public data: pay per result, no start fees, clear error rows that are never charged, and a `RUN_SUMMARY` on every run.

- [YouTube Transcript & Subtitles Scraper](https://apify.com/scrapemole/youtube-transcript-scraper)
- [Google Trends Scraper](https://apify.com/scrapemole/google-trends-scraper)
- [YouTube Scraper](https://apify.com/scrapemole/youtube-video-channel-scraper)
- [Telegram Channel Scraper](https://apify.com/scrapemole/telegram-channel-scraper)
- [Amazon Product & Search Scraper](https://apify.com/scrapemole/amazon-product-scraper)

Building an AI agent with its own wallet? The YouTube and Google Trends data is also sold per call over [x402](https://www.x402.org) (USDC on Base, no account): see [scrapemole.pages.dev](https://scrapemole.pages.dev). Questions or a missing field? Open an issue on this Actor. ScrapeMole is the maker of this Actor.

# Actor input Schema

## `videos` (type: `array`):

YouTube video URLs or 11-character video IDs. Any URL form works: watch, youtu.be, Shorts, embed, live.

## `startUrls` (type: `array`):

Same as Videos, in URL-list form. Handy when pasting from a spreadsheet or another Actor's output.

## `maxComments` (type: `integer`):

Stop after this many top-level comments for each video. Replies (if enabled) come on top of this.

## `sortBy` (type: `string`):

Top comments (YouTube's ranking) or newest first.

## `includeReplies` (type: `boolean`):

Also scrape replies under each comment. Each reply is one extra row (and one extra 'comment' charge).

## `maxRepliesPerComment` (type: `integer`):

Only used when Include replies is on.

## `language` (type: `string`):

Language for relative dates such as "2 days ago" (keep "en" so dates can be parsed).

## `country` (type: `string`):

Two-letter country code YouTube uses for ranking.

## `maxConcurrency` (type: `integer`):

How many videos to scrape at once.

## `proxyConfiguration` (type: `object`):

Apify Proxy (automatic) works well. The Actor rotates IPs on blocks and only escalates to residential if YouTube keeps blocking.

## Actor input object example

```json
{
  "videos": [
    "https://www.youtube.com/watch?v=aircAruvnKk"
  ],
  "maxComments": 100,
  "sortBy": "top",
  "includeReplies": false,
  "maxRepliesPerComment": 20,
  "language": "en",
  "country": "US",
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All dataset rows (status ok or error).

## `runSummary` (type: `string`):

JSON summary: processed/ok/failed counts, error codes, events charged, HTTP stats.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "videos": [
        "https://www.youtube.com/watch?v=aircAruvnKk"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapemole/youtube-comments-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "videos": ["https://www.youtube.com/watch?v=aircAruvnKk"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapemole/youtube-comments-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "videos": [
    "https://www.youtube.com/watch?v=aircAruvnKk"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapemole/youtube-comments-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapemole/youtube-comments-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/35gnpX1U9D1BFGMWY/builds/VrcM9GMJLdzb0lun4/openapi.json
