# YouTube Comments Scraper — Comments, Replies & Likes (`tortuga/youtube-comments-scraper`) Actor

Scrape YouTube comments and replies from videos, Shorts, playlists and channels: text, author, likes, reply count, date, pinned and creator-heart flags.

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

## Pricing

from $1.50 / 1,000 comments

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 — Comments, Replies & Likes

Scrape the comments of any YouTube video, Short, playlist or channel: the comment text, the author's handle, channel ID and channel URL, like count, reply count, when it was posted (YouTube's "3 days ago" plus an estimated date), and whether it was edited, pinned, hearted by the creator or written by the video's creator. Replies are optional and come right after their parent comment, each linked to it with `parentCommentId`.

Sort by **Top comments** or **Newest first**, cap each video with **Max comments per video**, or keep only comments from the last few days. Turn on monitoring to get only the new comments on every scheduled run.

No login, no cookies, no YouTube Data API key and no API quota. The Actor reads the same public comment data the YouTube website loads when you scroll down under a video.

### What data does YouTube Comments Scraper extract?

| Field | Description |
|---|---|
| `commentId`, `commentUrl` | Comment ID (replies: `<parentId>.<replyId>`) and a direct link that opens the video at that comment |
| `text` | Full comment text (emoji as characters, line breaks kept) |
| `author`, `authorHandle` | Author as shown on YouTube (the @handle) |
| `authorChannelId`, `authorChannelUrl`, `authorAvatarUrl` | Author's channel ID (`UC…`), channel URL and avatar image |
| `authorIsVerified`, `authorIsArtist`, `authorIsChannelOwner` | Verified badge, Official Artist Channel, and whether the author is the video's creator |
| `authorBadges` | Other badges YouTube shows next to the name (for example "Moderator") |
| `likeCount`, `likeCountText` | Likes as a number and as shown (`"325K"`; YouTube rounds counts above 1,000) |
| `replyCount` | Number of replies under the comment (0 for replies) |
| `publishedTimeText`, `publishedAt` | Posting time as shown (`"2 weeks ago"`) and the date computed from it (estimate: YouTube only shows relative times) |
| `isEdited`, `isPinned`, `isHeartedByCreator`, `heartedBy` | Edited flag, pinned comment, creator heart and who gave it |
| `paidAmount` | Super Thanks amount as shown (for example `"$5.00"`) when the comment carries YouTube's paid-comment chip; `null` otherwise (paid comments are rare) |
| `isReply`, `parentCommentId` | Reply flag and the ID of the comment it answers |
| `position` | Position in the video's comment list for the chosen sort (replies: position in the thread) |
| `videoId`, `videoTitle`, `videoUrl`, `videoChannelName`, `videoChannelId`, `videoCommentCount` | The video the comment belongs to and its total comment count |
| `scrapedAt` | When the comment was scraped (UTC) |
| `changeType` | Only in monitoring mode: `"new"` |

### How to scrape YouTube comments

1. Paste video URLs or IDs, Shorts URLs, playlist URLs or channel URLs into **YouTube URLs or video IDs**, one per line. All usual forms work: `watch?v=`, `youtu.be/`, `/shorts/`, `/live/`, `/embed/`, `/playlist?list=`, `/@handle`, `/channel/UC…`, `/c/…`, `/user/…`.
2. Set **Max comments per video**. Replies count toward it when **Include replies** is on.
3. Pick **Sort comments by**: Top comments (YouTube's default) or Newest first.
4. For channels and playlists, set **Max videos per playlist / channel** (newest videos first for channels). Use **Channel tab** to pick Videos, Shorts or past Live streams.
5. Click **Start**. Comments appear in the **Dataset** tab while the run is going. Download them as JSON, CSV or Excel, or fetch them through the API.

### Input example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://www.youtube.com/shorts/IHkp5Kq72ro",
    "https://www.youtube.com/@veritasium"
  ],
  "maxComments": 500,
  "sortBy": "top",
  "includeReplies": true,
  "maxRepliesPerComment": 20,
  "maxVideosPerSource": 5,
  "maxItems": 5000,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

