# ▶️ YouTube Scraper (`citrine_venus/youtube-scraper`) Actor

Scrape YouTube videos, Shorts, channels, playlists, comments, and search results, no API key or quota limit. Extract subtitles, transcripts, channel emails, and a computed virality score for creator research and content analysis.

- **URL**: https://apify.com/citrine\_venus/youtube-scraper.md
- **Developed by:** [Data Minds](https://apify.com/citrine_venus) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

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?

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 Scraper — Videos, Channels, Comments, Transcripts & Search, No API Key

Scrape YouTube videos, Shorts, live streams, channels, playlists, hashtag pages and search results into structured data — comments, subtitles/transcripts, channel emails and a built-in virality score included, no YouTube Data API key or quota required.

🔗 **[View this Actor on Apify Store](https://apify.com/citrine_venus/youtube-scraper)**

***

### 📑 Table of Contents

- [What is YouTube Scraper?](#-what-is-youtube-scraper)
- [What data can you extract from YouTube?](#-what-data-can-you-extract-from-youtube)
- [How it works](#-how-it-works)
- [Input parameters reference](#-input-parameters-reference)
- [Output example](#-output-example)
- [Related Actors](#-related-actors)
- [FAQ](#-faq)
- [Support](#-support)

***

### 🎥 What is YouTube Scraper?

**YouTube Scraper** is an [Apify Actor](https://docs.apify.com/platform/actors) that turns any YouTube link — or a plain search term — into clean, structured data: video and channel metadata, **comments**, **subtitles/transcripts**, **channel emails**, and a computed **outlier/virality score** and **engagement rate**. It talks directly to YouTube's own **InnerTube API** and the embedded `ytInitialData`/`ytInitialPlayerResponse` JSON that every YouTube page ships with — the same private endpoints the youtube.com front end itself calls. That means **no Google Cloud project, no API key, and no daily quota** to manage. As a practical **YouTube API alternative**, it suits anyone who has hit the official API's quota ceiling, or who simply never wants to set one up.

Running it as an Apify Actor also gets you the platform's usual conveniences for free: **scheduling** for recurring monitoring runs, a full **run API** for programmatic triggering and result pulling, **automatic proxy rotation** across datacenter and residential pools, live log streaming, and one-click export to JSON, CSV, Excel, or a **pandas dataframe** for anyone doing YouTube data analysis in Python.

***

### 📦 What data can you extract from YouTube?

In plain terms, this **youtube scraper** can pull:

- 🎬 **Video & Shorts details** — title, description, duration, category, thumbnail, keywords, view count, like count, upload date, live/upcoming flags.
- 👤 **Channel information** — name, ID, handle, subscriber and total-view counts, join date, country, description, resolved external links, and any **email address published in the About panel** (handy for creator/lead-gen outreach).
- 💬 **Comments** — top-level comments and reply counts, with author name, channel ID, verified/owner flags and like counts — a full **YouTube comment scraper** without touching the official comments API.
- 📝 **Subtitles and transcripts** — the caption track for a video in **SRT, VTT, plain text or raw JSON3**, in any available language, manual or auto-generated — a bulk **YouTube transcript scraper** and **subtitle/caption scraper** in one.
- 📈 **Outlier / virality score and engagement rate** — how a video's views compare to that channel's own recent median, plus `(likes + comments) / views` — a ready-made **YouTube outlier finder** and virality-score tool computed for free from data already fetched.
- 🔎 **Search results** — run any keyword through YouTube search and get back videos, channels and playlists exactly as YouTube would rank them, with the same sort/date/type/length/feature filters the youtube.com search UI exposes.

***

### 🔧 How it works

1. **Paste your inputs.** Drop any mix of YouTube links into `urls` — a single **video**, a **Shorts** link, a **live stream**, a **channel** (`@handle`, `/channel/UC…`, `/c/…` or legacy `/user/…`), a **playlist**, a **hashtag page**, or a full YouTube **search-results URL**. No URL at all? Type plain search terms into `searchQueries` instead — each one is searched exactly as if you'd typed it into the YouTube search box.
2. **Auto-classification.** Every entry in `urls` is parsed and routed automatically — the Actor detects whether it's a video, channel, playlist, hashtag or search page and follows the correct internal flow, so you never have to sort inputs by type yourself or run six separate actors.
3. **Self-healing network ladder.** Requests start on a **direct connection**. If YouTube pushes back (403/429, a bot-check page, or a block marker in the HTML), the run escalates automatically: direct → **datacenter proxy** → **residential proxy** → and, as a last resort, a **real headless browser session** (`browserFallback`). Once it escalates it stays on the working tier for the rest of the run instead of retrying a route that's already blocked.
4. **Collection.** For every video found, the Actor reads the embedded player response and InnerTube `next` payload for the core metadata, then optionally fetches comments and the subtitle track, and — for channel sources — the About panel for channel-level details and emails.
5. **Insights computed for free.** With `computeOutlierScore` on, each video's view count is compared against the channel's own recent upload median (already collected while listing that channel's videos — no extra request) to produce an outlier ratio/label plus an engagement-rate percentage.
6. **Streamed output.** Every finished record is pushed to the Apify **Dataset** immediately — you can watch results land in real time and export to JSON, CSV, Excel, or XML, or pull them via the Apify API into a **pandas dataframe** for Python analysis.
7. **Monitor mode.** Turn on `monitorMode` for scheduled/recurring runs and the Actor remembers every video ID it has already reported (per Apify account), so a daily or weekly schedule only ever charges you for genuinely new uploads.

***

### 📋 Input parameters reference

#### 🚀 Start here

| Field | Type | Default | Description |
|---|---|---|---|
| `urls` | array | `[]` | Video, Shorts, live-stream, channel, playlist, hashtag or search-results links — one per line, bulk/file input supported. |
| `searchQueries` | array | `[]` | Plain search terms run on YouTube search, one per line — same as typing into the search box. |
| `maxResults` | integer | `10` | Max regular videos to collect per search term, channel or playlist. |
| `maxResultsShorts` | integer | `0` | Max Shorts to collect per search term or channel. `0` = don't collect Shorts. |
| `maxResultStreams` | integer | `0` | Max live/upcoming streams to collect per search term or channel. `0` = don't collect streams. |

#### 🔍 Search filters

*Applies to search queries and search-result URLs. Combine freely — leave blank to skip a filter.*

| Field | Type | Default | Description |
|---|---|---|---|
| `sortingOrder` | string | `""` | How results are ordered: `""` (relevance), `relevance`, `rating`, `date`, `views`. |
| `dateFilter` | string | `""` | Upload-date window: `""` (any), `hour`, `today`, `week`, `month`, `year`. |
| `videoType` | string | `""` | Restrict content type: `""` (any), `video`, `movie`. |
| `lengthFilter` | string | `""` | Video length: `""` (any), `under4`, `between420`, `plus20`. |
| `isHD` | boolean | `false` | Only HD videos. |
| `hasSubtitles` | boolean | `false` | Only videos with subtitles/CC available. |
| `hasCC` | boolean | `false` | Only Creative Commons–licensed videos. |
| `is3D` | boolean | `false` | Only 3D videos. |
| `isLive` | boolean | `false` | Only videos currently live. |
| `isBought` | boolean | `false` | Only purchased content (account-dependent). |
| `is4K` | boolean | `false` | Only 4K videos. |
| `is360` | boolean | `false` | Only 360° videos. |
| `isHDR` | boolean | `false` | Only HDR videos. |
| `hasLocation` | boolean | `false` | Only videos tagged with a location. |
| `isVR180` | boolean | `false` | Only VR180 videos. |
| `sortVideosBy` | string | `NEWEST` | For channel URLs — order to read the Videos/Shorts/Live tab: `NEWEST`, `POPULAR`, `OLDEST`. |

#### 💬 Comments & subtitles

*Both are opt-in — they add extra requests per video.*

| Field | Type | Default | Description |
|---|---|---|---|
| `extractComments` | boolean | `false` | Collect top comments for every video (author, text, likes, replies). |
| `maxComments` | integer | `20` | Stop collecting comments for a video after this many. |
| `downloadSubtitles` | boolean | `false` | Collect the subtitle/caption track for every video, when available. |
| `subtitlesLanguage` | string | `en` | Language code to prefer (e.g. `en`, `es`, `hi`). Use `any` to accept whatever is available. |
| `subtitlesFormat` | string | `srt` | Output format: `srt`, `vtt`, `plaintext`, `json3`. |
| `preferAutoGeneratedSubtitles` | boolean | `false` | Prefer YouTube's auto-generated captions over manually-uploaded ones when both exist. |

#### 📊 Insights

*Extra analytics computed for free from data already collected.*

| Field | Type | Default | Description |
|---|---|---|---|
| `computeOutlierScore` | boolean | `true` | Score each video against the channel's own recent median views (virality), and compute `(likes + comments) / views` as an engagement rate. |
| `extractChannelDetails` | boolean | `true` | For channel URLs — also read the About panel: description, country, join date, total views/videos, external links and emails found in the description. |

#### 🔁 Monitor mode

*For scheduled/recurring runs — only pay for what's new since last time.*

| Field | Type | Default | Description |
|---|---|---|---|
| `monitorMode` | boolean | `false` | Remembers every video ID collected by a previous run of this Actor (same account) and skips it next time. |

#### 🌍 Network & ⚡ Speed & limits

*Leave alone unless you need a specific country route — the run manages itself.*

| Field | Type | Default | Description |
|---|---|---|---|
| `proxyConfiguration` | object | `{"useApifyProxy": false}` | By default the run starts direct and automatically escalates to datacenter then residential proxy only if YouTube pushes back. Set your own route here to override. |
| `browserFallback` | boolean | `true` | As a last resort, retry stubborn requests inside a real browser session. |
| `maxConcurrency` | integer | `5` | How many URLs/search queries to process at the same time (1–20). |
| `maxRequestRetries` | integer | `3` | Attempts before a request is considered failed on the current network route (1–10). |
| `maxScanned` | integer | `20000` | Safety cap on how many search-result rows are examined per query before giving up. |

***

### 📤 Output example

Every finished record streams to your Apify **Dataset** immediately. Here's a "kitchen sink" example with the optional Insights, comments and subtitles fields turned on, from a channel-sourced video — so channel-About fields are present too:

```json
{
  "id": "EufrVkKKCwE",
  "url": "https://www.youtube.com/watch?v=EufrVkKKCwE",
  "type": "video",
  "title": "FC BARCELONA 2 vs 0 ATHLETIC CLUB | LALIGA 2026/27 MD01",
  "description": "A win on the first night back at the Spotify Camp Nou…",
  "duration": 194,
  "channelName": "FC Barcelona",
  "channelId": "UC14UlmYlSNiQCBe9Eookf_A",
  "channelUrl": "https://www.youtube.com/@FCBarcelona",
  "date": "2026-08-27T14:25:29-07:00",
  "viewCount": 2618393,
  "likes": 42437,
  "commentsCount": 1200,
  "commentsTurnedOff": false,
  "category": "Sports",
  "thumbnailUrl": "https://i.ytimg.com/vi/EufrVkKKCwE/maxresdefault.jpg",
  "isLiveContent": false,
  "isUpcoming": false,
  "keywords": ["FC Barcelona", "La Liga", "football"],
  "engagementRate": 1.6666,
  "outlierScore": {
    "ratio": 2.1,
    "channelMedianViews": 1247000,
    "label": "above_average"
  },
  "comments": [
    {
      "commentId": "UgzAbC123",
      "videoId": "EufrVkKKCwE",
      "text": "What a performance from the midfield!",
      "publishedTimeText": "2 hours ago",
      "authorName": "@barca_fan",
      "authorChannelId": "UCxxxxxxxxxxxxxxxxxxxx",
      "authorIsChannelOwner": false,
      "authorIsVerified": false,
      "likesCountText": "312",
      "replyCount": 4,
      "replyLevel": 0
    }
  ],
  "subtitles": {
    "available": true,
    "language": "en",
    "kind": "asr",
    "format": "srt",
    "content": "1\n00:00:00,000 --> 00:00:03,200\nWelcome back to Camp Nou...\n"
  },
  "channelDescription": "Official channel of FC Barcelona. For business inquiries: press@fcbarcelona.com",
  "channelLocation": "Spain",
  "channelJoinedDate": "Feb 27, 2006",
  "channelTotalViews": 4821003912,
  "numberOfSubscribers": 15800000,
  "channelTotalVideos": 12904,
  "channelDescriptionLinks": [
    { "title": "Website", "displayText": "fcbarcelona.com", "url": "https://www.fcbarcelona.com" }
  ],
  "channelEmails": ["press@fcbarcelona.com"]
}
```

Playlist- and hashtag-sourced records use a lighter shape (`fromPlaylist`/`playlistTitle` or `fromHashtag` in place of the full channel-About fields) before comments/subtitles/insights are layered on for the underlying video.

#### 💬 Comment object shape

| Field | Description |
|---|---|
| `commentId` | Unique comment ID |
| `videoId` | Video the comment belongs to |
| `text` | Comment body |
| `publishedTimeText` | Relative published time, e.g. `"2 hours ago"` |
| `authorName` | Commenter's display name |
| `authorChannelId` | Commenter's channel ID |
| `authorIsChannelOwner` | `true` if posted by the video's own channel |
| `authorIsVerified` | `true` if the commenter's channel is verified |
| `likesCountText` | Like count as shown on the page |
| `replyCount` | Number of replies |
| `replyLevel` | `0` for top-level comments |

#### 📝 Subtitles object shape

| Field | Description |
|---|---|
| `available` | `true`/`false` — whether a usable track was found |
| `language` | Language code of the returned track |
| `kind` | `"asr"` for auto-generated, absent/other for manually uploaded |
| `format` | `srt` / `vtt` / `plaintext` / `json3`, matching `subtitlesFormat` |
| `content` | The caption text in the requested format |
| `reason` | Present only when `available` is `false` (e.g. `"no_caption_tracks"`, `"temporarily_unavailable"`) |

#### ❌ Error-row shape

A URL that can't be processed is logged as its own dataset row instead of stopping the run:

| Field | Description |
|---|---|
| `url` | The original input URL (when applicable) |
| `input` | The parsed value the Actor tried to resolve |
| `error` | One of the error codes below |
| `note` | Plain-language explanation |

**ERROR\_CODES:**

| Code | Meaning |
|---|---|
| `CHANNEL_DOES_NOT_EXIST` | Channel does not exist |
| `VIDEO_UNAVAILABLE` | Video is not available (deleted, region-blocked, etc.) |
| `NOT_FOUND` | Page was not found |
| `CHANNEL_HAS_NO_VIDEOS` | Channel exists but has no uploaded videos |
| `CHANNEL_HAS_NO_LIVE_VIDEOS` | Channel exists but has no live videos |
| `CHANNEL_HAS_NO_SHORTS` | Channel exists but has no Shorts |
| `NO_RESULTS` | No results collected for this input |
| `NO_VALID_START_URLS` | All provided start URLs were invalid or malformed |
| `INVALID_INPUT` | Actor failed due to bad configuration |

***

### 🔗 Related Actors

This Actor already extracts subtitles and transcripts as part of a full video/channel/comment/metadata record — so if you're pulling complete video and channel intelligence (views, likes, comments, channel emails, outlier score) and just want transcripts along for the ride, you're already covered here.

If your use case is **transcripts and nothing else, at high volume** — for example feeding a large batch of video IDs straight into an LLM pipeline without paying for comment/channel/insight collection you won't use — try **[YouTube Transcript Scraper](https://apify.com/citrine_venus/youtube-transcript-scraper)**, a leaner Actor purpose-built for bulk transcript/subtitle extraction.

**In short:** need just transcripts, fast and at scale — use [YouTube Transcript Scraper](https://apify.com/citrine_venus/youtube-transcript-scraper). Need full video, channel, comment, email and virality data (transcripts included) in one run — use this Actor.

***

### ❓ FAQ

#### 📜 Is it legal to scrape YouTube?

This Actor only reads **publicly available** YouTube pages — the same pages any anonymous visitor's browser can load. It doesn't bypass logins, paywalls or private content. You're responsible for how you use the collected data — respect YouTube's Terms of Service, applicable copyright law, and privacy regulations (GDPR, CCPA, etc.) for your jurisdiction and use case.

#### 🆚 How is this different from the official YouTube Data API?

The official **YouTube Data API** requires a Google Cloud project and API key, and bills every call against a **daily quota** that's easy to exhaust on anything beyond light use — comments, search and channel-list calls are especially quota-hungry. This Actor talks to YouTube's own **InnerTube API** and embedded page JSON instead, the same internal endpoints youtube.com's own front end uses. There's no key to provision and no daily quota to watch, which makes it a straightforward **YouTube API quota workaround** for teams that have hit `quotaExceeded` errors or simply don't want to manage Cloud Console credentials. It's a genuine **YouTube data API alternative**, not a wrapper around the official one.

#### 💰 How much does it cost to scrape YouTube data with this Actor?

This Actor uses Apify's **pay-per-event** pricing: you're billed one `video_result` event for every finished video/Short/stream record actually saved to your dataset, and error rows are never charged. Check the Actor's **Pricing** tab on Apify Store for the current rate per 1,000 events, and start with a low `maxResults` to gauge cost before committing to a full harvest.

#### 🔎 Can I scrape YouTube search results by keyword?

Yes — type plain terms into `searchQueries` (each is searched exactly as on youtube.com) or paste a `/results?search_query=…` URL into `urls`. Combine with `sortingOrder`, `dateFilter`, `videoType`, `lengthFilter` and the feature checkboxes to narrow results the same way the YouTube search filters do.

#### 👤 Can I get YouTube channel data without logging in?

Yes — paste a channel URL (`@handle`, `/channel/UC…`, `/c/…` or `/user/…`) into `urls`. No YouTube account, cookies or login session is required; the Actor reads the same public channel pages a signed-out visitor sees.

#### 💬 Does it extract YouTube comments without the official API?

Yes — turn on `extractComments` to collect top comments (author, text, likes, replies) per video via the same InnerTube endpoints the YouTube website itself calls when you scroll a comments section, with no API key involved.

#### 📝 Can I bulk-extract YouTube transcripts and captions?

Yes — turn on `downloadSubtitles`, set `subtitlesLanguage` (or `any`) and `subtitlesFormat` (`srt`, `vtt`, `plaintext` or `json3`), and every video record in the run gets its caption track attached, manual or auto-generated (`preferAutoGeneratedSubtitles`).

#### 📧 Does it find channel emails for outreach or lead generation?

When `extractChannelDetails` is on, the Actor reads the channel's About panel and extracts any email address published in the description into `channelEmails` — useful for building a **YouTube channel email finder** / creator-outreach list. Only what a channel has chosen to publish publicly is returned; not every channel lists one.

#### 📈 What is the outlier/virality score and how is it calculated?

With `computeOutlierScore` on, each video's `viewCount` is divided by that channel's own recent-upload median view count (already gathered while listing the channel — no extra request), producing a `ratio` and a plain-language `label` (`viral_outlier`, `above_average`, `average`, `below_average`) in `outlierScore`. It's a free **YouTube outlier finder** signal for spotting which uploads are punching above a channel's normal reach — useful for trend-hunting, competitor channel research, and content-strategy work.

#### 🔴 Does it support live streams and Shorts, or just regular videos?

All three — regular videos, Shorts and live/upcoming streams are each detected automatically and can be capped independently with `maxResults`, `maxResultsShorts` and `maxResultStreams`. Live streams are collected, not excluded.

#### ❌ Why did a URL come back as an error row instead of data?

Check the `error` and `note` fields on that row — see the [error-row shape and ERROR\_CODES table](#-error-row-shape) above for what each code means. The most common cause is a deleted, private or region-blocked video, or a channel that genuinely has no videos/Shorts/streams on the requested tab.

#### 🐍 Can I get YouTube data straight into Python or a pandas dataframe?

Yes — pull the finished dataset via the [Apify API](https://docs.apify.com/api/v2) or the `apify-client` Python package and load the JSON directly into a pandas `DataFrame`; every field name is stable and documented in the [Output example](#-output-example) section above.

#### 🔌 Is there an API for this Actor, or only the Console UI?

Both. Run it interactively from the Apify Console, or trigger and poll it entirely through the [Apify API](https://docs.apify.com/api/v2)/`apify-client` SDKs, including `run-sync-get-dataset-items` for a single blocking call that returns finished rows directly.

***

### 🙋 Support

Found a bug, need a custom field, or want a tailored pipeline built on top of this Actor? Reach out at **<hello.dataminds@gmail.com>** — feedback and feature requests directly shape future updates to this Actor.

# Actor input Schema

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

🎬 Video, Shorts, channel, playlist, hashtag or search-results links — one per line, or upload a file. Example: `https://www.youtube.com/watch?v=...`, `https://www.youtube.com/@channelhandle`, `https://www.youtube.com/playlist?list=...`.

## `searchQueries` (type: `array`):

🗺️ Plain search terms to run on YouTube search — for example `sports highlights`, `react tutorial`. Each line is searched separately, same as typing into the YouTube search box.

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

📬 How many regular videos to collect per search term, channel or playlist. Start small for a quick sample, raise it for a full harvest.

## `maxResultsShorts` (type: `integer`):

📱 How many Shorts to collect per search term or channel. 0 = don't collect Shorts.

## `maxResultStreams` (type: `integer`):

🔴 How many live/upcoming streams to collect per search term or channel. 0 = don't collect streams.

## `sortingOrder` (type: `string`):

🔃 How YouTube orders the search results.

## `dateFilter` (type: `string`):

📅 Only include videos uploaded within this window.

## `videoType` (type: `string`):

🎞️ Restrict to videos or movies only.

## `lengthFilter` (type: `string`):

⏱️ Filter by video duration.

## `isHD` (type: `boolean`):

📺 Only include HD videos.

## `hasSubtitles` (type: `boolean`):

💬 Only include videos with subtitles or closed captions available.

## `hasCC` (type: `boolean`):

©️ Only include videos licensed under Creative Commons.

## `is3D` (type: `boolean`):

🕶️ Only include 3D videos.

## `isLive` (type: `boolean`):

🔴 Only include videos that are currently live.

## `isBought` (type: `boolean`):

🛒 Only include content you've purchased (account-dependent).

## `is4K` (type: `boolean`):

🎞️ Only include 4K videos.

## `is360` (type: `boolean`):

🌐 Only include 360° videos.

## `isHDR` (type: `boolean`):

🌈 Only include HDR videos.

## `hasLocation` (type: `boolean`):

📍 Only include videos tagged with a location.

## `isVR180` (type: `boolean`):

🥽 Only include VR180 videos.

## `sortVideosBy` (type: `string`):

📚 For channel URLs: which order to read the Videos/Shorts/Live tab in.

## `extractComments` (type: `boolean`):

💬 Collect top comments for every video (author, text, likes, replies).

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

🔢 Stop collecting comments for a video after this many.

## `downloadSubtitles` (type: `boolean`):

📝 Collect the subtitle/caption track for every video, when available.

## `subtitlesLanguage` (type: `string`):

🗣️ Language code to prefer — for example `en`, `es`, `hi`. Use `any` to accept whatever is available.

## `subtitlesFormat` (type: `string`):

📄 File format for the collected subtitle text.

## `preferAutoGeneratedSubtitles` (type: `boolean`):

🤖 Prefer YouTube's auto-generated captions over manually-uploaded ones when both exist.

## `computeOutlierScore` (type: `boolean`):

🚀 Score each video against the channel's own recent median views (virality) and compute (likes + comments) / views as an engagement rate.

## `extractChannelDetails` (type: `boolean`):

📺 For channel URLs: also read the About panel — description, country, join date, total views/videos, external links and emails found in the description.

## `monitorMode` (type: `boolean`):

🔁 Remembers every video ID collected by a previous run of this Actor (same account) and skips them next time — perfect for a daily/weekly schedule that should only report new uploads.

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

🚦 By default the run starts on a direct connection and automatically switches to a datacenter and then a residential route only if YouTube pushes back. Pick your own route here to override that.

## `browserFallback` (type: `boolean`):

🧭 As a last resort, retry stubborn requests inside a real browser session.

## `maxConcurrency` (type: `integer`):

🏎️ How many URLs/search queries to process at the same time.

## `maxRequestRetries` (type: `integer`):

🛡️ Attempts before a request is considered failed on the current network route.

## `maxScanned` (type: `integer`):

🧮 Safety cap on how many search-result rows are examined per query before giving up.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://www.youtube.com/@YouTube"
    }
  ],
  "searchQueries": [],
  "maxResults": 10,
  "maxResultsShorts": 0,
  "maxResultStreams": 0,
  "sortingOrder": "",
  "dateFilter": "",
  "videoType": "",
  "lengthFilter": "",
  "isHD": false,
  "hasSubtitles": false,
  "hasCC": false,
  "is3D": false,
  "isLive": false,
  "isBought": false,
  "is4K": false,
  "is360": false,
  "isHDR": false,
  "hasLocation": false,
  "isVR180": false,
  "sortVideosBy": "NEWEST",
  "extractComments": false,
  "maxComments": 20,
  "downloadSubtitles": false,
  "subtitlesLanguage": "en",
  "subtitlesFormat": "srt",
  "preferAutoGeneratedSubtitles": false,
  "computeOutlierScore": true,
  "extractChannelDetails": true,
  "monitorMode": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "browserFallback": true,
  "maxConcurrency": 5,
  "maxRequestRetries": 3,
  "maxScanned": 20000
}
```

# Actor output Schema

## `results` (type: `string`):

No description

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

No description

## `insights` (type: `string`):

No description

## `channel` (type: `string`):

No description

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

No description

## `errors` (type: `string`):

No description

## `runSummary` (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": [
        {
            "url": "https://www.youtube.com/@YouTube"
        }
    ],
    "maxResults": 10,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("citrine_venus/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 = {
    "urls": [{ "url": "https://www.youtube.com/@YouTube" }],
    "maxResults": 10,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("citrine_venus/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 '{
  "urls": [
    {
      "url": "https://www.youtube.com/@YouTube"
    }
  ],
  "maxResults": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call citrine_venus/youtube-scraper --silent --output-dataset

```

## MCP server setup

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