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

Scrape YouTube comments and nested replies from videos, Shorts, community posts, channels and playlists. Exact like counts and publish times, full reply threads up to 6 levels deep, plus optional video and channel details. Export to JSON, CSV or Excel.

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

## Pricing

from $0.30 / 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

Scrape **YouTube comments and nested replies** from videos, Shorts, live streams, community posts, and whole channels or playlists into clean JSON, CSV or Excel. Every comment comes with the **exact like count**, **exact publish time**, author details, pinned and creator-heart flags, and the links you need to **rebuild every reply thread** - up to 6 levels deep. No YouTube account, no login and no API key needed.

Use it for **audience and sentiment research**, **brand and product monitoring**, **community management**, **lead and influencer research**, **AI / LLM training data** and **analytics dashboards**.

### What you get

#### Every comment and reply

One row per comment or reply with the text, author (name, channel, avatar, verified, **is the channel owner**), **exact like count**, reply count, **exact publish time**, edited, pinned and **creator heart**. Each row carries `replyLevel`, `parentId` and `rootId`, plus the `videoId` and `videoTitle` (or `postId`) it belongs to.

#### Nested replies, as deep as you want

Replies are collected up to **6 levels deep** (replies to replies to replies). You choose the depth and how many replies per comment.

#### Optional extras (each in its own table)

- **Video details** - title, description, views, likes, comment count, publish date, duration, tags and channel for every video, Short or post you scraped.
- **Channel details** - for the channel of every video and post: subscribers, total views, video count, country, join date, description and **every social / website link**.

Comments are always in the main (default) table, so integrations, exports and the API get them straight away. The extras go to their own tables, and the run log ends with one line per table and a link to it.

### Input

| Field | What it does |
| --- | --- |
| **YouTube links** | Video, Short and live links, `youtu.be` links, community post links, and channel (URL or `@handle`) or playlist links |
| **Maximum comments per video** | Top-level comments per video, Short or post |
| **Comments order** | Top comments or newest first |
| **Reply depth** | 0 = no replies, 1 = direct replies, up to 6 for replies to replies |
| **Maximum replies per comment** | Replies collected under each comment, at every level |
| **Comments published after** | Only keep comments newer than a date (e.g. `2026-09-01` or `7 days`) |
| **Videos per channel or playlist** | For channel and playlist links: comments from this many of the newest videos |
| **$ Add video details** | Adds a row per video, Short or post |
| **$ Add channel details** | Adds a row per channel, with social links |

#### Example input

```json
{
    "startUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/shorts/T_SMf9j50uc",
        "@mkbhd"
    ],
    "maxComments": 100,
    "commentsSortBy": "top",
    "maxReplyDepth": 2,
    "maxRepliesPerComment": 10,
    "maxVideos": 5
}
```

### Example output

#### Comment (a reply)

```json
{
    "type": "comment",
    "id": "UgwbFVC25OjzrbY9iYB4AaABAg.AatakisKOuLAatdb_dHJlU",
    "text": "That is a great way of using these tools as a supportive study tool for students!",
    "author": {
        "name": "@TeachersTechHQ",
        "channelId": "UCM3mutT2jaaAIrqiMqom11g",
        "isVerified": false,
        "isChannelOwner": true,
        "url": "https://www.youtube.com/@TeachersTechHQ"
    },
    "likeCount": 1,
    "replyCount": 0,
    "replyLevel": 1,
    "parentId": "UgwbFVC25OjzrbY9iYB4AaABAg",
    "rootId": "UgwbFVC25OjzrbY9iYB4AaABAg",
    "publishedAt": "2026-09-18T09:41:02Z",
    "estimatedPublishedAt": null,
    "isEdited": false,
    "hasCreatorHeart": false,
    "isPinned": false,
    "videoId": "cIScTGWMrgg",
    "videoTitle": "AI Tools for Teachers: How Students Can Use AI to Learn, Not Just Get Answers?"
}
```

