# YouTube Transcript Scraper - Channels, Playlists, Bulk (`sauliusautomatesit/youtube-transcript-scraper`) Actor

Extract YouTube transcripts in bulk - paste video, channel, or playlist URLs, or search queries. Get plain text, SRT, VTT, or timed segments plus video metadata. Only delivered transcripts are charged. No cookies, no API key.

- **URL**: https://apify.com/sauliusautomatesit/youtube-transcript-scraper.md
- **Developed by:** [Saulius Saulenas](https://apify.com/sauliusautomatesit) (community)
- **Categories:** Videos, AI, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.13 / 1,000 transcripts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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 Transcript Scraper — Videos, Channels, Playlists & Search

Extract YouTube transcripts **in bulk**: paste video URLs, channel URLs, playlist URLs, or plain
search queries, and get clean transcripts with video metadata — as plain text, timed segments,
SRT, or WebVTT.

Built for AI/RAG pipelines, content repurposing, media monitoring, and research. No cookies, no
login, no YouTube API key.

### Why this scraper

- **Bulk-first** — channels, playlists, and search queries expand to their videos automatically.
  One input handles all formats, mixed freely.
- **Reliable on cloud infrastructure** — YouTube aggressively bot-checks datacenter IPs. This
  actor uses a smart proxy ladder with automatic retries; in our benchmark it extracted
  **200/200 transcripts from a channel in under 2 minutes**.
- **You only pay for delivered transcripts** — videos without captions, unavailable videos, and
  fetch failures are **never charged**. Diagnostic rows tell you exactly what happened.
- **4 output formats** — plain text for LLMs, timed segments for analysis, SRT/VTT for subtitles.
- **Language control** — priority list (e.g. `["de", "en"]`), manual-vs-auto-generated preference,
  strict or fallback matching. Every result shows all available caption languages.

### Input

```json
{
    "videoUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://youtu.be/jNQXAC9IVRw",
        "https://www.youtube.com/@mkbhd",
        "https://www.youtube.com/playlist?list=PLFgquLnL59alCl_2TQvOiD5Vgm1hCaGSI",
        "machine learning tutorial"
    ],
    "languages": ["en"],
    "transcriptFormat": "text",
    "maxVideosPerSource": 200
}
```

| Field | Default | Description |
|---|---|---|
| `videoUrls` | — | Video URLs/IDs, channel URLs (`@handle` or `/channel/UC…`), playlist URLs, or search queries |
| `languages` | `["en"]` | Preferred transcript languages, in priority order |
| `transcriptFormat` | `text` | `text`, `segments`, `srt`, or `vtt` |
| `preferAutoGenerated` | `false` | Prefer auto-generated (ASR) captions over manual ones |
| `fallbackToAnyLanguage` | `true` | Use the best available track if no preferred language exists |
| `includeFailures` | `true` | Emit uncharged diagnostic rows for videos without transcripts |
| `maxVideosPerSource` | `200` | Cap per channel/playlist/search |
| `maxResults` | `100000` | Global cap per run (spend guard) |

### Output

One dataset item per video:

```json
{
    "type": "transcript",
    "videoId": "dQw4w9WgXcQ",
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "title": "Rick Astley - Never Gonna Give You Up (Official Video)",
    "channelName": "Rick Astley",
    "channelId": "UCuAXFkgsw1L7xaCfnd5JJOw",
    "lengthSeconds": 213,
    "viewCount": 1697651560,
    "language": "en",
    "languageName": "English",
    "isAutoGenerated": false,
    "transcriptFormat": "text",
    "transcript": "We're no strangers to love. You know the rules and so do I…",
    "segmentCount": 61,
    "wordCount": 488,
    "availableLanguages": ["en", "en (auto)", "de-DE", "ja", "pt-BR", "es-419"],
    "sourceInput": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "scrapedAt": "2026-08-11T21:35:20.991Z"
}
```

With `transcriptFormat: "segments"`, `transcript` is an array of
`{ "text": "…", "start": 1.36, "duration": 1.68 }` objects. With `srt`/`vtt` it contains a
ready-to-save subtitle file.

Videos that can't produce a transcript get a `type: "failure"` row (free of charge) with an
`error` code such as `NO_CAPTIONS`, `NO_MATCHING_LANGUAGE`, or `LOGIN_REQUIRED`, so your pipeline
can handle them explicitly.

### Pricing

Pay per event — **$2.50 per 1,000 transcripts** ($0.0025 per transcript) plus a negligible
actor-start fee ($0.00005 per GB of actor memory). Platform usage (compute, proxies, storage) is
**included** — the event price is all you pay.

- Videos **without captions cost $0** — you pay only for transcripts actually delivered.
- Set **Maximum total charge** on the run to hard-cap spending; the actor stops cleanly at the cap.

| Run | You pay |
|---|---|
| 100-video playlist, 92 have captions | $0.23 |
| 1,000-video channel backfill | ~$2.50 |
| 20,000-video corpus | ~$50.00 |

### Use cases

- **AI & RAG pipelines** — turn channels into LLM-ready corpora (works great from n8n, Make,
  LangChain, or the Apify API).
- **Content repurposing** — transcripts for blogs, newsletters, and social clips.
- **Media & brand monitoring** — schedule runs on channels and search queries.
- **Research** — collect interview/lecture transcripts with timestamps for citation.
- **Subtitles** — batch-export SRT/VTT for re-upload or translation workflows.

### Scheduling & API

Run it on a schedule (e.g. daily on a channel URL) from the **Schedules** tab, or call it from
your code via the [Apify API](https://docs.apify.com/api/v2) — see the **API** button on this
page for ready-made snippets. Results stream to the dataset as they're extracted, so you can
consume partial results while a large run is still going.

### Limitations

- Transcripts come from YouTube caption tracks (manual or auto-generated). Videos with captions
  disabled can't be transcribed — they're reported as `NO_CAPTIONS` and not charged.
- Live streams in progress and age-restricted videos are generally not extractable.
- Channel expansion returns the channel's regular uploads (newest first), up to
  `maxVideosPerSource`.

### FAQ

**Do I need a YouTube API key or cookies?** No. The actor uses YouTube's public endpoints.

**What languages are supported?** Anything YouTube has captions for. Set `languages` to your
priority list; `availableLanguages` on every item shows what exists.

**Can I get word-level timestamps?** Segment-level timestamps (a few seconds each) via
`segments`, `srt`, or `vtt` formats.

**What happens on a video that's private/deleted?** A free `failure` row with the error code —
never a charge.

# Actor input Schema

## `videoUrls` (type: `array`):

YouTube video URLs or IDs, channel URLs (`youtube.com/@handle` or `/channel/UC...`), playlist URLs, or plain search queries. Channels, playlists, and searches are expanded into their videos automatically.

## `languages` (type: `array`):

Language codes in priority order (e.g. `en`, `es`, `pt-BR`). The first available match is used.

## `transcriptFormat` (type: `string`):

`text` = plain text; `segments` = array of {text, start, duration}; `srt` / `vtt` = subtitle file content.

## `preferAutoGenerated` (type: `boolean`):

By default manually-created captions win over auto-generated (ASR) ones in the same language. Enable to prefer ASR.

## `fallbackToAnyLanguage` (type: `boolean`):

If no preferred language is available, use the best available track instead of skipping the video. The `language` field always shows what you got.

## `includeFailures` (type: `boolean`):

Push a diagnostic row (type=`failure`) for videos without captions or that could not be fetched. Failure rows are never charged.

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

Cap on how many videos each channel, playlist, or search expands to (newest first for channels).

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

Hard cap on videos processed in this run — a spend guard for large inputs.

## `concurrency` (type: `integer`):

Videos processed in parallel.

## `proxyStrategy` (type: `string`):

`auto` (recommended): try datacenter first, fall back to residential on YouTube bot-checks. Forcing a single tier is mainly for debugging.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/jNQXAC9IVRw"
  ],
  "languages": [
    "en"
  ],
  "transcriptFormat": "text",
  "preferAutoGenerated": false,
  "fallbackToAnyLanguage": true,
  "includeFailures": true,
  "maxVideosPerSource": 200,
  "maxResults": 100000,
  "concurrency": 10,
  "proxyStrategy": "auto"
}
```

# Actor output Schema

## `transcripts` (type: `string`):

One item per video (`type: "transcript"`) with the transcript rendered in your chosen format — plain text, SRT, VTT or timed segments — plus the caption language, whether it was auto-generated, the list of available languages, word and segment counts, and video metadata (title, channel name and ID, length, view count, URL). Videos that could not be transcribed appear as `type: "failure"` items carrying a machine-readable `error` reason, and are never charged.

## `summary` (type: `string`):

A JSON report of the run: how many videos were planned, how many transcripts were extracted, and how many videos had no captions, had no caption in a requested language, stayed blocked after retries, or failed for another reason — plus whether the run stopped early at your maximum charge limit.

# 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 = {
    "videoUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://youtu.be/jNQXAC9IVRw"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sauliusautomatesit/youtube-transcript-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 = { "videoUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://youtu.be/jNQXAC9IVRw",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("sauliusautomatesit/youtube-transcript-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 '{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/jNQXAC9IVRw"
  ]
}' |
apify call sauliusautomatesit/youtube-transcript-scraper --silent --output-dataset

```

## MCP server setup

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