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

Scrape YouTube comments with author, likes, reply counts and timestamps. Sort by top or newest, optionally include replies, no login or API key required.

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

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

Pull the comment section off any YouTube video into a clean dataset — comment text, author, likes, reply counts and timestamps. Works on regular videos, Shorts and live replays. **No login, no cookies, no API key, and no YouTube quota.**

300 comments across three videos takes about 35 seconds.

### What you get

Every comment becomes one row:

| Field | Description |
|---|---|
| `commentId` | YouTube's own comment ID — stable, good for de-duplication across runs |
| `text` | The comment itself |
| `author` | Display name, e.g. `@YouTube` |
| `authorChannelId` | Channel ID of the commenter |
| `authorChannelUrl` | Direct link to their channel |
| `authorAvatar` | Profile picture URL |
| `authorIsCreator` | Whether the comment is from the video's own channel |
| `authorIsVerified` | Verified or official-artist channel |
| `likeCount` | Number of likes |
| `likeCountText` | YouTube's own display form, e.g. `301K` |
| `replyCount` | Replies on that thread |
| `publishedTime` | Relative time as YouTube shows it, e.g. `1 year ago` |
| `isEdited` | Whether the comment was edited |
| `isPinned` | Pinned to the top by the creator |
| `isHeartedByCreator` | Creator gave it a heart |
| `replyLevel` | `0` for a top-level comment, `1` for a reply |
| `videoId`, `videoUrl`, `scrapedAt` | Which video the comment came from, and when |

### Example

```json
{
  "commentId": "Ugzge340dBgB75hWBm54AaABAg",
  "text": "can confirm: he never gave us up",
  "author": "@YouTube",
  "authorChannelUrl": "https://www.youtube.com/channel/UCBR8-60-B28hp2BmDPdntcQ",
  "authorIsVerified": true,
  "likeCount": 301000,
  "likeCountText": "301K",
  "replyCount": 962,
  "publishedTime": "1 year ago",
  "isPinned": true,
  "replyLevel": 0,
  "videoId": "dQw4w9WgXcQ"
}
```

### Input

| Option | Description |
|---|---|
| **Video URLs** | Watch, share, Shorts or embed links — or bare 11-character video IDs. Required. |
| **Max comments per video** | How many to collect per video, up to 20,000. YouTube returns about 20 per request. |
| **Sort by** | Top comments (YouTube's default ranking) or newest first. |
| **Include replies** | Also collect replies to each comment. |
| **Max items** | Hard cap across the whole run. |
| **Proxy configuration** | Residential proxy, required and on by default. |

### Use it for

- **Audience research** — what people actually say under your videos, or a competitor's
- **Sentiment analysis** — feed the `text` column straight into a model
- **Creator outreach** — find engaged commenters, with channel links included
- **Moderation review** — pull everything newest-first and scan it in a spreadsheet
- **Trend tracking** — re-run on a schedule and diff on `commentId`

### Honest notes

- **Like counts above 1,000 are approximate.** YouTube itself displays `301K` rather than an exact figure and publishes the precise number nowhere, so `likeCount` becomes `301000`. Counts under 1,000 are exact. The original display string is kept in `likeCountText` so you can always see what YouTube actually showed.
- **`publishedTime` is relative**, not a date — `1 year ago`, `7 minutes ago` — because that is the only form YouTube returns for comments. Combine it with `scrapedAt` if you need to anchor it.
- **Replies are opt-in and count toward your limit.** YouTube preloads a teaser reply under popular threads; those are filtered out unless you switch replies on, so a run with replies off returns top-level comments only.
- **Videos with comments disabled return a clear error row** rather than an empty result, so you can tell "no comments" apart from "comments turned off".
- **Residential proxy is required.** YouTube blocks Apify's datacenter IPs. The Actor takes a fresh proxy session per request and retries refusals automatically.

### Pricing

Pay per comment actually extracted. Failed or blocked requests cost you nothing, and there is no per-page or per-hour charge — retries are on us.

# Actor input Schema

## `videoUrls` (type: `array`):

YouTube video URLs or IDs. Watch, share, Shorts and embed links all work, e.g. https://www.youtube.com/watch?v=dQw4w9WgXcQ

## `maxCommentsPerVideo` (type: `integer`):

How many comments to collect from each video. YouTube returns about 20 per request.

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

Order comments the way YouTube does: top comments first, or newest first.

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

Also collect replies to each comment. Replies count towards the per-video limit and need an extra request per thread, so runs take longer.

## `maxItems` (type: `integer`):

Hard cap on total comments across all videos. 0 means no cap.

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

YouTube blocks Apify's datacenter IPs, so residential proxy is required. Leave this as it is unless you know what you are changing.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "maxCommentsPerVideo": 100,
  "sortBy": "top",
  "includeReplies": false,
  "maxItems": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Every comment scraped, one row each.

## `csv` (type: `string`):

The same comments as a spreadsheet-ready CSV file.

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

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

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

```

## MCP server setup

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