# YouTube Comments Scraper without Author Names or IDs (`steadydata/youtube-comments`) Actor

Comments from YouTube videos for sentiment analysis, FAQ mining and research: text, likes, reply count, publication time, pinned and owner flags, top or newest first, optional replies, up to 200 videos per run. No author names, handles or channel IDs, so the dataset carries no personal data.

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

## Pricing

$0.35 / 1,000 comment listeds

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/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 (no author data)

Comments from YouTube videos, **up to 200 videos per run**: the comment text, likes,
reply count, when it was posted, whether it is pinned, hearted or written by the channel
owner, in YouTube's Top order or newest first, optionally with the replies under each
comment. **Deliberately without commenter names, handles, channel ids or avatars.** You
only pay for comments that are actually delivered.

### Why this scraper

- **Comments without people.** Most comment scrapers ship the commenter's name and
  channel id with every row, which turns a dataset of opinions into a dataset of persons.
  This one reads past those fields on purpose. What you get is what sentiment analysis,
  FAQ mining, product research and content planning actually use: the text and its
  signals.
- **Top or newest.** YouTube's own ranking for "what resonated", or newest first for
  "what are people saying right now".
- **Replies, when you want them.** Off by default; on, each reply is delivered with
  `parentCommentId` so threads can be rebuilt.
- **Built on a lightweight route.** About 4.8 KB per comment through YouTube's own
  internal API, no browser. In testing on 13-09-2026, 100 comments per video took about
  three seconds per video.
- **Only delivered comments are charged.** A video with comments off, or one that does
  not exist, comes back as a clear error record at no cost.

### Who this is for

Brand and product teams reading audience reaction at scale. Researchers coding sentiment
or topics across hundreds of videos. Creators and agencies mining questions for FAQ and
content ideas. Anyone feeding comments into an LLM and who does not want personal data in
the prompt.

### Who this is not for

**Read this before you buy.** If you need to know *who* commented, to build an outreach
list or to track individual users, this is the wrong tool and it will not be extended in
that direction. There is also no exact timestamp: YouTube publishes relative times ("2
weeks ago", "1 year ago (edited)") and that is what is delivered.

### Input example

```json
{
    "videos": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "9bZkp7q19f0"],
    "maxCommentsPerVideo": 100,
    "sort": "top",
    "includeReplies": false,
    "maxRepliesPerComment": 20,
    "language": "en"
}
```

Video URLs (watch, youtu.be, shorts, embed) or bare 11-character ids both work.

### Output example

```json
{
    "videoId": "dQw4w9WgXcQ",
    "commentId": "Ugzge340dBgB75hWBm54AaABAg",
    "parentCommentId": null,
    "rank": 1,
    "text": "can confirm: he never gave us up",
    "likeCount": 314000,
    "replyCount": 963,
    "publishedText": "1 year ago",
    "isOwner": false,
    "isPinned": true,
    "hasCreatorHeart": true,
    "isReply": false,
    "commentUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ&lc=Ugzge340dBgB75hWBm54AaABAg",
    "status": "ok"
}
```

A reply looks the same with `isReply: true`, `parentCommentId` set and `rank` empty. A
video that yields nothing produces an error record instead, and is **not** charged:

```json
{
    "input": "aaaaaaaaaaa",
    "status": "error",
    "errorCode": "NO_COMMENTS",
    "error": "Video aaaaaaaaaaa has no comment section (comments off or video unavailable)"
}
```

Error codes: `INVALID_VIDEO_ID`, `NO_COMMENTS`, `BLOCKED`. `INPUT_TRUNCATED` appears once when your input is longer than this actor accepts.

### Related actors from steadydata

- [youtube-video-details](https://apify.com/steadydata/youtube-video-details): the video behind the comments, with views and tags
- [youtube-transcript-bulk](https://apify.com/steadydata/youtube-transcript-bulk): what was said in the video itself
- [youtube-channel-videos](https://apify.com/steadydata/youtube-channel-videos): every video of a channel, to comment-mine a whole channel

### Pricing

Pay per event: one `comment-listed` event per delivered comment, replies included when
you switch them on. No charge for videos that fail, no separate platform-usage surcharge.
`maxCommentsPerVideo` (and `maxRepliesPerComment`) are your hard cost ceiling.

### FAQ

**Why is the like count rounded?**
YouTube shows "314K", not the exact figure, and the number is converted faithfully from
what YouTube shows. Small counts are exact.

**Why is a comment from a year ago first when I asked for newest?**
A pinned comment stays on top in both orders, exactly as on YouTube. `isPinned` tells you
which one it is.

**Do I get the total number of comments on the video?**
No; YouTube's mobile route does not carry it. Use the Video Details actor from the same
publisher for counts.

**Can I get the commenter's name if I really need it?**
No. That is the one thing this actor will not do, and the reason it exists.

**Is personal data collected?**
Comment text is what people wrote in public and may itself mention a name; nothing about
the commenter's identity is collected, and nothing is linked to a person.

**What happens when YouTube changes something?**
Internal routes shift from time to time. The actor is monitored daily and fixed fast, and
while it is broken you are not charged, because only delivered comments cost anything.

# Actor input Schema

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

Video URLs or 11-character video ids, one per row. Each video is one input; a video without comments comes back as a free error record.

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

Cost ceiling: at most this many top-level comments per video, in YouTube's order. One delivered comment is one charged event.

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

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

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

Also fetch the replies under each comment (each reply is a charged comment too, with `parentCommentId` set). Off by default: top-level comments only.

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

Only used when replies are on.

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

Interface language for relative dates such as '2 weeks ago' (hl).

## Actor input object example

```json
{
  "videos": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "maxCommentsPerVideo": 100,
  "sort": "top",
  "includeReplies": false,
  "maxRepliesPerComment": 20,
  "language": "en"
}
```

# Actor output Schema

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

// Run the Actor and wait for it to finish
const run = await client.actor("steadydata/youtube-comments").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=dQw4w9WgXcQ"] }

# Run the Actor and wait for it to finish
run = client.actor("steadydata/youtube-comments").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=dQw4w9WgXcQ"
  ]
}' |
apify call steadydata/youtube-comments --silent --output-dataset

```

## MCP server setup

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

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/4JOO1d4xxVIGUbS8J/builds/NWQBebb6voKS0IN54/openapi.json
