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

\[💰 $0.25 / 1K] Extract comments and reply threads from public YouTube videos and Shorts. Returns comment text, author name and channel, like counts, reply structure, pinned and hearted flags and creator-reply detection. Pay only for the comments you get no compute fees, no subscription.

- **URL**: https://apify.com/solidcode/youtube-comments-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Social media, Videos, Developer tools
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.25 / 1,000 results

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 a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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 complete comment threads from any public YouTube video or Short — top-level comments, reply chains, like counts, author profiles, pinned and hearted flags, and creator replies — in clean structured rows. Built for sentiment analysis, brand monitoring, influencer vetting, and audience research, with no login required and pay-per-result pricing.

### Why This Scraper?

- **Top-level comments and full reply threads** — fetch any depth of conversation, with each reply linked back to its parent comment via `parentCommentId` for easy thread reconstruction.
- **Rich author and engagement signals** — every row carries the author's display name, channel ID, profile URL, avatar, like count, edited flag, pinned flag, hearted-by-creator flag, and an `isCreatorReply` indicator for instantly spotting channel-owner responses.
- **Top or Latest sort** — surface the most-engaged comments first, or switch to newest-first for live event monitoring and shifting sentiment.
- **Built-in reply cap** — `maxRepliesPerComment` keeps a single viral mega-thread from monopolizing your run, so you stay in control of cost and dataset shape.
- **Optional video metadata row** — flip on `includeVideoInfo` to also receive the video's title, channel, view count, upload date, and description per input video — perfect for joining comments back to context in a single dataset.
- **Shorts and watch URLs in one input** — paste any mix of `youtube.com/watch?v=...`, `youtu.be/...`, and `youtube.com/shorts/...` — Shorts URLs are auto-normalized.
- **19 interface languages** — choose the language for the optional video metadata row to match your audience.
- **Pay only for results** — flat rate per 1,000 dataset items, no compute-time charges.

### Use Cases

**Sentiment Analysis**
- Measure positive, negative, and neutral reactions to a product launch, ad campaign, or news event
- Track sentiment shifts over time by re-running on the same video
- Build labeled training sets for downstream sentiment models

**Brand Monitoring**
- Watch comment threads on competitor and partner channels for mentions of your brand
- Detect emerging complaints, support questions, or PR risks early
- Quantify share of voice in conversations under industry-relevant videos

**Market Research**
- Mine the audience reaction to a new feature, price change, or market entrant
- Compare audience demographics and preferences across creators in the same niche
- Surface frequently asked questions, common objections, and unmet needs in your space

**Influencer Vetting**
- Audit engagement quality before sponsoring a creator — look for real conversations, not bot spam
- Spot suspicious comment patterns (repeated phrases, off-topic plugs, low-effort replies)
- Quantify creator-fan interaction by counting `isCreatorReply` rows and `isHearted` engagement

**NLP Training Data**
- Collect large, diverse comment corpora for sentiment, toxicity, intent, or topic classifiers
- Pull multilingual comment data — comment text is user-generated, never machine-translated
- Pair comments with `videoInfo` rows to provide topical context for context-aware models

**Trend Detection**
- Switch to `latest` sort to monitor a live event or fresh upload as reactions roll in
- Catch breakout opinions and viral replies as they emerge under trending videos
- Track reaction velocity by re-running on the same video at fixed intervals

### Getting Started

#### Simple Run

The fastest way to start — paste a video URL and use the defaults (Top sort, 100 comments).

