# YouTube Scraper Pro — Videos, Channels & Download Links (`scrapepilot/youtube-scraper-pro----videos-channels-download-links`) Actor

Scrape any YouTube video, channel or playlist. Returns title, views, likes, duration, thumbnail and signed download URLs for every resolution (144p to 4K). Audio-only download also available. No login required.

- **URL**: https://apify.com/scrapepilot/youtube-scraper-pro----videos-channels-download-links.md
- **Developed by:** [Scrape Pilot](https://apify.com/scrapepilot) (community)
- **Categories:** Videos, Developer tools, Automation
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

$7.99/month + usage

To use this Actor, you pay a monthly rental fee to the developer. The rent is subtracted from your prepaid usage every month after the free trial period.You also pay for the Apify platform usage, which gets cheaper the higher Apify subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#rental-actors

## 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 Scraper Pro — YouTube Scrape Videos, Channels, Playlists & Search Results

> **The most powerful YouTube scrape tool on Apify.** Extract video metadata, download URLs, subtitles, channel stats, and full playlist data — no login, no browser, no bot detection. Powered by `yt`.

---

### 📌 Table of Contents


- [What Is This Actor?](#what-is-this-actor)
- [Why Use This YouTube Scrape Tool?](#why-use-this-youtube-scrape-tool)
- [Use Cases](#use-cases)
- [Supported Input Types](#supported-input-types)
- [Output Fields (Full Reference)](#output-fields-full-reference)
- [Input Parameters](#input-parameters)
- [Example Inputs & Outputs](#example-inputs--outputs)
- [Download URLs Explained](#download-urls-explained)
- [Proxy Configuration](#proxy-configuration)
- [Video Quality Options](#video-quality-options)
- [Subtitles & Captions](#subtitles--captions)
- [Chapters Support](#chapters-support)
- [Channel Scraping](#channel-scraping)
- [Playlist Scraping](#playlist-scraping)
- [YouTube Search Scraping](#youtube-search-scraping)
- [Performance & Rate Limits](#performance--rate-limits)
- [FAQ](#faq)
- [Changelog](#changelog)
- [Legal & Terms of Use](#legal--terms-of-use)

---

### 🔍 What Is This Actor?

**YouTube Scraper Pro** is a production-grade Apify actor that performs a complete **YouTube scrape** of any public YouTube content — including individual videos, full channels, playlists, and keyword search results — without requiring any Google login, API keys, or browser automation.

It is built on top of **yt**, the industry-standard open-source YouTube extraction engine trusted by millions of developers and researchers worldwide. Unlike browser-based scrapers that simulate a user clicking through YouTube, this actor communicates directly with YouTube's internal endpoints, bypassing bot detection entirely and delivering results in seconds.

Whether you need to **YouTube scrape** a single video for metadata and download URLs, extract every video from a creator's channel, or pull the top 50 results for a keyword search — this actor handles all of it through one clean, unified interface.

---

### 🚀 Why Use This YouTube Scrape Tool?

| Feature | YouTube Scraper Pro | Browser-Based Scrapers | YouTube Data API v3 |
|---|---|---|---|
| **No login required** | ✅ | ✅ | ❌ API key required |
| **Bot detection triggered** | ❌ Never | ⚠️ Frequently | ❌ N/A |
| **Download URLs** | ✅ All resolutions | ❌ No | ❌ No |
| **Subtitle extraction** | ✅ | ⚠️ Partial | ⚠️ Partial |
| **Channel scrape** | ✅ Unlimited | ⚠️ Limited | ⚠️ Quota limited |
| **Playlist scrape** | ✅ Full | ⚠️ Partial | ✅ |
| **Residential proxy** | ✅ Built-in | ⚠️ Extra setup | ❌ N/A |
| **Speed** | ⚡ Fast | 🐢 Slow | ⚡ Fast |
| **Daily quota** | ✅ Unlimited | ✅ Unlimited | ❌ 10,000 units/day |
| **4K download URL** | ✅ | ❌ | ❌ |

> **Bottom line:** If you need to **YouTube scrape** at scale, with download URLs, zero quotas, and no API key — this is the tool for you.

---

### 🎯 Use Cases

This actor is used by developers, marketers, researchers, and data scientists to:

#### 📊 Market Research & Competitive Intelligence
- YouTube scrape a competitor's channel to analyze their top-performing videos, view counts, like ratios, and publishing frequency
- Track trending topics in a niche by scraping YouTube search results for target keywords weekly
- Monitor subscriber growth and engagement metrics across multiple channels

#### 🎓 Content Research & SEO
- YouTube scrape search results to discover what content ranks for your target keywords
- Analyze video titles, descriptions, and tags to identify SEO patterns that drive views
- Extract chapter structures from long-form videos to understand content depth and user engagement hooks

#### 📥 Content Archiving & Backup
- Scrape and archive download URLs for entire YouTube playlists or channels before content is deleted
- Extract video transcripts and subtitles at scale for research datasets or accessibility tools
- Download metadata for thousands of videos for academic research or journalism

#### 🤖 AI & Machine Learning Datasets
- YouTube scrape thousands of videos to build training datasets for NLP, sentiment analysis, or video classification models
- Extract auto-generated captions across languages for multilingual AI training
- Collect structured video metadata (duration, views, likes, categories, tags) for recommendation system research

#### 📱 App Development & Integration
- Build a YouTube client app that pulls metadata and streams content via direct download URLs
- Integrate YouTube search results into your own platform without hitting YouTube API quotas
- Create automated content pipelines that monitor channels and alert on new uploads

#### 📰 Journalism & Fact-Checking
- YouTube scrape specific channels or accounts to preserve evidence of public statements
- Extract engagement statistics for viral videos during news events
- Archive entire playlists of public interest content with timestamped metadata

---

### 🔗 Supported Input Types

This actor supports **four distinct YouTube scrape modes**, all through the same interface:

#### 📺 Single Video Scrape
Provide any YouTube video URL and receive the complete metadata record including all download URLs, subtitles, chapters, and format options.

**Supported URL formats:**
````

https://www.youtube.com/watch?v=dQw4w9WgXcQ
https://youtu.be/dQw4w9WgXcQ
https://www.youtube.com/watch?v=VIDEO\_ID\&list=PLAYLIST\_ID   ← extracts the video, not the playlist

```

#### 📢 Channel Scrape
Provide any YouTube channel URL and scrape all (or the top N) videos from that channel, complete with full metadata and download URLs for each.

**Supported channel URL formats:**
```

https://www.youtube.com/@ChannelHandle
https://www.youtube.com/c/ChannelName
https://www.youtube.com/channel/UCxxxxxxxxxxxxxxxxxxxxxx
https://www.youtube.com/user/LegacyUsername

```

#### 📋 Playlist Scrape
Provide a YouTube playlist URL to scrape all videos in the playlist, in order, with position numbers.

**Supported playlist URL formats:**
```

https://www.youtube.com/playlist?list=PLxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

```

#### 🔍 YouTube Search Scrape
Provide a keyword or phrase and scrape the top N YouTube search results, complete with view counts, ranks, and download URLs.

**Example search queries:**
```

Python programming tutorial 2024
best lo-fi music for studying
how to make sourdough bread

````

---

### 📋 Output Fields (Full Reference)

Every **YouTube scrape** result record contains the following fields:

#### 🎥 Core Video Fields

| Field | Type | Description | Example |
|---|---|---|---|
| `video_id` | string | YouTube video ID | `"dQw4w9WgXcQ"` |
| `title` | string | Full video title (max 300 chars) | `"Rick Astley - Never Gonna Give You Up"` |
| `video_url` | string | Canonical YouTube watch URL | `"https://www.youtube.com/watch?v=..."` |
| `duration_seconds` | integer | Duration in seconds | `212` |
| `duration` | string | Human-readable duration | `"03:32"` |
| `published_date` | string | ISO date of upload | `"2009-10-25"` |
| `is_live` | boolean | Whether video is a live stream | `false` |
| `age_restricted` | boolean | Whether 18+ age gate applies | `false` |
| `category` | string | YouTube content category | `"Music"` |

#### 👤 Channel & Creator Fields

| Field | Type | Description | Example |
|---|---|---|---|
| `channel_name` | string | Creator's channel name | `"RickAstleyVEVO"` |
| `channel_url` | string | Full URL to channel | `"https://www.youtube.com/@RickAstleyVEVO"` |
| `channel_id` | string | Internal YouTube channel ID | `"UCuAXFkgsw1L7xaCfnd5JJOw"` |
| `subscriber_count` | integer | Raw subscriber count | `1300000` |
| `subscriber_count_text` | string | Formatted subscriber count | `"1.3M subscribers"` |

#### 📈 Engagement Metrics

| Field | Type | Description | Example |
|---|---|---|---|
| `views` | integer | Total view count | `1400000000` |
| `views_text` | string | Formatted view count | `"1.4B views"` |
| `likes` | integer | Total like count | `15000000` |

#### 🖼️ Media Fields

| Field | Type | Description | Example |
|---|---|---|---|
| `thumbnail` | string | URL to max-resolution thumbnail | `"https://i.ytimg.com/vi/.../maxresdefault.jpg"` |
| `description` | string | Video description (max 1000 chars) | `"The official video..."` |
| `tags` | array | Video tags (max 20) | `["rick astley", "80s", "pop"]` |

#### ⬇️ Download URL Fields

| Field | Type | Description |
|---|---|---|
| `download_url_best` | string | Best available combined video+audio stream URL |
| `download_url_best_quality` | string | Resolution label of the best stream (e.g. `"1080p"`) |
| `download_url_video_only` | string | Best video-only stream URL (no audio, for merging) |
| `download_url_audio_only` | string | Best audio-only stream URL (m4a/webm/opus) |
| `all_formats` | array | All available formats (see below) |

#### 🎞️ Format Object (inside `all_formats`)

```json
{
  "format_id": "137",
  "ext": "mp4",
  "resolution": "1080p",
  "height": 1080,
  "fps": 30,
  "has_video": true,
  "has_audio": false,
  "filesize_mb": 245.8,
  "bitrate_kbps": 3200.0,
  "url": "https://..."
}
````

#### 📝 Subtitles & Captions Fields

| Field | Type | Description | Example |
|---|---|---|---|
| `subtitles_languages` | array | Languages with manual subtitles | `["en", "es", "fr"]` |
| `auto_captions_languages` | array | Languages with auto-generated captions | `["en", "de"]` |

#### 📑 Chapters Fields

| Field | Type | Description | Example |
|---|---|---|---|
| `chapters_count` | integer | Number of chapters | `8` |
| `chapters` | array | List of chapter objects | `[{"title": "Intro", "start": 0}]` |

#### 🔧 Meta Fields

| Field | Type | Description | Example |
|---|---|---|---|
| `url_type` | string | Source type of this result | `"video"`, `"channel_video"`, `"playlist_video"`, `"search_result"` |
| `fetched_at` | string | ISO timestamp of scrape | `"2024-11-01T12:34:56Z"` |
| `search_query` | string | (Search mode only) Query used | `"python tutorial"` |
| `search_rank` | integer | (Search mode only) Position in results | `1` |
| `playlist_title` | string | (Playlist/Channel mode) Parent playlist name | `"My Favorites"` |
| `playlist_id` | string | (Playlist/Channel mode) Playlist ID | `"PLxxx..."` |
| `position` | integer | (Playlist/Channel mode) Position in list | `3` |

***

### ⚙️ Input Parameters

Configure your **YouTube scrape** job with the following input fields:

```json
{
  "video_url":           "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "channel_url":         "",
  "playlist_url":        "",
  "search_query":        "",
  "max_results":         20,
  "quality":             "best",
  "proxyConfiguration": {
    "useApifyProxy":     true,
    "apifyProxyGroups":  ["RESIDENTIAL"]
  }
}
```

| Parameter | Type | Default | Description |
|---|---|---|---|
| `video_url` | string | `""` | URL of a single YouTube video to scrape |
| `channel_url` | string | `""` | URL of a YouTube channel to scrape |
| `playlist_url` | string | `""` | URL of a YouTube playlist to scrape |
| `search_query` | string | `""` | Keyword or phrase to search YouTube and scrape results |
| `max_results` | integer | `20` | Maximum number of videos to return (for channel/playlist/search modes) |
| `quality` | string | `"best"` | Preferred quality level for download URLs: `"best"`, `"1080p"`, `"720p"`, `"480p"`, `"360"`, `"audio"` |
| `proxyConfiguration` | object | Residential | Apify proxy config. Recommended to keep RESIDENTIAL enabled. |

> **Note:** Only one of `video_url`, `channel_url`, `playlist_url`, or `search_query` should be provided per run. If multiple are provided, priority is: `video_url` → `channel_url` → `playlist_url` → `search_query`.

***

### 📦 Example Inputs & Outputs

#### Example 1: YouTube Scrape — Single Video

**Input:**

```json
{
  "video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "quality": "best"
}
```

**Output:**

```json
[
  {
    "video_id": "dQw4w9WgXcQ",
    "title": "Rick Astley - Never Gonna Give You Up (Official Music Video)",
    "video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "channel_name": "Rick Astley",
    "channel_url": "https://www.youtube.com/@RickAstleyVEVO",
    "subscriber_count": 4200000,
    "subscriber_count_text": "4.2M subscribers",
    "views": 1450000000,
    "views_text": "1.5B views",
    "likes": 16000000,
    "duration_seconds": 212,
    "duration": "03:32",
    "published_date": "2009-10-25",
    "description": "The official video for "Never Gonna Give You Up" by Rick Astley...",
    "tags": ["Rick Astley", "Never Gonna Give You Up", "OfficialVideoMusic"],
    "category": "Music",
    "thumbnail": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
    "is_live": false,
    "age_restricted": false,
    "download_url_best": "https://rr3---sn-xxxx.googlevideo.com/...",
    "download_url_best_quality": "1080p",
    "download_url_video_only": "https://rr3---sn-xxxx.googlevideo.com/...",
    "download_url_audio_only": "https://rr3---sn-xxxx.googlevideo.com/...",
    "all_formats": [
      {
        "format_id": "137",
        "ext": "mp4",
        "resolution": "1080p",
        "height": 1080,
        "fps": 30,
        "has_video": true,
        "has_audio": false,
        "filesize_mb": 89.3,
        "bitrate_kbps": 3120.0,
        "url": "https://..."
      },
      {
        "format_id": "22",
        "ext": "mp4",
        "resolution": "720p",
        "height": 720,
        "fps": 30,
        "has_video": true,
        "has_audio": true,
        "filesize_mb": 45.1,
        "bitrate_kbps": 1800.0,
        "url": "https://..."
      }
    ],
    "subtitles_languages": ["en", "es", "pt", "fr", "de"],
    "auto_captions_languages": ["en", "ja"],
    "chapters_count": 0,
    "chapters": [],
    "url_type": "video",
    "fetched_at": "2024-11-01T10:30:00Z"
  }
]
```

***

#### Example 2: YouTube Scrape — Channel Videos

**Input:**

```json
{
  "channel_url": "https://www.youtube.com/@mkbhd",
  "max_results": 5,
  "quality": "best"
}
```

**Output (abbreviated):**

```json
[
  {
    "video_id": "abc123",
    "title": "The Best Smartphones of 2024",
    "channel_name": "Marques Brownlee",
    "channel_url": "https://www.youtube.com/@mkbhd",
    "subscriber_count": 18500000,
    "views": 4800000,
    "views_text": "4.8M views",
    "duration": "18:42",
    "published_date": "2024-12-01",
    "download_url_best": "https://...",
    "download_url_best_quality": "4K",
    "url_type": "channel_video",
    "position": 1,
    "fetched_at": "2024-12-10T08:00:00Z"
  }
]
```

***

#### Example 3: YouTube Scrape — Search Results

**Input:**

```json
{
  "search_query": "YouTube scrape tutorial python",
  "max_results": 10
}
```

**Output (abbreviated):**

```json
[
  {
    "video_id": "xyz789",
    "title": "How to YouTube Scrape with Python in 2024",
    "views": 120000,
    "views_text": "120K views",
    "search_query": "YouTube scrape tutorial python",
    "search_rank": 1,
    "url_type": "search_result",
    "download_url_best": "https://...",
    "fetched_at": "2024-12-10T09:00:00Z"
  }
]
```

***

#### Example 4: YouTube Scrape — Playlist

**Input:**

```json
{
  "playlist_url": "https://www.youtube.com/playlist?list=PLbpi6ZahtOH6Ar_3GPy3workS_ij8",
  "max_results": 50
}
```

**Output:** Returns up to 50 video objects, each with `url_type: "playlist_video"` and `position` number.

***

### ⬇️ Download URLs Explained

One of the most powerful features of this **YouTube scrape** actor is the ability to extract **direct, signed, time-limited download URLs** for every video. Here's what each field means:

#### `download_url_best`

The highest-quality **combined** stream containing both video and audio in a single file. This is ideal for direct playback or download via tools like `curl` or `wget`. For older/shorter videos this is often a 720p MP4 with both streams. For longer or newer videos, YouTube separates video and audio tracks.

#### `download_url_video_only`

The highest-quality video stream **without audio**. This is typically 1080p, 1440p (2K), or 2160p (4K) in VP9 or AVC format. To use this with audio, merge it with `download_url_audio_only` using FFmpeg:

```bash
ffmpeg -i video_only.mp4 -i audio_only.m4a -c:v copy -c:a aac merged_output.mp4
```

#### `download_url_audio_only`

Audio-only stream in M4A, WebM, or Opus format. Ideal for podcasts, music extraction, or transcription pipelines.

#### `all_formats`

A complete list of every format available for that video (up to 20), sorted by resolution descending. Use this to select a specific quality level programmatically.

> ⚠️ **Important:** Download URLs are **signed and time-limited** by Google (typically valid for 6–12 hours). They are meant for immediate use and should not be stored long-term. Re-run the actor to refresh URLs.

***

### 🌐 Proxy Configuration

For maximum reliability when performing a **YouTube scrape**, especially at high volume, a residential proxy is strongly recommended.

#### Recommended Setup (Apify Residential Proxy)

```json
{
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

#### Why Residential Proxy?

- YouTube detects and rate-limits datacenter IPs at high volume
- Residential IPs appear as normal user traffic
- Essential for scraping region-restricted content
- Reduces `HTTP 429 Too Many Requests` errors significantly

#### No Proxy (Default)

For low-volume scraping (under ~50 videos/run),  typically works without any proxy. YouTube has not blocked yt-'s request pattern as aggressively as browser-based scrapers.

```json
{
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

#### Custom Proxy

You can also provide your own proxy URL by passing it through Apify's proxy configuration system.

***

### 🎬 Video Quality Options

Control the quality of `download_url_best` using the `quality` parameter:

| Value | Description | Typical Use Case |
|---|---|---|
| `"best"` | Highest available combined stream | General purpose, recommended |
| `"1080p"` | Full HD (1920×1080) | HD video archiving |
| `"720p"` | HD (1280×720) | Balanced quality/size |
| `"480p"` | SD (854×480) | Mobile-friendly size |
| `"360p"` | Low resolution (640×360) | Bandwidth-limited environments |
| `"audio"` | Audio only (best audio stream) | Podcast/music extraction |

> **Note:** The `all_formats` array always contains all available resolutions regardless of the `quality` setting. The `quality` parameter only affects which URL is returned in `download_url_best`.

Available resolutions per video depend on the original upload. Most modern YouTube videos support up to 4K (2160p), while older content may max out at 720p.

***

### 📝 Subtitles & Captions

Every **YouTube scrape** result includes subtitle availability data:

#### `subtitles_languages`

Languages for which the creator has manually uploaded subtitles (closed captions). These are the highest accuracy captions. Example: `["en", "es", "pt-BR", "fr", "de", "ja", "ko"]`

#### `auto_captions_languages`

Languages for which YouTube has auto-generated captions using speech recognition. Available for most videos in major languages. Example: `["en", "hi", "ar"]`

#### Fetching Subtitle Content

This actor returns the **availability** of subtitles. To download the actual subtitle text (SRT/VTT format), use yt-dlp locally with the video URL:

```bash
yt-dlp --write-subs --sub-lang en --skip-download "https://www.youtube.com/watch?v=VIDEO_ID"
```

***

### 📑 Chapters Support

If a video has chapters (timestamps in the description), the actor returns structured chapter data:

```json
{
  "chapters_count": 5,
  "chapters": [
    {"title": "Introduction", "start": 0},
    {"title": "Setting Up Your Environment", "start": 120},
    {"title": "Writing the Code", "start": 480},
    {"title": "Testing & Debugging", "start": 900},
    {"title": "Conclusion", "start": 1320}
  ]
}
```

This is extremely useful for:

- Extracting specific segments from long-form videos
- Building educational content navigation interfaces
- Analyzing how creators structure their content

***

### 📢 Channel Scraping

When performing a **YouTube channel scrape**, the actor uses a two-phase approach for maximum speed and accuracy:

#### Phase 1: Fast Flat Extraction

The actor first fetches a flat list of all video IDs in the channel using yt-dlp's `extract_flat` mode. This is extremely fast and gives us the complete video inventory.

#### Phase 2: Detailed Metadata Fetch

For each video (up to `max_results`), the actor fetches full metadata including download URLs, views, likes, chapters, and subtitle info. A small random delay (0.5–1.5s) between requests prevents rate limiting.

#### Channel Output Extras

In addition to all standard video fields, channel scrape results include:

- `url_type: "channel_video"` — identifies the source
- `position` — video's position in the channel (1 = most recent)
- `playlist_title` — usually the channel's uploads playlist name

#### Tip: Large Channels

For channels with thousands of videos, set `max_results` to the number you need. The actor fetches in chronological order from newest to oldest.

***

### 📋 Playlist Scraping

Playlist scraping is ideal for structured content sets like course series, documentary collections, or music albums.

#### Playlist Output Extras

- `url_type: "playlist_video"` — identifies the source
- `position` — video's position in the playlist (1 = first)
- `playlist_title` — name of the playlist
- `playlist_id` — YouTube playlist ID

#### Mixed Playlists

If a playlist mixes videos from multiple channels, each video's `channel_name` and `channel_url` will correctly reflect the original uploader.

***

### 🔍 YouTube Search Scraping

The search scraping mode uses yt-dlp's built-in `ytsearch` protocol to query YouTube and return the top N results. This is equivalent to what a user would see on YouTube's search results page.

#### Search Output Extras

- `url_type: "search_result"` — identifies results from search mode
- `search_query` — the exact query used
- `search_rank` — 1-based position in search results (1 = top result)

#### Search Tips

- Use specific, long-tail keywords for niche research
- Search results reflect YouTube's own algorithm (views, recency, relevance)
- For trending content, run searches daily and compare rank changes
- Use `max_results` up to 50 for comprehensive keyword analysis

***

### ⚡ Performance & Rate Limits

#### Speed Benchmarks (approximate, with residential proxy)

| Mode | Videos | Estimated Time |
|---|---|---|
| Single video | 1 | ~5–10 seconds |
| Search results | 10 | ~30–60 seconds |
| Search results | 50 | ~3–5 minutes |
| Channel (small, <100 videos) | 20 | ~1–2 minutes |
| Channel (large, 500+ videos) | 50 | ~4–7 minutes |
| Playlist | 50 | ~4–7 minutes |

#### Rate Limiting Strategy

The actor implements smart rate limiting with:

- **0.5–1.5 second random delay** between consecutive video fetches in channel/playlist mode
- **3 automatic retries** with exponential backoff on failed requests
- **30-second socket timeout** to prevent hanging on slow connections
- **Graceful error handling** — failed videos return partial records instead of crashing the run

#### Concurrent Runs

You can run multiple instances of this actor simultaneously (e.g., one per channel) for parallel scraping without conflicts.

***

### ❓ FAQ

**Q: Do I need a YouTube API key or Google account?**
A: No. This actor requires zero authentication. No API keys, no cookies, no login.

**Q: Are the download URLs direct links I can use in a browser?**
A: Yes. `download_url_best` is a direct signed URL to the video file hosted on Google's CDN. You can paste it in a browser, `curl` it, or stream it directly. They expire in ~6–12 hours.

**Q: Why does `download_url_best` sometimes return a video-only stream?**
A: For high-resolution videos (1080p+), YouTube serves video and audio as separate streams. In that case, `download_url_best` returns the highest-quality video-only stream. Use `download_url_audio_only` alongside it with FFmpeg to merge.

**Q: How many videos can I scrape from a channel?**
A: There is no hard limit. Set `max_results` to however many you need. Very large channels (10,000+ videos) may require long run times; consider splitting into multiple runs.

**Q: Can I scrape private or unlisted videos?**
A: No. This actor can only access publicly accessible YouTube content. Private videos require authenticated cookies.

**Q: Why are some videos missing `views` or `likes`?**
A: Some YouTube videos have these metrics hidden by the creator. In those cases the fields will be `null`.

**Q: Can I use this for shorts?**
A: Yes. YouTube Shorts are treated as regular short-duration videos and can be scraped with all standard fields including download URLs.

**Q: What happens if a video is age-restricted?**
A: Age-restricted videos will have `age_restricted: true`. Metadata extraction typically still works, but download URLs may not be available without authentication.

**Q: How fresh is the data?**
A: Completely fresh. Every run performs a live **YouTube scrape** in real time. There is no caching.

**Q: Does this work for YouTube Music content?**
A: YouTube Music videos are hosted on YouTube and can be scraped like regular videos.

***

### 📜 Changelog

#### v2.0.0 (Current)

- ✅ Full yt-dlp engine integration replacing legacy extraction
- ✅ Added `all_formats` array with up to 20 quality levels
- ✅ Residential proxy auto-configuration
- ✅ Chapter extraction support
- ✅ Subtitle language detection (manual + auto-captions)
- ✅ Formatted view/subscriber count fields
- ✅ `search_rank` and `position` fields for ordered results
- ✅ Graceful error handling with partial records on failure
- ✅ Smart rate limiting with jitter delay

#### v1.5.0

- ✅ Added YouTube search scraping mode
- ✅ Added `download_url_video_only` and `download_url_audio_only`
- ✅ Channel subscriber count extraction
- ✅ Tags extraction (up to 20)

#### v1.0.0

- ✅ Initial release: single video + playlist scraping
- ✅ Basic metadata: title, views, description, thumbnail

***

### ⚖️ Legal & Terms of Use

This actor extracts publicly available data from YouTube in the same way a regular user browses the site. All data collected is publicly accessible without any login.

**Please note:**

- This actor is intended for **research, education, journalism, and personal use**
- Respect YouTube's Terms of Service and do not use scraped data for unauthorized commercial redistribution of video content
- Signed download URLs are for personal use only; redistributing copyrighted video content may violate copyright law
- Do not use this tool to scrape private, unlisted, or age-gated content without authorization
- The actor developer is not responsible for how users choose to use the scraped data

**Fair Use:** Metadata scraping (titles, views, descriptions, channel stats) is generally considered fair use for research and analytical purposes. Always consult a legal professional for your specific use case.

***

### 🤝 Support & Feedback

- **Issues?** Open a GitHub issue or contact us via the Apify actor page
- **Feature request?** Drop a message in the Apify Community forum
- **Rating:** If this actor helped you, please leave a ⭐ review on the Apify Store — it helps others discover it!

***

<p align="center">
  <strong>Built with ❤️ on Apify · Powered by yt-dlp · Zero Login Required</strong><br/>
  <em>The most complete YouTube scrape solution on the Apify platform</em>
</p>

# Actor input Schema

## `video_url` (type: `string`):

YouTube video URL to scrape and get download link.

✅ Accepted formats:
https://www.youtube.com/watch?v=dQw4w9WgXcQ
https://youtu.be/dQw4w9WgXcQ
https://www.youtube.com/shorts/abc123

💡 Returns: title, views, likes, duration, all download URLs (144p → 4K), subtitles list, chapters

## `channel_url` (type: `string`):

YouTube channel URL to scrape all videos.

✅ Accepted formats:
https://www.youtube.com/@MrBeast
https://www.youtube.com/c/ChannelName
https://www.youtube.com/channel/UCxxxxxx
https://www.youtube.com/user/OldUsername

💡 Returns: all channel videos with full metadata and download links
⚙️ Set 'Max Videos' to control how many videos to scrape

## `playlist_url` (type: `string`):

YouTube playlist URL to scrape all videos.

✅ Accepted formats:
https://www.youtube.com/playlist?list=PLxxxxx
https://www.youtube.com/watch?v=xxx\&list=PLxxxxx

💡 Returns: all playlist videos with download links in order

## `search_query` (type: `string`):

Search YouTube and scrape the top results.

✅ Examples:
Python tutorial for beginners
lofi hip hop music 2024
Mr Beast challenge
nature documentary 4K

💡 Returns: top search results with views, duration and download links

## `max_results` (type: `integer`):

Maximum number of videos to scrape.

📌 Recommended:
1 → single video (instant)
10-20 → channel/playlist test
50-100 → bulk channel scrape

⚠️ More videos = longer run time. Channel scraping: ~5-10 sec per video.

## `quality` (type: `string`):

Preferred video quality for the download\_url\_best field.

4K (2160p) → Ultra HD, very large files
1080p → Full HD — recommended
720p → HD — smaller files, good quality
480p → Standard quality
360p → Low bandwidth
144p → Minimum quality
audio\_only → Audio only (no video)

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

RESIDENTIAL proxy keeps your IP safe and avoids rate limits.

✅ Always keep RESIDENTIAL proxy enabled for:
• Channel scraping (many requests)
• Avoiding YouTube rate limits
• Accessing geo-restricted content

⚠️ yt-dlp works without proxy for single videos but RESIDENTIAL is recommended for bulk scraping.

## Actor input object example

```json
{
  "max_results": 20,
  "quality": "best",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapepilot/youtube-scraper-pro----videos-channels-download-links").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 = { "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    } }

# Run the Actor and wait for it to finish
run = client.actor("scrapepilot/youtube-scraper-pro----videos-channels-download-links").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 '{
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call scrapepilot/youtube-scraper-pro----videos-channels-download-links --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "YouTube Scraper Pro — Videos, Channels & Download Links",
        "description": "Scrape any YouTube video, channel or playlist. Returns title, views, likes, duration, thumbnail and signed download URLs for every resolution (144p to 4K). Audio-only download also available. No login required.",
        "version": "0.0",
        "x-build-id": "2AdBjUoOTxgzhg8dK"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/scrapepilot~youtube-scraper-pro----videos-channels-download-links/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-scrapepilot-youtube-scraper-pro----videos-channels-download-links",
                "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/scrapepilot~youtube-scraper-pro----videos-channels-download-links/runs": {
            "post": {
                "operationId": "runs-sync-scrapepilot-youtube-scraper-pro----videos-channels-download-links",
                "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/scrapepilot~youtube-scraper-pro----videos-channels-download-links/run-sync": {
            "post": {
                "operationId": "run-sync-scrapepilot-youtube-scraper-pro----videos-channels-download-links",
                "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": {
                    "video_url": {
                        "title": "📹 Single Video URL",
                        "type": "string",
                        "description": "YouTube video URL to scrape and get download link.\n\n✅ Accepted formats:\nhttps://www.youtube.com/watch?v=dQw4w9WgXcQ\nhttps://youtu.be/dQw4w9WgXcQ\nhttps://www.youtube.com/shorts/abc123\n\n💡 Returns: title, views, likes, duration, all download URLs (144p → 4K), subtitles list, chapters"
                    },
                    "channel_url": {
                        "title": "📢 Channel URL",
                        "type": "string",
                        "description": "YouTube channel URL to scrape all videos.\n\n✅ Accepted formats:\nhttps://www.youtube.com/@MrBeast\nhttps://www.youtube.com/c/ChannelName\nhttps://www.youtube.com/channel/UCxxxxxx\nhttps://www.youtube.com/user/OldUsername\n\n💡 Returns: all channel videos with full metadata and download links\n⚙️ Set 'Max Videos' to control how many videos to scrape"
                    },
                    "playlist_url": {
                        "title": "📋 Playlist URL",
                        "type": "string",
                        "description": "YouTube playlist URL to scrape all videos.\n\n✅ Accepted formats:\nhttps://www.youtube.com/playlist?list=PLxxxxx\nhttps://www.youtube.com/watch?v=xxx&list=PLxxxxx\n\n💡 Returns: all playlist videos with download links in order"
                    },
                    "search_query": {
                        "title": "🔍 Search Query",
                        "type": "string",
                        "description": "Search YouTube and scrape the top results.\n\n✅ Examples:\nPython tutorial for beginners\nlofi hip hop music 2024\nMr Beast challenge\nnature documentary 4K\n\n💡 Returns: top search results with views, duration and download links"
                    },
                    "max_results": {
                        "title": "🔢 Max Videos",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Maximum number of videos to scrape.\n\n📌 Recommended:\n1 → single video (instant)\n10-20 → channel/playlist test\n50-100 → bulk channel scrape\n\n⚠️ More videos = longer run time. Channel scraping: ~5-10 sec per video.",
                        "default": 20
                    },
                    "quality": {
                        "title": "🎞️ Preferred Download Quality",
                        "enum": [
                            "best",
                            "2160",
                            "1080",
                            "720",
                            "480",
                            "360",
                            "240",
                            "144",
                            "audio_only"
                        ],
                        "type": "string",
                        "description": "Preferred video quality for the download_url_best field.\n\n4K (2160p) → Ultra HD, very large files\n1080p → Full HD — recommended\n720p → HD — smaller files, good quality\n480p → Standard quality\n360p → Low bandwidth\n144p → Minimum quality\naudio_only → Audio only (no video)",
                        "default": "best"
                    },
                    "proxyConfiguration": {
                        "title": "🔒 Proxy (RESIDENTIAL Recommended)",
                        "type": "object",
                        "description": "RESIDENTIAL proxy keeps your IP safe and avoids rate limits.\n\n✅ Always keep RESIDENTIAL proxy enabled for:\n• Channel scraping (many requests)\n• Avoiding YouTube rate limits\n• Accessing geo-restricted content\n\n⚠️ yt-dlp works without proxy for single videos but RESIDENTIAL is recommended for bulk scraping."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