### Output example

```json
{
  "commentId": "Ugzge340dBgB75hWBm54AaABAg",
  "videoId": "dQw4w9WgXcQ",
  "videoTitle": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)",
  "videoUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "commentUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ&lc=Ugzge340dBgB75hWBm54AaABAg",
  "text": "can confirm: he never gave us up",
  "author": "@YouTube",
  "authorHandle": "@YouTube",
  "authorChannelId": "UCBR8-60-B28hp2BmDPdntcQ",
  "authorChannelUrl": "https://www.youtube.com/@YouTube",
  "authorAvatarUrl": "https://yt3.ggpht.com/3s6evpqAiDU9tQR4sC2siJippbH2RWVPnwHgyl4V0th2iuQz0VDQZbUhQBGmsxLYo-mjG6TqZQ=s88-c-k-c0x00ffffff-no-rj",
  "authorIsVerified": true,
  "authorIsArtist": false,
  "authorIsChannelOwner": false,
  "authorBadges": [],
  "likeCount": 325000,
  "likeCountText": "325K",
  "replyCount": 962,
  "publishedTimeText": "1 year ago",
  "publishedAt": "2025-10-09T12:00:00Z",
  "isEdited": false,
  "isPinned": true,
  "isHeartedByCreator": true,
  "heartedBy": "@RickAstleyYT",
  "paidAmount": null,
  "isReply": false,
  "parentCommentId": null,
  "position": 1,
  "videoChannelName": "Rick Astley",
  "videoChannelId": "UCuAXFkgsw1L7xaCfnd5JJOw",
  "videoCommentCount": 2458616,
  "scrapedAt": "2026-10-09T12:00:00Z"
}
```

### How to scrape YouTube comment replies

Turn on **Include replies**. Each reply is saved as its own row right after its parent comment, with `isReply: true` and `parentCommentId` set to the parent's `commentId`. Use **Max replies per comment** to keep only the first replies of very long threads, in the order YouTube shows them. Replies count toward **Max comments per video** and are charged like comments.

### Can I get only recent comments?

Yes, in two ways. **Only comments newer than** takes a date (`2026-10-01`) or a period (`7 days`, `24 hours`): the Actor reads newest first and stops paging once a whole page is older. YouTube shows relative times only ("2 weeks ago", "1 year ago"), so `publishedAt` and the cut are estimates, accurate to the unit YouTube shows. For a reliable "only what is new since last time", use monitoring (next section), which compares comment IDs instead of dates.

### Monitor changes on a schedule

Turn on **Only new or changed items** to get only new comments on each run. The Actor remembers the comment IDs that earlier runs of the same input returned, reads comments newest first, and stops paging as soon as it reaches a comment an earlier run already saw, so a quiet video costs one small request and nothing is charged for comments you already have. On channels and playlists, the newest videos are checked each run, so comments on new uploads are picked up too. Save the input as a task and add a Schedule in Apify (for example hourly or daily); give each watch its own **Monitoring key** if several schedules use the same videos. Every output item then has `changeType: "new"`. Replies are fetched for new comments only; new replies under older comments are not tracked.

### Does it work without login or an API key?

Yes. No Google account, no cookies and no YouTube Data API key (so no 10,000-units-per-day quota). Videos with comments turned off (for example videos made for kids), private videos and removed videos are skipped and not charged; the run summary (key-value store, `SUMMARY`) counts them. Members-only and age-restricted videos are not supported because their comments need a login.

### How many comments can I scrape?

As many as YouTube lists under the video. With **Newest first** the Actor pages through the whole list: in our test it read 6,000 comments of one video in one run, with no failed request. YouTube's **Top comments** list is shorter: on big videos it ends after roughly 1,000-1,250 comments. When that happens and you asked for more, the Actor continues with the newest-first list and skips comments it already saved, so **Max comments per video** still holds. Comments load 20 per request (about 1.5 seconds each), so 6,000 comments of one video take about 7-8 minutes; several videos run in parallel. Popular videos have millions of comments, so always set **Max comments per video** and **Max results (total)**: you pay per saved comment.

### Proxy note