```json
{
    "startUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"]
}
````

#### Multiple Videos with Replies

Pull comments and reply threads from a batch of videos, capped at 50 replies per top-level comment.

```json
{
    "startUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://youtu.be/9bZkp7q19f0",
        "https://www.youtube.com/shorts/s3DrGkDvgNw"
    ],
    "includeReplies": true,
    "maxResults": 500,
    "maxRepliesPerComment": 50
}
```

#### Latest-First Monitoring with Video Context

Watch a fresh upload, get the newest comments first, and join them back to the video's metadata in the same dataset.

```json
{
    "startUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
    "sortBy": "latest",
    "maxResults": 1000,
    "includeVideoInfo": true,
    "language": "en"
}
```

#### Full Run — Every Toggle Set

Top-engagement comments, full reply threads, video context, Spanish video metadata, capped per thread.

```json
{
    "startUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/watch?v=9bZkp7q19f0"
    ],
    "sortBy": "top",
    "includeReplies": true,
    "maxResults": 2000,
    "maxRepliesPerComment": 25,
    "includeVideoInfo": true,
    "language": "es"
}
```

### Input Reference

#### What to Scrape

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `startUrls` | string\[] | `["https://www.youtube.com/watch?v=dQw4w9WgXcQ"]` | Paste one or more YouTube video or Shorts URLs. Accepts `youtube.com/watch?v=...`, `youtu.be/...`, and `youtube.com/shorts/...` — mix any of these in one list. The actor fetches the public comments stream for each video. |

#### Filters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `sortBy` | string | `"top"` | Order comments are returned in. "Top" surfaces the most-liked, most-engaged comments first (matches the default YouTube view). "Latest" returns newest-first — best for sentiment shifts or live-event monitoring. |
| `includeReplies` | boolean | `false` | Also fetch reply threads under each top-level comment. Replies count toward your Maximum Results cap and are charged as separate dataset items. Leave off if you only need top-level engagement. |

#### Results

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxResults` | integer | `100` | Total comments + replies to fetch per video. Set to `0` to fetch as many as YouTube serves. YouTube itself caps the public comments stream on most videos — even on viral videos with millions of comments, only a few thousand are typically reachable through the public continuation tokens. The actor delivers everything reachable up to your limit, and stops requesting new pages once this number is reached (it may return a few extra rows from the final page). |
| `maxRepliesPerComment` | integer | `50` | Cap on replies fetched per top-level comment. Useful for viral videos where a single megathread can have thousands of replies — this prevents one thread from monopolizing the run. Ignored when Include Reply Threads is off. Set to `0` to disable the per-thread cap (replies are still bounded by Maximum Comments per Video). Note: YouTube itself sometimes caps how deep a single reply thread can be walked through the public continuation tokens; the actor delivers everything reachable up to your limit. |

#### Enrichment

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `includeVideoInfo` | boolean | `false` | Emit one extra row per input video with the video's title, channel, view count, upload date, and description. Handy for sentiment analysis when you need to join comments back to the video. Adds 1 dataset item per video. |

#### Localization

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `language` | string | `"en"` | Interface language for video metadata (titles, descriptions). Comment text itself is user-generated and is never translated by YouTube — this setting only affects the optional Video Metadata Row. Supports English, French, German, Spanish, Italian, Portuguese, Dutch, Polish, Turkish, Russian, Japanese, Korean, Chinese (Simplified), Chinese (Traditional), Arabic, Hebrew, Thai, Vietnamese, Indonesian. |

### Output

Every row carries a `recordType` field so you can tell top-level comments, replies, and video metadata rows apart at a glance. Below is one example per type.

#### Comment (top-level)

```json
{
    "recordType": "comment",
    "videoId": "dQw4w9WgXcQ",
    "commentId": "UgxKREWxIgDrw8w2e_Z4AaABAg",
    "parentCommentId": null,
    "text": "Still here in 2026, this never gets old.",
    "author": "Jane Listener",
    "authorChannelId": "UCBJycsmduvYEL83R_U4JriQ",
    "authorProfileUrl": "https://www.youtube.com/channel/UCBJycsmduvYEL83R_U4JriQ",
    "authorThumbnail": "https://yt3.ggpht.com/ytc/jane_listener_avatar.jpg",
    "publishedAt": "2026-04-23T17:46:41+00:00",
    "publishedAtRaw": "2 days ago",
    "isEdited": false,
    "likeCount": 1842,
    "replyCount": 37,
    "isPinned": true,
    "isHearted": true,
    "isCreatorReply": false,
    "sourceInput": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "scrapedAt": "2026-04-25T17:46:41+00:00"
}
```

#### Reply

```json
{
    "recordType": "reply",
    "videoId": "dQw4w9WgXcQ",
    "commentId": "UgxKREWxIgDrw8w2e_Z4AaABAg.2x9aR4Q1bQc",
    "parentCommentId": "UgxKREWxIgDrw8w2e_Z4AaABAg",
    "text": "Same — first time I heard it on the radio in 1987!",
    "author": "Mark T.",
    "authorChannelId": "UCXuqSBlHAE6Xw-yeJA0Tunw",
    "authorProfileUrl": "https://www.youtube.com/channel/UCXuqSBlHAE6Xw-yeJA0Tunw",
    "authorThumbnail": "https://yt3.ggpht.com/ytc/mark_t_avatar.jpg",
    "publishedAt": "2026-04-24T11:12:03+00:00",
    "publishedAtRaw": "1 day ago (edited)",
    "isEdited": true,
    "likeCount": 24,
    "replyCount": null,
    "isPinned": false,
    "isHearted": false,
    "isCreatorReply": false,
    "sourceInput": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "scrapedAt": "2026-04-25T17:46:41+00:00"
}
```

