# 💬 YouTube Comments Scraper (`citrine_venus/youtube-comments-scraper`) Actor

YouTube Comments Scraper: pull video comments and replies in real time — author, text, likes, pinned, hearted, verified & publish date. Ideal for sentiment analysis, brand monitoring & NLP. No YouTube API key or quota. Stream results to your Apify dataset.

- **URL**: https://apify.com/citrine\_venus/youtube-comments-scraper.md
- **Developed by:** [Data Minds](https://apify.com/citrine_venus) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## 💬 YouTube Comments Scraper — Extract Video Comments, Replies & Engagement Data

**YouTube Comments Scraper** is a production-grade [Apify Actor](https://docs.apify.com/platform/actors) for **YouTube comment scraping**, **audience sentiment analysis** and **engagement research**. Give it one or more YouTube video links and it returns every comment (and, optionally, every reply) — author, full text, like count, publish date, pinned/verified/creator-hearted status and more — written to your Apify **Dataset** in real time as it's collected.

> 💡 **Need a custom version, private integration, or a tailored data pipeline?** Email **<hello.dataminds@gmail.com>**.

Built for **social media analysts**, **brand & reputation monitoring**, **content creators**, **market researchers**, **NLP/ML teams** and **community managers** — anyone who needs **structured YouTube comment data** without scrolling and copy-pasting by hand.

***

### 📑 Table of contents

- [What is YouTube Comments Scraper?](#-what-is-youtube-comments-scraper)
- [Main features](#-main-features)
- [Who is this Actor for?](#-who-is-this-actor-for)
- [What the scraper does](#%EF%B8%8F-what-the-scraper-does)
- [Inputs it accepts](#-inputs-it-accepts)
- [Filtering configuration](#-filtering-configuration)
- [Output format (Dataset)](#-output-format-dataset)
- [Example output (JSON)](#-example-output-json)
- [Quick start](#-quick-start)
- [Input parameters reference](#%EF%B8%8F-input-parameters-reference)
- [Reliability & anti-blocking](#%EF%B8%8F-reliability--anti-blocking)
- [Integrations & automation](#-integrations--automation)
- [Pricing & how to control cost](#-pricing--how-to-control-cost)
- [Frequently asked questions (FAQ)](#-frequently-asked-questions-faq)
- [Troubleshooting](#%EF%B8%8F-troubleshooting)
- [Help, support & custom builds](#-help-support--custom-builds)
- [Is scraping YouTube comments legal?](#%EF%B8%8F-is-scraping-youtube-comments-legal)
- [SEO keywords targeted](#-seo-keywords-targeted)

***

### 💬 What is YouTube Comments Scraper?

YouTube Comments Scraper is an **Apify Actor** that extracts the full comment section of any public YouTube video — top-level comments and, optionally, their replies — into clean, structured data. No YouTube Data API key, no daily quota, and no manual scrolling required. Just paste a video URL (or a hundred) and press **Start**.

Every comment record includes the text, author details, like count, reply count, publish-time estimate, and flags for pinned comments, creator hearts, verified authors and edited comments — everything you need for **sentiment analysis**, **audience research**, **brand monitoring** or feeding into an **LLM/NLP pipeline**.

### ✨ Main features

- 🔗 **Bulk video input** — paste a list, upload a file, or import a Google Sheet of YouTube URLs.
- 💬 **Comments & replies** — collect top-level comments and drill into reply threads, independently capped.
- 🔃 **Two sort modes** — Top comments (relevance) or Newest first (chronological), plus a date cutoff.
- 🎯 **Built-in filters** — minimum likes and a keyword/phrase match, applied before anything is saved.
- 📌 **Rich engagement signals** — pinned status, creator ❤️, verified authors, edited flag, like/reply counts.
- 📡 **Live streaming output** — every comment lands in your dataset the instant it's collected, not at the end.
- 📂 **Six ready-made views** — Overview, Comments, Authors, Engagement, Video source and Errors, no post-processing needed.
- 🌐 **Automatic proxy fallback** — starts direct, escalates to datacenter then residential only if needed, and stays there.
- ⚠️ **Transparent error reporting** — a video that can't be processed shows up in the dataset with a clear reason, it's never silently dropped.
- ⚡ **Configurable concurrency** — tune how many videos and reply threads run in parallel.

### 👥 Who is this Actor for?

- **Social media & brand teams** monitoring what people say under a video, product launch or ad.
- **Content creators & channel managers** analyzing audience feedback at scale, beyond what YouTube Studio shows.
- **Market & academic researchers** studying public sentiment, discourse or misinformation trends.
- **Data scientists / ML engineers** building training or evaluation datasets for sentiment/NLP models.
- **Agencies** running competitor or campaign engagement analysis across many videos at once.

### ⚙️ What the scraper does

1. Takes your list of YouTube video URLs (or bare video IDs).
2. Opens each video and reads its comment section.
3. Collects comments in your chosen order (top or newest), applying your filters as it goes.
4. Optionally expands the reply thread under every comment, up to your configured cap.
5. Writes every kept comment/reply to the dataset **immediately** — you can watch results arrive live in the **Output** tab while the run is still going.
6. If a video can't be processed (private, deleted, region-blocked, comments disabled), it's logged as a clearly-labeled error row instead of being silently skipped.

### 📥 Inputs it accepts

| Input | Accepts |
|---|---|
| **YouTube Video URLs** | Full `watch?v=` links, `youtu.be/` short links, `/shorts/` links, or bare 11-character video IDs — any mix, in bulk. |

### 🎯 Filtering configuration

| Filter | What it does |
|---|---|
| **Max comments per video** | Caps top-level comments collected per video (0 = unlimited). Replies are additional. |
| **Sort order** | Top comments (relevance) or Newest first (chronological). |
| **Only comments after this date** | Absolute (`YYYY-MM-DD`) or relative (`7 days`, `2 weeks`) cutoff — forces Newest-first sorting. |
| **Include replies** | Toggle reply-thread collection on/off. |
| **Max replies per comment** | Caps replies fetched per thread (0 = every reply). |
| **Minimum likes** | Drops comments/replies below this like count. |
| **Keyword filter** | Keeps only comments whose text contains your word/phrase. |

### 📤 Output format (Dataset)

Every comment and reply is one dataset item. The **Output** tab exposes six views over the same data — flip between them without writing any code:

| View | What it shows |
|---|---|
| ✨ **Overview** | The essentials — author, comment, likes, replies, pinned, video title. |
| 💬 **Comments** | Full text and thread metadata (IDs, parent ID, dates, edited flag). |
| 👤 **Authors** | Who wrote it — name, channel ID/URL, avatar, owner/verified flags. |
| 📊 **Engagement** | Likes (raw + as shown), reply count, creator ❤️, pinned. |
| 🎬 **Video source** | Which video each row belongs to — ID, URL, title, total comment count. |
| ⚠️ **Errors** | Videos that couldn't be processed, with a plain-English reason. |

### 🧾 Example output (JSON)

```json
{
  "cid": "Ugzge340dBgB75hWBm54AaABAg",
  "replyToCid": null,
  "type": "comment",
  "publishedTimeText": "1 year ago",
  "publishedTimeEstimate": "2025-09-02",
  "publishedTimePrecision": "year",
  "isEdited": false,
  "comment": "can confirm: he never gave us up",
  "author": "@YouTube",
  "authorChannelId": "UCBR8-60-B28hp2BmDPdntcQ",
  "authorChannelUrl": "https://www.youtube.com/@YouTube",
  "authorAvatarUrl": "https://yt3.ggpht.com/....=s88-c-k-c0x00ffffff-no-rj",
  "authorIsChannelOwner": false,
  "authorIsVerified": true,
  "isPinned": true,
  "replyCount": 963,
  "voteCount": 310000,
  "voteCountText": "310K",
  "hasCreatorHeart": true,
  "videoId": "dQw4w9WgXcQ",
  "pageUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "commentsCount": 2456584,
  "title": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)",
  "isError": false
}
```

An error row (a video that couldn't be processed) looks like this instead:

```json
{
  "isError": true,
  "error": "COMMENTS_UNAVAILABLE",
  "note": "Comments are disabled or unavailable for this video.",
  "videoId": "xxxxxxxxxxx",
  "pageUrl": "https://www.youtube.com/watch?v=xxxxxxxxxxx"
}
```

### 🚀 Quick start

#### Run in Apify Console

1. Log in at [console.apify.com](https://console.apify.com) → **Actors**.
2. Find and open **YouTube Comments Scraper**.
3. Paste your YouTube video URL(s) into **YouTube Video URLs**.
4. (Optional) Adjust the filters, sort order, or proxy under the collapsible sections.
5. Click **Start**.
6. Watch results stream in live under the **Log** and **Output** tabs.
7. Export from **Output** as JSON, CSV, Excel, or query it via API.

#### Run via API

```bash
curl -X POST "https://api.apify.com/v2/acts/cerulean_zucchini~youtube-comments-scraper/run-sync-get-dataset-items" \
     -H "Authorization: Bearer $APIFY_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"urls":[{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ"}],"maxComments":100}'
```

#### Python client

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("cerulean_zucchini/youtube-comments-scraper").call(run_input={
    "urls": [{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}],
    "maxComments": 100,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### ⚙️ Input parameters reference

#### 💬 What to collect

| Field | Type | Default | Description |
|---|---|---|---|
| `urls` | array | — | YouTube video URLs (required). |
| `maxComments` | integer | `100` | Max top-level comments per video. `0` = unlimited. |
| `sortCommentsBy` | string | `TOP_COMMENTS` | `TOP_COMMENTS` or `NEWEST_FIRST`. |
| `oldestCommentDate` | string | — | `YYYY-MM-DD` or relative (`7 days`). |
| `includeReplies` | boolean | `true` | Fetch reply threads. |
| `maxRepliesPerComment` | integer | `1` | Cap per thread. `0` = all. |

#### 🎯 Filters

| Field | Type | Default | Description |
|---|---|---|---|
| `minLikes` | integer | `0` | Minimum like count to keep. |
| `keyword` | string | — | Case-insensitive text match. |

#### 🌐 Language & region

| Field | Type | Default | Description |
|---|---|---|---|
| `hl` | select | 🌐 Auto-detect | Interface language, picked from a dropdown (`en`, `es`, `pt-PT`, ...). |
| `gl` | select | 🌐 Auto-detect | Country/region, picked from a dropdown (`US`, `GB`, `IN`, ...). |

#### 🌍 Network

| Field | Type | Default | Description |
|---|---|---|---|
| `proxyConfiguration` | object | direct → auto-escalates | Apify proxy configuration. |

#### ⚡ Speed & limits

| Field | Type | Default | Description |
|---|---|---|---|
| `videoConcurrency` | integer | `3` | Videos processed in parallel. |
| `replyConcurrency` | integer | `5` | Reply threads expanded in parallel, per video. |
| `maxRetries` | integer | `3` | Retries per request on the current network route. |
| `maxScanned` | integer | `20000` | Safety cap when filters are narrow. |

### 🛡️ Reliability & anti-blocking

- Every request starts on a **direct connection** — fastest, and the friendliest option for YouTube.
- If YouTube pushes back, the run **automatically escalates** to a **datacenter proxy**, then a **residential proxy** — and once escalated, it **stays on that route** for the rest of the run instead of flip-flopping.
- Failed requests are retried with backoff before any proxy change is made.
- One video failing (private, deleted, region-blocked, comments disabled) never stops the run — every other video keeps going, and the failure is written to the **Errors** view with a plain-English reason.
- Results are pushed to the dataset **as they're collected**, so a run that's stopped early still keeps everything found so far.

### 🔌 Integrations & automation

Apify Actors connect natively to the tools you already use:

- **Zapier, Make, n8n** — trigger a run or react to new comments without code.
- **Webhooks** — fire a request to your own endpoint on `ACTOR.RUN.SUCCEEDED` / `FAILED`.
- **Schedules** — run this Actor on a cron schedule to track comment sentiment over time.
- **REST API & client SDKs** — Python and JavaScript clients, or plain REST, for pipelines.
- **Google Sheets / Airtable / Slack** — send results straight into a spreadsheet or channel.
- **MCP** — call this Actor as a tool from Claude, Cursor and other MCP-compatible AI agents.

### 💰 Pricing & how to control cost

This Actor runs on Apify's standard **Pay-per-usage** compute pricing — you pay for the platform resources (compute, proxy, storage) a run consumes, with no separate per-result markup. To manage cost:

- Set **Max comments per video** and **Max replies per comment** to only what you need.
- Leave **Proxy configuration** on its default (direct-first) — a datacenter/residential proxy is only used automatically if YouTube actually requires it.
- Use **Minimum likes** or a **Keyword filter** to narrow results instead of scraping everything and filtering afterward.
- Check the **Resource usage** tab in Console after a run to see exactly what was consumed.

### ❓ Frequently asked questions (FAQ)

**Does this need a YouTube API key or Google login?**
No. It reads the same public comment data the youtube.com website itself displays.

**Can I scrape comments from a private or age-restricted video?**
No — only publicly viewable comments on publicly viewable videos can be collected.

**Why don't all comments have an exact date?**
YouTube itself only ever shows a relative date ("3 weeks ago"). `publishedTimeEstimate` is a best-effort estimate back-calculated from that text at scrape time — `publishedTimePrecision` tells you how coarse the rounding was (day/week/month/year).

**Do I need to configure a proxy myself?**
No — leave **Proxy configuration** on its default and the Actor manages the network route automatically.

**Can I get replies without the parent comments?**
Replies are always collected alongside their parent comment thread; use the `type` field (`comment` vs `reply`) to separate them after the fact if needed.

**What happens if a video has comments disabled or is unavailable?**
It's recorded as a row in the **Errors** view with a reason — the run continues with the rest of your list.

### 🛠️ Troubleshooting

| Symptom | Likely cause / fix |
|---|---|
| A video shows up only in **Errors** | It's private, deleted, region-blocked, or has comments disabled — check the `note` field. |
| Fewer comments than expected on a huge video | The "Top comments" ranked feed has a known depth limit on very large videos — switch **Sort order** to *Newest first* to keep going past it. |
| `publishedTimeEstimate` is empty | Only happens when **Language code (hl)** is forced to a non-English value — leave it empty or set it to `en`. |
| Run seems slow | Lower **Videos in parallel** if you're on a small proxy/memory plan, or raise it if you have headroom. |
| No results at all | Double-check the URLs are valid public YouTube videos, and that your filters (likes/keyword) aren't too strict. |

### 🆘 Help, support & custom builds

Found a bug, have a feature request, or need a custom variant (extra fields, a different platform, scheduled monitoring)? Email **<hello.dataminds@gmail.com>** or open an issue from the Actor's **Issues** tab in Apify Console.

### ⚖️ Is scraping YouTube comments legal?

This Actor only collects **publicly available** comment data that any visitor to youtube.com can already see — no login, no private data, no bypassing of access controls. You are responsible for how you use the collected data: respect YouTube's Terms of Service, applicable data-protection laws (GDPR, CCPA, etc.), and avoid using personal data (like author names) for spam or harassment. Always review the target platform's terms before large-scale or commercial use.

### 🔑 SEO keywords targeted

YouTube comments scraper, extract YouTube comments, scrape YouTube comments, YouTube comment data extractor, download YouTube comments, YouTube comments API alternative, YouTube reply scraper, YouTube engagement data, YouTube sentiment analysis, YouTube audience research, YouTube comment export, YouTube comments to JSON, YouTube comments to CSV, YouTube comment scraper no API key, YouTube comment scraper Python, bulk YouTube comment scraper, YouTube video comments dataset, brand monitoring YouTube, NLP training data YouTube comments, YouTube comment sentiment tool.

# Actor input Schema

## `urls` (type: `array`):

📺 One or more YouTube video links (watch, youtu.be, or /shorts/ links all work) — paste a list, upload a file, or import from a Google Sheet. Every video's comments are collected in the same run.

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

🎯 Stop collecting top-level comments after this many per video. Replies don't count against this cap — see 'Max replies per comment' below. Set to 0 for no limit.

## `sortCommentsBy` (type: `string`):

📌 'Top comments' is YouTube's own relevance ranking. 'Newest first' walks chronologically — pick this if you need recent comments or are using the date filter below.

## `oldestCommentDate` (type: `string`):

⏳ Stop once comments get older than this date. Use an absolute date (YYYY-MM-DD) or a relative value like '7 days' or '2 weeks'. Automatically switches sorting to Newest first. Leave empty to disable.

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

💬 Also fetch the reply thread under every collected comment.

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

📏 Cap on replies fetched per comment thread. Set to 0 to fetch every reply on that thread.

## `minLikes` (type: `integer`):

🚦 Only keep comments (and replies) with at least this many likes.

## `keyword` (type: `string`):

🧵 Only keep comments whose text contains this word or phrase (case-insensitive). Leave empty to keep everything.

## `hl` (type: `string`):

🌍 Force YouTube's interface language for this run. Leave on Auto-detect to use whatever the video page returns. Comment-age estimates (📅 the 'Estimated date' column) are only supported when the language is English.

## `gl` (type: `string`):

🌎 Force the YouTube country/region this run is served from. Leave on Auto-detect to use whatever the video page returns.

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

🚦 By default the run connects directly to YouTube, then automatically escalates to a datacenter proxy and finally a residential proxy only if YouTube pushes back — and stays on that route for the rest of the run. Pick your own route here to override the automatic ladder.

## `videoConcurrency` (type: `integer`):

🚀 How many videos to process at the same time.

## `replyConcurrency` (type: `integer`):

🚀 How many reply threads to expand at the same time, per video.

## `maxRetries` (type: `integer`):

♻️ How many times to retry a single request on the current network route before the run falls back to the next one.

## `maxScanned` (type: `integer`):

🛑 Safety valve for narrow filters (Minimum likes / Keyword filter) — stop after examining this many comments even if the cap isn't reached. Set to 0 for no limit.

## Actor input object example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "maxComments": 10,
  "sortCommentsBy": "TOP_COMMENTS",
  "includeReplies": true,
  "maxRepliesPerComment": 1,
  "minLikes": 0,
  "hl": "",
  "gl": "",
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "videoConcurrency": 3,
  "replyConcurrency": 5,
  "maxRetries": 3,
  "maxScanned": 20000
}
```

# Actor output Schema

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

Every comment and reply collected in this run.

## `overview` (type: `string`):

No description

## `comments` (type: `string`):

No description

## `authors` (type: `string`):

No description

## `engagement` (type: `string`):

No description

## `source` (type: `string`):

No description

## `errors` (type: `string`):

No description

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

No description

# 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 = {
    "urls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("citrine_venus/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 = {
    "urls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("citrine_venus/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 '{
  "urls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call citrine_venus/youtube-comments-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,citrine_venus/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/NWWEjD3T6Naj9Gfc0/builds/ZOOegUoK5DpvutRvG/openapi.json
