# All-in-One YouTube Scraper (`thenetaji/youtube-scraper`) Actor

Collects YouTube search results, channels, videos, comments, transcripts, playlists, trending and hashtag feeds through a single Actor. The mode is selected per run; each mode accepts its own identifier and returns that dataset's fields.

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

## Pricing

from $0.45 / 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.
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

## All-in-One YouTube Scraper

The Actor collects eleven YouTube datasets — search, hashtag and trending feeds, the home and hype feeds, search suggestions, channels, videos, comments, playlists, and transcripts — through a single run configuration. The dataset is chosen with **View**; each mode reads its own identifier and returns that dataset's fields.

Media downloads are deliberately absent. They are billed per file rather than per row and are published as separate Actors, listed at the end.

### Modes

| View | Identifier | Returns |
| --- | --- | --- |
| Search | `search_term` | Videos, channels or playlists matching a term, filtered by length, upload date and sort order |
| Hashtag | `hashtag` | Videos carrying a hashtag |
| Trending | `trend_category` | The trending feed for a category |
| Hype | — | The hype feed |
| Home | — | The home feed |
| Suggestions | `search_term` | The autocomplete terms YouTube offers for a prefix |
| Channel | `channel_sources` | Channel metadata and the sections named in `channel_sections` |
| Video | `video_sources` | Video metadata, with optional related content, transcript and captions |
| Comments | `comment_sources` | A video's comments, with optional parent-comment detail |
| Playlist | `playlist_sources` | A playlist's items, with optional per-video detail |
| Transcript | `video_sources` | A video's transcript, with optional subtitle file |

**View** is the only required input. A mode that cannot find the identifier it needs raises a clear error, so a misconfigured run fails at the start rather than returning an unexpected dataset.

`region_code` and `language_code` apply to every mode and change what YouTube serves: trending and home differ substantially by region, and titles and descriptions are returned in the requested language where YouTube has them.

### Enrichment

Optional per-mode add-ons attach related records to rows that would otherwise carry only an identifier. Each costs one extra request per enriched row and is charged only when the enrichment succeeds.

| Add-on | Mode | Attaches |
| --- | --- | --- |
| `includeRelatedContent` | Video | Related videos, bounded by `maxRelatedItems` |
| `includeTranscript` | Video | The transcript |
| `includeCaption` | Video | Caption text in `caption_language` |
| `includeSoundShorts` | Video | Shorts using the video's sound |
| `includeParentDetails` | Comments | The parent comment of each reply |
| `includeVideoDetails` | Playlist | Full video detail for each playlist item |
| `includeSubtitleFile` | Transcript | A subtitle file in `caption_format` |

### Limits and resumption

`maxItems` caps the rows saved by the paginating modes. Setting it to `0` continues until YouTube stops returning new records.

`resume_cursor` restarts a run from where a previous one stopped. YouTube's continuation tokens expire, so a cursor from an old run may yield nothing; starting fresh is the correct response rather than treating it as a fault.

### Behaviour worth knowing

Transcripts exist only where captions have been published or auto-generated, and auto-generated captions are unavailable for some languages and for videos with restricted embedding. A transcript mode returning no rows usually means the video has no caption track, not that the request failed.

Comment counts reported on a video rarely match the number of comments retrievable. YouTube withholds held-for-review and spam-filtered comments from the public thread while still counting them.

Channel sections vary by channel. A section named in `channel_sections` that the channel does not publish is skipped rather than erroring, so a run can legitimately return fewer sections than were requested.

### Focused alternatives

