# YouTube Scraper (`zeropointstudio/youtube-scraper`) Actor

All-in-one YouTube scraper: search, channels, playlists, video URLs, and transcripts in a single run. Powered by TranscriptAPI.

- **URL**: https://apify.com/zeropointstudio/youtube-scraper.md
- **Developed by:** [Andrej Šimunaj](https://apify.com/zeropointstudio) (community)
- **Categories:** Videos, Social media, AI
- **Stats:** 38 total users, 12 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 search requests

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/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

## $5/1K Requests — YouTube Scraper: Search, Channels, Playlists & Transcripts in One Run

> **Scrape YouTube at scale: search results, full channels, entire playlists, direct video URLs, and transcripts — all from a single actor. Pay per API call ($0.005), not per result. No YouTube API key, no actor-start fee, errors are free.**

| ⚡ **Sub-500 ms typical** | 📊 **15 M+ requests / month** | 🛡️ **Doesn't break when YouTube changes things** | 🔌 **Powered by [TranscriptAPI.com](https://transcriptapi.com)** |
|---|---|---|---|

A production-grade, multi-mode YouTube scraper for content research, AI/LLM training datasets, RAG pipelines, brand monitoring, SEO, market analysis, and any workflow that needs YouTube data + transcripts as clean structured JSON.

***

### 🚀 Why this YouTube scraper?

- 🎛️ **All-in-one** — search, channel uploads, playlists, direct video URLs, **and** transcripts in one actor. Mix any combination of inputs in a single run.
- 💸 **Per-API-call pricing** — pay $0.005 per backend request, not per result. A single search returns up to 20 results for one charge. A channel page returns up to 100 videos for one charge. Compare that to per-item billing elsewhere.
- ⚡ **Sub-500 ms typical** — backed by [TranscriptAPI.com](https://transcriptapi.com) with **median 49 ms** latency, plus a small Apify networking hop.
- 📊 **15 M+ requests / month** — battle-tested in real production traffic, not a side project.
- 🛡️ **Doesn't break when YouTube changes things** — we ship through every YouTube backend change without dropping requests.
- 💸 **No actor-start fee** — we absorb the run cost.
- 🆓 **Errors are free** — failed transcripts, bad URLs, and unreachable channels never bill.
- 🔑 **No YouTube API key required** — bring a URL or a search query, we bring the data.
- 📦 **Bulk-friendly** — paste 1 query or 1,000 URLs. Results land in an Apify Dataset, ready for JSON, CSV, Excel, or your warehouse.
- 🧹 **Clean structured output** — unified per-item schema across every input mode, so downstream parsing stays simple.
- 📝 **Transcripts as a first-class feature** — JSON segments, plain text, **SRT**, or **WebVTT**. Toggle on/off per run.
- 🔌 **Plug-and-play** — runnable from Python, Node.js, REST API, n8n, Make, Zapier, MCP, LangChain, LlamaIndex, or any webhook.

***

### 💰 Pricing

| Event | Price |
|---|---|
| `search` | **$0.005** *(per search request — returns up to ~20 results per call; paginates if you ask for more)* |
| `videos-page` | **$0.005** *(per page when listing videos from a channel or playlist — returns up to ~100 videos per call)* |
| `transcript-fetched` | **$0.005** *(per successfully retrieved transcript)* |
| Actor start | **Free** *(we absorb it)* |
| Errors / failed videos | **Free** |

> **How much does a typical run cost?** A search for 100 videos = 5× `search` events ≈ $0.025. Pulling 300 videos from one channel = 3× `videos-page` events ≈ $0.015. Adding transcripts to all 300 = +$1.50. Discovery without transcripts is intentionally cheap.

> Per-API-call pricing. No subscription, no monthly minimum, no hidden fees. Failed requests never bill.

***

### ⚡ Quick Start

1. Click **Try for free** at the top of this page.
2. Drop YouTube search terms into `searchQueries`, paste channel / playlist / video URLs into `startUrls`, or both.
3. Set `downloadSubtitles: true` if you also want transcripts.
4. Run. Results land in the actor's default Dataset — export to JSON, CSV, Excel, XML, or HTML.

```json
{
  "searchQueries": ["ai productivity tips", "vibe coding"],
  "startUrls": [
    "https://www.youtube.com/@TED",
    "https://www.youtube.com/playlist?list=PLOU2XLYxmsILqUKy5sN-2NjjkUtX_kxnu",
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "searchType": "video",
  "maxResults": 50,
  "downloadSubtitles": true,
  "subtitlesFormat": "json",
  "includeTimestamps": true
}
```

***

### 📥 Input

| Field | Type | Default | Description |
|---|---|---|---|
| `searchQueries` | `string[]` | `[]` | Free-text YouTube searches. Each query is fetched separately and capped by `maxResults`. |
| `startUrls` | `string[]` | `[]` | Mix of video URLs, channel URLs (`/channel/UC…`, `/@handle`, `/c/…`, `/user/…`), or playlist URLs (`?list=…`). Auto-detected. |
| `searchType` | `"video"` | `"channel"` | `"video"` | What `searchQueries` should return. |
| `maxResults` | `integer` | `20` | Per-search-query, per-channel, per-playlist cap. |
| `downloadSubtitles` | `boolean` | `false` | When `true`, fetches a transcript for every video discovered and merges it onto the same item. |
| `subtitlesFormat` | `"json"` | `"text"` | `"srt"` | `"vtt"` | `"json"` | Transcript output format. |
| `includeTimestamps` | `boolean` | `true` | Per-segment timestamps on `json` / `text` transcripts. |
| `subtitlesLanguage` | `string` | `"en"` | Caption language preference. |
| `includeVideoMetadata` | `boolean` | `true` | Include title / channel / thumbnail on transcript items. |
| `saveSubsToKVS` | `boolean` | `false` | Also write each transcript to the default Key-Value Store as `transcript-<videoId>`. |

At least one of `searchQueries` or `startUrls` must be provided.

***

### 📤 Output — unified per-item shape

Each result is one row in the default Dataset. The `source` field tells you where it came from: `search`, `channel`, `channelLatest`, `playlist`, or `directUrl`.

**Video result (from search):**

```json
{
  "source": "search",
  "input": "claude code tutorial",
  "order": 0,
  "type": "video",
  "videoId": "ujHXnlSVheI",
  "title": "Claude Code Tutorial: Beginner to Advanced in 20 Minutes",
  "url": "https://www.youtube.com/watch?v=ujHXnlSVheI",
  "channelId": "UC3i3qKQ5aR_guegQj5bhOMw",
  "channelTitle": "Zinho Automates",
  "channelHandle": "@zinhoautomates",
  "channelUrl": "https://www.youtube.com/channel/UC3i3qKQ5aR_guegQj5bhOMw",
  "lengthText": "19:24",
  "viewCountText": "48,427 views",
  "publishedTimeText": "5 days ago",
  "hasCaptions": true,
  "thumbnails": [{ "url": "https://i.ytimg.com/...", "width": 1280, "height": 720 }]
}
```

**Video result with transcript attached (`downloadSubtitles: true`):**

```json
{
  "source": "channel",
  "input": "https://www.youtube.com/@TED",
  "order": 0,
  "type": "video",
  "videoId": "aDGaUWkioqk",
  "title": "...",
  "channelTitle": "TED",
  "channelUrl": "https://www.youtube.com/channel/UCAuUUnT6oDeKwE6v1NGQxug",
  "lengthText": "1:32",
  "transcript": [
    { "text": "What does a warming planet mean for the foods you love?", "start": 0.12, "duration": 3.4 },
    { "text": "...", "start": 3.6, "duration": 2.9 }
  ],
  "transcriptLanguage": "en"
}
```

**Channel result (`searchType: "channel"`):**

```json
{
  "source": "search",
  "input": "TED",
  "order": 0,
  "type": "channel",
  "channelId": "UCAuUUnT6oDeKwE6v1NGQxug",
  "title": "TED",
  "handle": "@TED",
  "url": "https://www.youtube.com/@TED",
  "description": "The TED Talks channel features the best talks and performances from the TED Conference...",
  "subscriberCount": "27.4M subscribers",
  "verified": true,
  "rssUrl": "https://www.youtube.com/feeds/videos.xml?channel_id=UCAuUUnT6oDeKwE6v1NGQxug",
  "thumbnails": [{ "url": "...", "width": 88, "height": 88 }]
}
```

**Transcript failure attached to its video (free of charge):**

```json
{
  "source": "channel",
  "input": "https://www.youtube.com/@SomeChannel",
  "order": 4,
  "type": "video",
  "videoId": "BADID000000",
  "title": "...",
  "transcript_error": { "status": 404, "detail": "No transcript available" }
}
```

**Discovery-layer failures** (bad URL, unreachable channel, dead playlist) land in a separate **`errors` dataset** — never billed.

***

### 🎯 Use Cases

- **AI / LLM training data** — bulk-collect transcripts from any niche.
- **RAG knowledge bases** — index educational channels, lectures, podcasts.
- **Content research & SEO** — extract topics, keywords, and themes from competitor channels.
- **Brand monitoring** — pipe transcripts into sentiment / NLP analysis.
- **Market & competitive analysis** — track entire channels or topics over time.
- **Podcast & lecture transcription** — turn long-form video libraries into searchable text.
- **Repurpose video into content** — blog posts, newsletters, X/LinkedIn threads, Shorts captions, summaries.
- **Academic research** — corpus building for linguistic, media, or political analysis.
- **Accessibility** — generate plain-text alternatives for video content.

***

### 🌐 Supported Input Formats

| Mode | Examples |
|---|---|
| Video URL | `https://www.youtube.com/watch?v=dQw4w9WgXcQ`<br>`https://youtu.be/dQw4w9WgXcQ`<br>`https://www.youtube.com/shorts/dQw4w9WgXcQ`<br>`https://www.youtube.com/embed/dQw4w9WgXcQ`<br>`dQw4w9WgXcQ` |
| Channel URL | `https://www.youtube.com/channel/UCAuUUnT6oDeKwE6v1NGQxug`<br>`https://www.youtube.com/@TED`<br>`https://www.youtube.com/c/TED`<br>`https://www.youtube.com/user/TEDtalksDirector` |
| Playlist URL | `https://www.youtube.com/playlist?list=PL…`<br>Any URL containing `?list=…`<br>Bare playlist IDs starting with `PL`, `UU`, `LL`, `FL`, `OL`, `RD` |
| Search query | Any free-text string in `searchQueries` |

***

### 🔌 Integrations

Run from anywhere via Apify's native integrations:

- 🐍 **Python** — `apify-client` SDK
- 🟢 **Node.js / JavaScript** — `apify-client` SDK
- 🔗 **REST API** — POST to `/v2/acts/.../runs` and read the Dataset
- 🧩 **n8n** — official Apify nodes
- ⚙️ **Make (Integromat)** — official Apify modules
- ⚡ **Zapier** — official Apify Zap actions
- 🪝 **Webhooks** — fire on run finish, success, or failure
- 🤖 **MCP / Claude Desktop / Cursor** — expose this actor as a tool to your AI agents via the Apify MCP server
- 🧱 **LangChain / LlamaIndex** — drop the Dataset directly into a RAG pipeline

***

### ❓ FAQ

**Can I mix search queries with channel and playlist URLs in one run?**
Yes — that's the whole point. Drop any combination into `searchQueries` and `startUrls`; we auto-detect each URL and dispatch it correctly.

**How does pricing work?**
Three pay-per-event meters, all priced at **$0.005**: `search` (per search request — returns up to ~20 results per call), `videos-page` (per page when listing videos from a channel or playlist — up to ~100 videos per call), and `transcript-fetched` (per successful transcript). Failed requests and bad URLs are **free**. No actor-start fee, no subscription, no monthly minimum. See the [Pricing](#-pricing) section for typical run costs.

**Do I need a YouTube API key?**
No. Bring URLs or search terms; we handle everything.

**How fast is it?**
Median upstream latency 49 ms (TranscriptAPI.com), so end-to-end you typically see results in well under 500 ms per call. Long channels and playlists are paginated automatically.

**Which transcript formats are supported?**
JSON (timed segments), plain text, **SRT**, and **WebVTT**. Pick via `subtitlesFormat`.

**What if a video has no captions?**
The transcript fetch attaches a `transcript_error` field to the same item — the discovery data is still delivered, and the failed transcript is **not billed**.

**Can I scrape only the latest N videos from a channel?**
Yes. Set `maxResults` to your cap. When `maxResults ≤ 15`, we use a richer endpoint that gives exact publish dates and full descriptions.

**Can I run an unattended schedule?**
Yes — combine this actor with Apify's built-in schedules and webhooks. Many users poll new uploads daily.

**Is this legal?**
This actor only reads metadata and captions that YouTube makes public to any visitor. It does not bypass age gates, scrape signed-in surfaces, or collect personal user data. Use the output in compliance with copyright law, YouTube ToS for your jurisdiction, GDPR / CCPA, and any licensing your downstream product requires.

**Where do results go?**
Default Apify Dataset. Discovery failures go to a separate `errors` named dataset. Both export to JSON, CSV, Excel, XML, HTML, or RSS.

**What if I need higher volume / parallelism?**
Run the actor multiple times in parallel — Apify schedules and bills each run independently. Reach out via the Issues tab for specific scale needs.

***

### 🛡️ Legal & Ethical Scraping

This actor only accesses metadata and captions that YouTube makes public to any visitor of a video, channel, or playlist page. It does **not**:

- bypass age restrictions, private uploads, or unlisted-link gates,
- collect personally identifiable user data,
- scrape comments, watch history, or any signed-in surface.

You are responsible for using the output in compliance with copyright law, YouTube's Terms of Service for your jurisdiction, GDPR / CCPA, and any platform-specific licensing your downstream product requires.

***

### 🐛 Support

- 🐞 **Issues / feature requests** — use the **Issues** tab at the top of this page.
- 📬 **Response time** — within 1 business day.
- 💬 **Need a custom contract?** Reach out via the Issues tab.

# Actor input Schema

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

Free-text YouTube searches. Each query is fetched separately and capped by 'maxResults'. Use 'searchType' to pick whether each query returns videos or channels.

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

Paste any mix of video URLs (watch, youtu.be, shorts, embed, bare 11-char ID), channel URLs (/channel/UC…, /@handle, /c/…, /user/…), or playlist URLs (?list=PL…). We auto-detect each.

## `searchType` (type: `string`):

What 'searchQueries' should return. 'video' = video results. 'channel' = channel results.

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

Per-search-query, per-channel, and per-playlist cap. 20 is a safe default; raise for bulk runs.

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

When true, fetches a transcript for every video discovered (search, channel, playlist, or direct URL) and merges it onto the same item. Each successful transcript is billed at the 'transcript-fetched' rate.

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

Output format for transcripts. JSON = list of timed segments. Text = single concatenated string. SRT / VTT = standard subtitle file formats.

## `includeTimestamps` (type: `boolean`):

When 'subtitlesFormat' is 'json' or 'text', include per-segment timestamps. Always on for SRT and VTT.

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

Caption language preference. Most videos return English by default; transcripts come back in the video's primary published caption language.

## `includeVideoMetadata` (type: `boolean`):

When fetching transcripts, also include video title, channel, and thumbnail.

## `saveSubsToKVS` (type: `boolean`):

When true, each transcript is also written to the default Key-Value Store as 'transcript-<videoId>' (raw payload). Useful for piping transcripts to downstream actors or storing them separately from the dataset.

## Actor input object example

```json
{
  "searchQueries": [
    "claude code tutorial"
  ],
  "startUrls": [
    "https://www.youtube.com/@TED",
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "searchType": "video",
  "maxResults": 20,
  "downloadSubtitles": false,
  "subtitlesFormat": "json",
  "includeTimestamps": true,
  "subtitlesLanguage": "en",
  "includeVideoMetadata": true,
  "saveSubsToKVS": false
}
```

# Actor output Schema

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

Default dataset — one item per video or channel result.

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

Named dataset for discovery-layer failures. Empty when there were none. Never billed.

# 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 = {
    "searchQueries": [
        "claude code tutorial"
    ],
    "startUrls": [
        "https://www.youtube.com/@TED",
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("zeropointstudio/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 = {
    "searchQueries": ["claude code tutorial"],
    "startUrls": [
        "https://www.youtube.com/@TED",
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("zeropointstudio/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 '{
  "searchQueries": [
    "claude code tutorial"
  ],
  "startUrls": [
    "https://www.youtube.com/@TED",
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ]
}' |
apify call zeropointstudio/youtube-scraper --silent --output-dataset

```

## MCP server setup

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