# Youtube Comments Scraper (`grow_media/youtube-comments-scraper`) Actor

Scrape YouTube comments with detailed author info. Extract comment text, likes, replies, timestamps, and channel details. Sort by relevance or newest. No proxies needed. Perfect for sentiment analysis and engagement tracking.

- **URL**: https://apify.com/grow\_media/youtube-comments-scraper.md
- **Developed by:** [Grow Media](https://apify.com/grow_media) (community)
- **Categories:** Social media
- **Stats:** 71 total users, 0 monthly users, 88.9% runs succeeded, 3 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.0007 / result

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?

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

Scrape **YouTube video comments** (author, text, likes, replies, verified/artist/creator status) from **one or many videos** in a single run. Each comment is stored as a flat dataset record together with the video it came from.

The Actor validates every video through the **YouTube Data API** (using a server-side access token, no API key needed on your side) and then fetches comments in **paged batches** until it reaches the number you asked for.

### Features

- ✅ **Multiple videos per run** — pass any number of video URLs or IDs in `startUrls`.
- ✅ **Remote URL lists** — a `startUrls` entry can point to a `.txt`/list URL whose lines are video URLs (`requestsFromUrl`).
- ✅ **Validation** — each video ID is checked via the YouTube Data API first; invalid IDs are reported without stopping the run.
- ✅ **Exact counts** — results are trimmed so you get precisely the number of comments you request (or fewer if the video has fewer top-level comments).
- ✅ **Sort order** — fetch **top** or **newest** comments.
- ✅ **Server-side token flow** — the access token is fetched automatically; no Google API key in the input.

### Input

Configure the Actor from the input UI or API:

| Field | Type | Required | Default | Description |
| ----- | ---- | -------- | ------- | ----------- |
| `startUrls` | array | ⬜ | — | One or more video **URLs** or bare 11-character **IDs** to scrape. Each element may also be an object with `requestsFromUrl` pointing to a remote file that lists more URLs/IDs (one per line). |
| `maxComments` | integer | ⬜ | `20` | How many comments to scrape from **each** video before stopping (min `1`). |
| `sort` | string | ⬜ | `top` | Comment sort order: `top` or `newest`. |

Accepted video formats (any of):

- `https://www.youtube.com/watch?v=VIDEO_ID`
- `https://youtu.be/VIDEO_ID`
- `https://www.youtube.com/shorts/VIDEO_ID`
- `https://www.youtube.com/embed/VIDEO_ID`
- `https://www.youtube.com/live/VIDEO_ID`
- just the bare 11-character ID, e.g. `zQGOcOUBi6s`

Example input:

```json
{
  "startUrls": [
    { "url": "https://www.youtube.com/watch?v=zQGOcOUBi6s" },
    { "url": "nx-mGN2Fz5M" },
    { "requestsFromUrl": "https://example.com/video-list.txt" }
  ],
  "maxComments": 20,
  "sort": "newest"
}
```

### Output

Each item in the run's dataset is **one comment** flattened with the video it belongs to:

```json
{
  "commentId": "Ugw9ufCpvXQeZLR8NJV4AaABAg",
  "authorText": "@Saltpork305",
  "authorChannelId": "UCEh6DtyiC17EX89Dv-fafbw",
  "authorAvatar": "https://yt3.ggpht.com/...",
  "textDisplay": "1:13:40 Oh you sweet summer child...",
  "commentPublishText": "24 minutes ago",
  "likesCount": "1",
  "replyCount": "",
  "isVerified": false,
  "isArtist": false,
  "isCreator": false,
  "videoId": "S_Pu-DLXbKc",
  "pageUrl": "https://www.youtube.com/watch?v=S_Pu-DLXbKc",
  "title": "Dune: Part Two | FIRST TIME WATCHING | Reaction",
  "commentsCount": 536
}
```

#### Comment fields

| Field | Type | Description |
| ----- | ---- | ----------- |
| `commentId` | string | YouTube's ID of the comment. |
| `authorText` | string | Display name of the author (usually starts with `@`). |
| `authorChannelId` | string | Channel ID of the author. |
| `authorAvatar` | string | URL of the author's avatar. |
| `textDisplay` | string | The comment text, including mention/URL formatting. |
| `commentPublishText` | string | Human-readable publish time (e.g. `2 months ago`). |
| `likesCount` | string | Number of likes on the comment (as a string). |
| `replyCount` | string | Number of replies to the comment; empty when none. |
| `isVerified` | boolean | Whether the author has a verified badge. |
| `isArtist` | boolean | Whether the author is an official artist. |
| `isCreator` | boolean | Whether the author is the video's channel owner. |

#### Video fields (added to every comment)

| Field | Type | Description |
| ----- | ---- | ----------- |
| `videoId` | string | The 11-character ID of the video. |
| `pageUrl` | string | Full URL of the video. |
| `title` | string | Title of the video. |
| `commentsCount` | integer | Total top-level comments on the video (from the YouTube Data API). |

#### Error rows

Runs can also push non-comment records that carry an `error` flag:

| `error` | Meaning |
| ------- | ------- |
| `INVALID_INPUT` | No usable video IDs/URLs were provided (run fails with exit code `91`). |
| `SCRAPE_ERROR` | That video was skipped after a validation or scraping failure; the row includes its `videoId`, `pageUrl` and a `note`. |
| `NO_RESULTS` | The video has no comments (when no video yields anything, the run fails with exit code `1`). |

### Cost and performance

- **YouTube Data API**: one `videos.list` validation call per video.
- **Comment fetching**: happens on the backend server in pages of ~20 comments, so the Actor itself stays lightweight — scraping a few thousand comments typically uses only a fraction of a CU.
- Billing is [pay-per-usage](https://docs.apify.com/platform/billing/usage-and-cost), proportional to the number of videos and pages requested.

### FAQ

#### Do I need a YouTube API key?

No. The Actor automatically obtains an OAuth access token from its backend token endpoint and uses it for video validation.

#### Why does the count differ from YouTube's comment count?

A video's `commentCount` reflects **top-level comments only** (replies are excluded), which is exactly what this scraper collects — so the numbers should line up.

#### Is scraping YouTube comments allowed?

Always review [YouTube's Terms of Service](https://www.youtube.com/t/terms) and the applicable laws in your jurisdiction. This Actor only reads publicly visible data.

#### Troubleshooting

- **`Invalid video ID`** — the ID is malformed or the video is private/removed. Check the URL/ID in `startUrls`.
- **`SCRAPE_ERROR`** — validation or fetching failed for that video; check the `note` field on the row. The run continues with the remaining videos.
- **No results at all** — every video had zero comments; the run ends with exit code `1` (`NO_RESULTS`).

### Contact

Custom solutions and integrations on request — open an issue or reach out via your Apify account.

# Actor input Schema

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

One or more YouTube video URLs or 11-char video IDs to scrape (e.g. https://www.youtube.com/watch?v=zQGOcOUBi6s or zQGOcOUBi6s). An entry can also be an object with "requestsFromUrl" pointing to a remote file that lists video URLs/IDs, one per line.

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

How many comments to scrape from each video before stopping.

## `sort` (type: `string`):

How to order comments: top or newest.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.youtube.com/watch?v=zQGOcOUBi6s"
    }
  ],
  "maxComments": 20,
  "sort": "top"
}
```

# Actor output Schema

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

Flat records of scraped comments. Each item is one top-level comment with its author, text, likes, replies and verified/artist/creator flags, plus the videoId, pageUrl, title and commentsCount of the video it belongs to. Rows carrying an error field (INVALID\_INPUT, SCRAPE\_ERROR, NO\_RESULTS) are not comments.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.youtube.com/watch?v=zQGOcOUBi6s"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("grow_media/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 = { "startUrls": [{ "url": "https://www.youtube.com/watch?v=zQGOcOUBi6s" }] }

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

```

## MCP server setup

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