#### Video Info

Emitted only when `includeVideoInfo` is set to `true` — one row per input video.

```json
{
    "recordType": "videoInfo",
    "videoId": "dQw4w9WgXcQ",
    "title": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)",
    "channel": "Rick Astley",
    "channelId": "UCuAXFkgsw1L7xaCfnd5JJOw",
    "viewCount": 1632400000,
    "likeCount": null,
    "publishedAt": "2009-10-25",
    "lengthSeconds": 212,
    "description": "The official 4K remastered video for Rick Astley's 'Never Gonna Give You Up'...",
    "isShort": false,
    "sourceInput": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "scrapedAt": "2026-04-25T17:46:41+00:00"
}
```

#### Fields by Record Type

**Common fields (every row)**

| Field | Type | Description |
|-------|------|-------------|
| `recordType` | string | One of `comment`, `reply`, or `videoInfo`. Use this to filter and route rows downstream. |
| `videoId` | string | The 11-character YouTube video ID this row belongs to. |
| `sourceInput` | string | The original URL the user provided, useful for grouping results in batches. |
| `scrapedAt` | string | ISO 8601 timestamp of when the row was captured. |

**Comment & Reply fields** (`recordType: "comment"` or `"reply"`)

| Field | Type | Description |
|-------|------|-------------|
| `commentId` | string | Stable YouTube comment ID. Reply IDs use the form `<parentId>.<replyId>`. |
| `parentCommentId` | string | null | The top-level comment's ID for replies; `null` for top-level comments. |
| `text` | string | Full comment text (links collapsed back to URLs). |
| `author` | string | Author display name. |
| `authorChannelId` | string | null | Author's YouTube channel ID (`UC...`). |
| `authorProfileUrl` | string | null | Canonical channel URL `https://www.youtube.com/channel/<UC...>`. |
| `authorThumbnail` | string | null | URL to the author's avatar (largest variant available). |
| `publishedAt` | string | null | ISO 8601 best-effort timestamp resolved from the relative label. Populated for English-locale runs; `null` for other languages. |
| `publishedAtRaw` | string | null | The original "2 days ago (edited)" label exactly as YouTube renders it. |
| `isEdited` | boolean | `true` if the comment was edited (parsed from the "(edited)" marker). |
| `likeCount` | integer | Like count (parsed from labels like "1.2K" or "3.4M" into an integer). |
| `replyCount` | integer | null | Number of replies on a top-level comment; `null` on reply rows. |
| `isPinned` | boolean | `true` if the comment is pinned by the channel owner. |
| `isHearted` | boolean | `true` if the comment is hearted by the channel owner. |
| `isCreatorReply` | boolean | `true` if the author is the channel that uploaded the video. |

**Video Info fields** (`recordType: "videoInfo"`)

| Field | Type | Description |
|-------|------|-------------|
| `title` | string | null | Video title in the requested language. |
| `channel` | string | null | Uploader channel display name. |
| `channelId` | string | null | Uploader channel ID (`UC...`). |
| `viewCount` | integer | Total views at fetch time. |
| `likeCount` | integer | null | Always `null` in this version — see Good to Know below. |
| `publishedAt` | string | null | Upload date (ISO 8601 format). |
| `lengthSeconds` | integer | null | Video duration in seconds; `null` for active live streams. |
| `description` | string | null | Video description (full text). |
| `isShort` | boolean | `true` if the input URL was a `youtube.com/shorts/...` URL. |

### Tips for Best Results

- **Set `maxRepliesPerComment` for viral videos.** A single mega-thread on a popular Short can have tens of thousands of replies — leaving the default cap of 50 in place keeps your dataset balanced and your bill predictable.
- **Use `latest` for live-event and fresh-upload monitoring.** Switch the sort to `latest` when you need to track reactions as they happen — perfect for product launches, news events, or just-uploaded videos.
- **Turn on `includeVideoInfo` for sentiment analysis.** The single extra row per video lets you join comments back to the video's title, channel, and view count in one dataset — no second actor call needed.
- **Mix watch URLs, short links, and Shorts URLs freely.** One run can blend `youtube.com/watch?v=...`, `youtu.be/...`, and `youtube.com/shorts/...` — Shorts URLs are auto-normalized to the corresponding watch URL behind the scenes.
- **Use `sourceInput` to batch results downstream.** Every row keeps the original URL you supplied, so you can group results by input video in your pipeline without extra bookkeeping.
- **Set `maxResults: 0` only when you genuinely want everything.** YouTube has an undocumented natural ceiling on the public comments stream; `0` will fetch everything reachable, but viral videos with millions of comments will still cap out at a few thousand rows.