| Actor | Use instead when |
| --- | --- |
| [YouTube Search Scraper](https://apify.com/thenetaji/youtube-search-scraper) | Only search, hashtag or trending feeds are needed |
| [YouTube Channel Scraper](https://apify.com/thenetaji/youtube-channel-scraper) | Only channel data is needed |
| [YouTube Video Scraper](https://apify.com/thenetaji/youtube-video-scraper) | Only video metadata is needed |
| [YouTube Comments Scraper](https://apify.com/thenetaji/youtube-comments-scraper) | Only comments are needed |
| [YouTube Transcript Scraper](https://apify.com/thenetaji/youtube-transcript-scraper) | Only transcripts are needed |
| [YouTube Playlist Scraper](https://apify.com/thenetaji/youtube-playlist-scraper) | Only playlists are needed |
| [YouTube Video Downloader](https://apify.com/thenetaji/youtube-video-downloader) | Video files are needed |
| [YouTube Music Downloader](https://apify.com/thenetaji/youtube-music-downloader) | Audio files are needed |

# Actor input Schema

## `scraperType` (type: `string`):

Choose the dataset for this run, then fill in the section for that mode below.

## `search_term` (type: `string`):

Used by Keyword search and Search suggestions. Words or a phrase to search for; Search suggestions also accepts partial text. Ignored by the other workflows.

## `result_kind` (type: `string`):

Keyword search only. Limit results to one public content type.

## `length_filter` (type: `string`):

Keyword search only. Keep videos within one duration range.

## `published_within` (type: `string`):

Keyword search only. Restrict results by upload period.

## `sort_order` (type: `string`):

Order the returned results. The available values depend on the workflow.

## `hashtag` (type: `string`):

Used by the Hashtag workflow only. Hashtag text without the # symbol.

## `content_kind` (type: `string`):

Hashtag workflow only. Choose the hashtag's video feed or its Shorts feed.

## `trend_category` (type: `string`):

Trending workflow only. Choose which regional chart to collect.

## `channel_sources` (type: `array`):

One or more public YouTube channels. Full URLs, @handles, usernames, and UC channel IDs are accepted.

## `channel_sections` (type: `array`):

Choose the channel sections to collect. Channel details produces one profile record per channel.

## `channel_search_term` (type: `string`):

Words or a phrase to find when Search within channel is selected.

## `video_sources` (type: `array`):

One or more public YouTube video or Shorts URLs. Bare video IDs are also accepted.

## `video_kind` (type: `string`):

Choose automatic detection, regular videos, or Shorts.

## `includeRelatedContent` (type: `boolean`):

Attach related videos and playlists to every eligible result. One request per page of related items, charged only when it succeeds.

## `maxRelatedItems` (type: `integer`):

Maximum related or same-sound items attached to each video. Set 0 to collect all available pages.

## `includeTranscript` (type: `boolean`):

Attach timed transcript segments when a transcript is available. One extra request per video, charged only when a transcript is returned.

## `includeCaption` (type: `boolean`):

Attach one caption track in the selected language when available. Two extra requests per video, charged only when the track is returned.

## `includeSoundShorts` (type: `boolean`):

For Shorts inputs, attach other Shorts attributed to the same sound. One request per page, charged only when it succeeds.

## `comment_sources` (type: `array`):

One or more public YouTube videos, Shorts, or community posts whose comments should be collected.

## `owner_channel` (type: `string`):

Optional channel ID that owns a community post. Use it when providing a bare post ID.

## `includeParentDetails` (type: `boolean`):

Attach video, Shorts, or community-post details to comments from the same target. One extra request per target, charged only when it succeeds.

## `playlist_sources` (type: `array`):

One or more public YouTube playlist URLs or playlist IDs.

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

Attach a separate full video-detail record to every eligible playlist item. One extra request per item, charged only when it succeeds.

## `transcript_language` (type: `string`):

Language code of the transcript to request, such as en, de, or ja. YouTube serves whichever track it has; the language actually returned is reported on every row. Leave empty for the video's default.

## `includeSubtitleFile` (type: `boolean`):

Attach the caption track as a ready-to-use WebVTT or SRT file, alongside the transcript. Two extra requests per video, charged only when the track is returned.

## `caption_format` (type: `string`):

File format for the attached subtitle track.

## `caption_language` (type: `string`):

Language code of the caption track to attach, such as en, es, or pt-BR.

## `region_code` (type: `string`):

Optional two-letter country code used to localize results, such as US, IN, or DE.

## `language_code` (type: `string`):

Optional language code used to localize result text, such as en, es, or pt-BR.

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

Maximum number of primary records to save across all targets. Set 0 to continue until no more pages remain.

## `resume_cursor` (type: `string`):

Continue a previous run instead of starting again. Paste the resume token printed near the end of that run's log. Leave empty to start from the first page.

## Actor input object example

```json
{
  "scraperType": "search",
  "search_term": "indoor herb garden",
  "hashtag": "urbanphotography",
  "content_kind": "all",
  "trend_category": "now",
  "channel_sources": [
    {
      "url": "https://www.youtube.com/@TED"
    }
  ],
  "channel_sections": [
    "about",
    "videos"
  ],
  "channel_search_term": "behind the scenes",
  "video_sources": [
    {
      "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    }
  ],
  "video_kind": "auto",
  "includeRelatedContent": false,
  "maxRelatedItems": 10,
  "includeTranscript": false,
  "includeCaption": false,
  "includeSoundShorts": false,
  "comment_sources": [
    {
      "url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ"
    }
  ],
  "owner_channel": "UCAuUUnT6oDeKwE6v1NGQxug",
  "includeParentDetails": false,
  "playlist_sources": [
    {
      "url": "https://www.youtube.com/playlist?list=PLMC9KNkIncKtPzgY-5rmhvj7fax8fdxoj"
    }
  ],
  "includeVideoDetails": false,
  "transcript_language": "en",
  "includeSubtitleFile": false,
  "caption_format": "vtt",
  "caption_language": "en",
  "region_code": "US",
  "language_code": "en",
  "maxItems": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

All records scraped by this run

# 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 = {
    "scraperType": "search",
    "search_term": "indoor herb garden",
    "hashtag": "urbanphotography",
    "channel_sources": [
        {
            "url": "https://www.youtube.com/@TED"
        }
    ],
    "video_sources": [
        {
            "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
        }
    ],
    "maxRelatedItems": 10,
    "comment_sources": [
        {
            "url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ"
        }
    ],
    "playlist_sources": [
        {
            "url": "https://www.youtube.com/playlist?list=PLMC9KNkIncKtPzgY-5rmhvj7fax8fdxoj"
        }
    ],
    "region_code": "US",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("thenetaji/youtube-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 = {
    "scraperType": "search",
    "search_term": "indoor herb garden",
    "hashtag": "urbanphotography",
    "channel_sources": [{ "url": "https://www.youtube.com/@TED" }],
    "video_sources": [{ "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ" }],
    "maxRelatedItems": 10,
    "comment_sources": [{ "url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ" }],
    "playlist_sources": [{ "url": "https://www.youtube.com/playlist?list=PLMC9KNkIncKtPzgY-5rmhvj7fax8fdxoj" }],
    "region_code": "US",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("thenetaji/youtube-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 '{
  "scraperType": "search",
  "search_term": "indoor herb garden",
  "hashtag": "urbanphotography",
  "channel_sources": [
    {
      "url": "https://www.youtube.com/@TED"
    }
  ],
  "video_sources": [
    {
      "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    }
  ],
  "maxRelatedItems": 10,
  "comment_sources": [
    {
      "url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ"
    }
  ],
  "playlist_sources": [
    {
      "url": "https://www.youtube.com/playlist?list=PLMC9KNkIncKtPzgY-5rmhvj7fax8fdxoj"
    }
  ],
  "region_code": "US",
  "maxItems": 20
}' |
apify call thenetaji/youtube-scraper --silent --output-dataset

```

## MCP server setup

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