Apify Proxy with the default datacenter IPs works for YouTube comments, and it is the cheapest option. Each comment page is trimmed to about 6-10 KB on the wire. In our runs, platform usage (compute and dataset storage) was about $0.008 per 1,000 comments. If a run reports rate limits (`SUMMARY.notes.retryReasons`), switch the proxy to RESIDENTIAL. Platform usage is billed to your Apify account in addition to the per-comment price.

### Pricing

Pay per result: **$0.0015 per comment or reply saved** ($1.50 per 1,000), plus the small platform usage. Skipped videos and failed requests are not charged. Use **Max comments per video** and **Max results (total)** to cap the cost of a run. There is no subscription, and Apify's free plan is enough to try it.

### Integrations and API

Use it from Zapier, Make, n8n or Google Sheets, or call it from Python/Node with the Apify client (see the **API** tab). AI agents can call it through Apify's MCP server. Typical uses: sentiment analysis and audience research, finding questions and complaints under product videos, giveaway winner picking, community moderation, and tracking reactions to new uploads on a schedule.

### Is it legal to scrape YouTube comments?

The Actor only reads what YouTube shows publicly to any visitor under a video: comment text, the public @handle and channel link of the author, and public counts. It does not log in and does not open members-only or age-restricted content. Comments are personal opinions of real people: if you store or publish them, follow YouTube's terms and the data protection law that applies to you (for example GDPR), and use the data for a legitimate purpose. You are responsible for how you use the data.

### Support

Found a video that fails, or need another field? Open an issue in the **Issues** tab with the video URL. Issues are usually answered within a day.

# Actor input Schema

## `urls` (type: `array`):

One per line. Video URLs (`watch?v=`, `youtu.be/`, `/shorts/`, `/live/`, `/embed/`) or 11-character video IDs, playlist URLs (`/playlist?list=...`), and channel URLs (`/@handle`, `/channel/UC...`, `/c/name`, `/user/name`, optionally ending in `/videos`, `/shorts` or `/streams`). Playlists and channels are expanded to their latest videos.

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

Stop each video after this many saved items (comments plus their replies). Large videos have millions of comments, so this keeps runs and cost predictable.

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

Top comments (YouTube's default ranking) or newest first. YouTube's Top list ends after about 1,000-1,250 comments on big videos; if you ask for more, the Actor continues with newest first and skips duplicates. Monitoring mode and the date filter always use newest first.

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

Also save the replies under each comment (each reply is one result, with `parentCommentId`). Replies count toward Max comments per video.

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

With Include replies on: save at most this many replies per comment. Leave empty for all replies (still capped by Max comments per video).

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

Only comments newer than: a date (YYYY-MM-DD) or a period such as '7 days' or '24 hours'. Uses newest-first order and stops paging once a whole page is older. YouTube shows relative dates ('3 weeks ago'), so the cut is approximate.

## `maxVideosPerSource` (type: `integer`):

For each playlist or channel URL, take this many videos (playlist order, or newest first for channels). Video URLs are always processed.

## `channelTab` (type: `string`):

Which list a channel URL is expanded from, unless the URL itself ends in `/videos`, `/shorts` or `/streams`.

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

Stop the whole run after this many comments and replies are saved. Each saved comment or reply is one charged result, so this caps the cost.

## `onlyNewOrChanged` (type: `boolean`):

Remember which comments earlier runs of this input returned and output only new comments (newest first). Use with a Schedule; paging stops as soon as it reaches comments an earlier run already saw, and those are not charged.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same videos stay separate; defaults to a key derived from the input

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

Apify Proxy (datacenter) works for YouTube comments and is the cheapest option. Switch to RESIDENTIAL only if runs report rate limits. Comment pages are trimmed to about 10 KB each on the wire.

## Actor input object example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://www.youtube.com/shorts/IHkp5Kq72ro"
  ],
  "maxComments": 100,
  "sortBy": "top",
  "includeReplies": false,
  "maxVideosPerSource": 10,
  "channelTab": "videos",
  "maxItems": 1000,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "urls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/shorts/IHkp5Kq72ro"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

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