### Pricing

**No compute charges — you only pay per result returned.**

**$0.25 per 1,000 results.**

| Results | Cost |
|---------|------|
| 100 | $0.025 |
| 1,000 | $0.25 |
| 10,000 | $2.50 |

Every row in your dataset counts as one result, regardless of whether it's a comment, a reply, or a video metadata row.

### Integrations

Connect your extracted data to the rest of your stack:

- **API** — Pull results programmatically via the Apify API
- **Webhooks** — Trigger downstream workflows the moment a run completes
- **Google Sheets** — One-click export straight into a spreadsheet
- **Zapier / Make / n8n** — Automate with 1,000+ app connectors
- **Datasets** — Download as JSON, CSV, Excel, XML, or RSS

### Good to Know

- **Comments-disabled videos return zero rows.** When a creator has turned off comments (or the video is private, age-gated, or removed), the actor logs an explanatory line, emits no rows for that video, and finishes the run normally — no traceback, no broken dataset.
- **`publishedAt` ISO dates are populated for English-locale runs.** Non-English runs (Spanish, French, etc.) still return the human-readable `publishedAtRaw` (e.g. `"hace 1 año"`) but leave `publishedAt` as `null`. If you need ISO timestamps for non-English videos, parse `publishedAtRaw` downstream.
- **YouTube caps how many comments are reachable** on some videos. Even with `maxResults: 0`, the public comments stream has an undocumented ceiling — you receive everything reachable, which on viral videos may be a small fraction of the stated comment count. This is a YouTube limitation, not an actor limitation.
- **Shorts URLs are auto-normalized** to their underlying watch URL — `youtube.com/shorts/<id>` and `youtube.com/watch?v=<id>` produce identical comment streams.
- **`likeCount` on the video metadata row is always `null`.** YouTube hides video like counts behind an authenticated endpoint. Comment like counts are unaffected and are returned as integers on every comment and reply row.
- **Replies are charged as separate items.** With `includeReplies: true`, each reply you receive counts as one dataset row. The `maxRepliesPerComment` cap is your main lever for keeping reply costs in check.
- **Comment text is user-generated and never translated by YouTube.** The `language` setting only affects the optional Video Metadata Row (titles, descriptions).

### Legal & Ethical Use

This actor is designed for legitimate sentiment analysis, brand monitoring, market research, influencer vetting, and academic research. You are responsible for complying with YouTube's Terms of Service, applicable laws, and data protection regulations in your jurisdiction. The actor only collects publicly visible data — no login, no private comments, no age-gated or members-only content, and no personal data beyond what YouTube already shows on the public watch page. Do not use extracted data for spam, harassment, impersonation, or any unlawful purpose.

# Actor input Schema

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

Paste one or more YouTube video or Shorts URLs. Accepts youtube.com/watch?v=..., youtu.be/..., and youtube.com/shorts/... — mix any of these in one list. The actor fetches the public comments stream for each video.

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

Order comments are returned in. "Top" surfaces the most-liked, most-engaged comments first (matches the default YouTube view). "Latest" returns newest-first — best for sentiment shifts or live-event monitoring.

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

Also fetch reply threads under each top-level comment. Replies count toward your Maximum Results cap and are charged as separate dataset items. Leave off if you only need top-level engagement.

## `maxResults` (type: `integer`):

Total comments + replies to fetch per video. Set to 0 to fetch as many as YouTube serves. YouTube itself caps the public comments stream on most videos — even on viral videos with millions of comments, only a few thousand are typically reachable through the public continuation tokens. The actor delivers everything reachable up to your limit, and stops requesting new pages once this number is reached (it may return a few extra rows from the final page).

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

Cap on replies fetched per top-level comment. Useful for viral videos where a single megathread can have thousands of replies — this prevents one thread from monopolizing the run. Ignored when Include Reply Threads is off. Set to 0 to disable the per-thread cap (replies are still bounded by Maximum Comments per Video). Note: YouTube itself sometimes caps how deep a single reply thread can be walked through the public continuation tokens; the actor delivers everything reachable up to your limit.

## `includeVideoInfo` (type: `boolean`):

Emit one extra row per input video with the video's title, channel, view count, upload date, and description. Handy for sentiment analysis when you need to join comments back to the video. Adds 1 dataset item per video.

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