***

### Pricing

You pay only for results you receive - never for links, retries, or videos that turned out to be private, deleted or have comments turned off.

| Result | Price per 1,000 |
| --- | --- |
| Comment or reply (any level) | **$0.50** |
| Video details add-on (per video or Short) | **$1.50** |
| Post details add-on (per community post) | **$1.00** |
| Channel details add-on (per channel) | **$2.00** |

Prices are for the Apify Free plan; paid Apify plans get lower prices automatically. **Sorting and date filters are free.** You can set a maximum cost per run in the run options - the Actor stops cleanly when it is reached.

### Free plan

On Apify's free plan a run uses up to 5 links, 10 comments per video with 1 level of replies (3 per comment), and 5 videos per channel or playlist. Every feature works, so you can try all of them before upgrading.

### Good to know

- **Community post comments** have no exact time: YouTube only shows "3 days ago" for them, so they get `estimatedPublishedAt` (worked out from `publishedTimeText`) and an empty `publishedAt`. Video comments have exact times in `publishedAt`.
- **Comments turned off, private, removed and members-only** videos are skipped and not charged; the run log says which.
- **"Comments published after"** switches the order to newest first, so the run can stop as soon as it reaches older comments.
- Want search results, channel profiles, transcripts or community posts too? Use our **YouTube Scraper**, which does all of that in one run.

### FAQ

**Do I need a YouTube account or API key?** No. Everything is public data, collected without logging in.

**How do I rebuild comment threads?** Group rows by `rootId`; each reply's `parentId` is the comment it answers and `replyLevel` is its depth (0 = top-level comment). `replyCount` is YouTube's own number: every reply below that comment, at all levels (so a reply with 1 answer that itself has 4 answers shows 5).

**Can I get the comments of a whole channel?** Yes - paste the channel link or `@handle` and set "Videos per channel or playlist". The newest videos are used first.

**Why do I get more rows than "Maximum comments"?** That limit counts top-level comments. Replies are extra rows, controlled by "Reply depth" and "Maximum replies per comment".

# Actor input Schema

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

One per row: video, Short or live links, community post links, and channel (URL or @handle) or playlist links. For a channel or playlist, the comments of its newest videos are collected.

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

Top-level comments to collect per video, Short or post. Replies are counted separately (see below).

## `commentsSortBy` (type: `string`):

YouTube's comment order.

## `maxReplyDepth` (type: `integer`):

How many levels of replies to collect: 0 = no replies, 1 = direct replies, up to 6 for replies to replies.

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

Replies to collect under each comment, at every level.

## `commentsNewerThan` (type: `string`):

Only keep comments published after this date (exact date or e.g. '7 days'). Sets the order to Newest first.

## `maxVideos` (type: `integer`):

For channel and playlist links: how many of the newest videos to collect comments from. Video, Short and post links are always used.

## `includeVideoDetails` (type: `boolean`):

Extra charge per video. Adds one row per video, Short or post in its own table: title, description, views, likes, comment count, publish date, duration, tags and channel.

## `includeChannelInfo` (type: `boolean`):

Extra charge per channel. Adds one row for the channel of every video and post in its own table: subscribers, total views, video count, country, join date, description and all social / website links. Each channel is collected and charged once per run.

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

YouTube shows content availability for this country.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://www.youtube.com/shorts/T_SMf9j50uc"
  ],
  "maxComments": 20,
  "commentsSortBy": "top",
  "maxReplyDepth": 1,
  "maxRepliesPerComment": 5,
  "maxVideos": 10,
  "includeVideoDetails": false,
  "includeChannelInfo": false,
  "country": "US"
}
```

# Actor output Schema

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

No description

## `videos` (type: `string`):

No description

## `posts` (type: `string`):

No description

## `channels` (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 = {
    "startUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/shorts/T_SMf9j50uc"
    ],
    "maxComments": 20
};

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

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

```

## MCP server setup

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