Interface language for video metadata (titles, descriptions). Comment text itself is user-generated and is never translated by YouTube — this setting only affects the optional Video Metadata Row.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "sortBy": "top",
  "includeReplies": false,
  "maxResults": 100,
  "maxRepliesPerComment": 50,
  "includeVideoInfo": false,
  "language": "en"
}
```

# Actor output Schema

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

Table of comments and replies with author, text, likes, and reply count.

# 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"
    ],
    "sortBy": "top",
    "includeReplies": false,
    "maxResults": 100,
    "maxRepliesPerComment": 50,
    "includeVideoInfo": false,
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/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"],
    "sortBy": "top",
    "includeReplies": False,
    "maxResults": 100,
    "maxRepliesPerComment": 50,
    "includeVideoInfo": False,
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/youtube-comments-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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"
  ],
  "sortBy": "top",
  "includeReplies": false,
  "maxResults": 100,
  "maxRepliesPerComment": 50,
  "includeVideoInfo": false,
  "language": "en"
}' |
apify call solidcode/youtube-comments-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=solidcode/youtube-comments-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "YouTube Comments Scraper",
        "description": "[💰 $0.25 / 1K] Extract comments and reply threads from public YouTube videos and Shorts. Returns comment text, author name and channel, like counts, reply structure, pinned and hearted flags and creator-reply detection. Pay only for the comments you get no compute fees, no subscription.",
        "version": "1.0",
        "x-build-id": "gknzbeYm2UR2nJmzL"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/solidcode~youtube-comments-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-solidcode-youtube-comments-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/solidcode~youtube-comments-scraper/runs": {
            "post": {
                "operationId": "runs-sync-solidcode-youtube-comments-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/solidcode~youtube-comments-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-solidcode-youtube-comments-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "startUrls": {
                        "title": "YouTube Video URLs",
                        "type": "array",
                        "description": "Paste one or more YouTube video or Shorts URLs. Accepts youtube.com/watch?v=..., youtu.be/..., and youtube.com/shorts/... — mix any of these in one list. The actor fetches the public comments stream for each video.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "sortBy": {
                        "title": "Sort Comments By",
                        "enum": [
                            "top",
                            "latest"
                        ],
                        "type": "string",
                        "description": "Order comments are returned in. \"Top\" surfaces the most-liked, most-engaged comments first (matches the default YouTube view). \"Latest\" returns newest-first — best for sentiment shifts or live-event monitoring.",
                        "default": "top"
                    },
                    "includeReplies": {
                        "title": "Include Reply Threads",
                        "type": "boolean",
                        "description": "Also fetch reply threads under each top-level comment. Replies count toward your Maximum Results cap and are charged as separate dataset items. Leave off if you only need top-level engagement.",
                        "default": false
                    },
                    "maxResults": {
                        "title": "Maximum Comments per Video",
                        "minimum": 0,
                        "maximum": 50000,
                        "type": "integer",
                        "description": "Total comments + replies to fetch per video. Set to 0 to fetch as many as YouTube serves. YouTube itself caps the public comments stream on most videos — even on viral videos with millions of comments, only a few thousand are typically reachable through the public continuation tokens. The actor delivers everything reachable up to your limit, and stops requesting new pages once this number is reached (it may return a few extra rows from the final page).",
                        "default": 100
                    },
                    "maxRepliesPerComment": {
                        "title": "Maximum Replies per Comment",
                        "minimum": 0,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Cap on replies fetched per top-level comment. Useful for viral videos where a single megathread can have thousands of replies — this prevents one thread from monopolizing the run. Ignored when Include Reply Threads is off. Set to 0 to disable the per-thread cap (replies are still bounded by Maximum Comments per Video). Note: YouTube itself sometimes caps how deep a single reply thread can be walked through the public continuation tokens; the actor delivers everything reachable up to your limit.",
                        "default": 50
                    },
                    "includeVideoInfo": {
                        "title": "Include Video Metadata Row",
                        "type": "boolean",
                        "description": "Emit one extra row per input video with the video's title, channel, view count, upload date, and description. Handy for sentiment analysis when you need to join comments back to the video. Adds 1 dataset item per video.",
                        "default": false
                    },
                    "language": {
                        "title": "Language",
                        "enum": [
                            "en",
                            "fr",
                            "de",
                            "es",
                            "it",
                            "pt",
                            "nl",
                            "pl",
                            "tr",
                            "ru",
                            "ja",
                            "ko",
                            "zh-CN",
                            "zh-TW",
                            "ar",
                            "he",
                            "th",
                            "vi",
                            "id"
                        ],
                        "type": "string",
                        "description": "Interface language for video metadata (titles, descriptions). Comment text itself is user-generated and is never translated by YouTube — this setting only affects the optional Video Metadata Row.",
                        "default": "en"
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
