# YouTube Transcript Scraper (`parsebird/youtube-transcript-scraper`) Actor

Get YouTube video transcripts and subtitles at scale. Extract plain text, timestamped segments, SRT and VTT, plus title, channel, views, and keywords. Optional Whisper AI fallback for caption-less videos.

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

## Pricing

from $4.00 / 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/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 Transcript Scraper

**YouTube Transcript Scraper** extracts the transcript of any public **YouTube** video or **Short** — as plain text, timestamped segments, and ready-to-use **SRT** and **VTT** subtitle files — together with the video's title, channel, view count, duration, and keywords. When a video has no captions at all, an optional **OpenAI Whisper** (faster-whisper) fallback transcribes the audio inside the Actor.

<table><tr>
<td style="border-left:4px solid #FF0000;padding:12px 16px;font-weight:600">
Paste YouTube video, Shorts, or youtu.be URLs and get a clean transcript per video — plain text for LLMs, timestamped JSON segments, SRT and VTT subtitle strings, plus channel and view metadata — with a Whisper AI fallback for caption-less videos.
</td>
</tr></table>

##### Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this Actor.

```
Actor: parsebird/youtube-transcript-scraper (Apify). Extracts YouTube video transcripts + subtitles + metadata. Call it with ApifyClient.
Input:
  {
    "startUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "https://youtu.be/VIDEO_ID", "https://www.youtube.com/shorts/VIDEO_ID"],
    "language": "",              // "" = original caption track; else ISO code: en, de, es, pt, fr, ja (auto-translated if the exact track is missing)
    "whisperFallback": false,    // true -> transcribe caption-less videos with Whisper (premium event)
    "whisperMaxMinutes": 30,     // per-video cap for the Whisper fallback
    "maxItems": 100,             // hard cap on billed transcript rows
    "maxConcurrency": 10,
    "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
  }
startUrls is required. Accepts watch URLs, youtu.be, Shorts, embed URLs, and bare 11-char video IDs.
Output: one row per video — videoId, title, author, channelId, lengthSeconds, viewCount, keywords[], shortDescription, thumbnail,
transcript[{text,startMs,endMs,startTimeText}], transcript_only_text, transcript_srt, transcript_vtt, transcriptSource
(captions | auto-captions | whisper), language, isTranslated, transcriptError, transcriptSkipped.
Pricing: pay-per-event, tiered — ~$5 / 1,000 transcripts; Whisper fallback is a separate premium event.
API docs: https://apify.com/parsebird/youtube-transcript-scraper/api   Token: https://console.apify.com/account/integrations
```

### What does YouTube Transcript Scraper do?

This Actor is a **YouTube transcript API** and **subtitle downloader**. Give it video URLs and it returns, for each one:

- 📝 **Plain-text transcript** (`transcript_only_text`) — one clean string, ready to drop into an LLM prompt, a summary, or a search index.
- ⏱️ **Timestamped segments** (`transcript`) — `text`, `startMs`, `endMs`, and a human `startTimeText` (`0:18`, `1:02:03`) for captions, chapters, or clip-finding.
- 🎬 **SRT and VTT files** (`transcript_srt`, `transcript_vtt`) — complete subtitle files as strings, save and use directly.
- 🌍 **Any caption language** — request `en`, `de`, `es`, `pt`, `ja`, … and get that track, or leave `language` empty for the video's original. Missing tracks are filled with **YouTube auto-translation**.
- 📊 **Video metadata for free** — `title`, `author`, `channelId`, `viewCount`, `lengthSeconds`, `keywords`, `shortDescription`, and `thumbnail`.
- 🧠 **Whisper AI fallback** (opt-in) — for videos with **no captions**, download the audio and transcribe it with **OpenAI Whisper** (`faster-whisper`) inside the container. Billed separately, only when it produces text.
- 🔁 **Batch + resumable** — thousands of URLs per run, parallel fetching, and automatic resume if a long run is interrupted.

#### Supported input URL formats

| Format | Example |
|--------|---------|
| Standard video URL | `https://www.youtube.com/watch?v=dQw4w9WgXcQ` |
| Short link | `https://youtu.be/dQw4w9WgXcQ` |
| Shorts | `https://www.youtube.com/shorts/dQw4w9WgXcQ` |
| Embed URL | `https://www.youtube.com/embed/dQw4w9WgXcQ` |
| Bare video ID | `dQw4w9WgXcQ` |

**Not supported:** private, members-only, and age-gated videos, and live streams still in progress. To transcribe a whole channel, first list its videos with a YouTube channel scraper and feed the URLs here.

### Input parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `startUrls` | array | **Yes** | — | YouTube video / Shorts URLs or bare video IDs. |
| `language` | string | No | original | Caption language code to return (`en`, `de`, …). Empty = the video's original track. Auto-translated if the exact track is missing. |
| `whisperFallback` | boolean | No | `false` | Transcribe caption-less videos with Whisper AI. Premium event. |
| `whisperMaxMinutes` | integer | No | `30` | Per-video cap (1–60) for the Whisper fallback. |
| `maxItems` | integer | No | `100` | Hard cap on billed transcript rows per run. |
| `maxConcurrency` | integer | No | `10` | Parallel video fetches (1–50). Whisper always runs one at a time. |
| `cookies` | string (secret) | No | — | Netscape `cookies.txt` for the "confirm you're not a bot" gate. Does not unlock private videos. |
| `proxyConfiguration` | object | No | Residential | Proxy for reaching YouTube. Residential strongly recommended. |

### Output example

```json
{
    "videoId": "dQw4w9WgXcQ",
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "title": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)",
    "author": "Rick Astley",
    "channelId": "UCuAXFkgsw1L7xaCfnd5JJOw",
    "lengthSeconds": "213",
    "viewCount": "1699540216",
    "keywords": ["rick astley", "Never Gonna Give You Up", "nggyu"],
    "shortDescription": "The official video for “Never Gonna Give You Up” by Rick Astley…",
    "thumbnail": { "thumbnails": [{ "url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg", "width": 168, "height": 94 }] },
    "language": "en",
    "isTranslated": false,
    "transcriptSource": "captions",
    "transcript": [
        { "text": "[♪♪♪]", "startMs": "1360", "endMs": "3040", "startTimeText": "0:01" },
        { "text": "♪ We're no strangers to love ♪", "startMs": "18800", "endMs": "22140", "startTimeText": "0:18" }
    ],
    "transcript_only_text": "[♪♪♪] ♪ We're no strangers to love ♪ ♪ You know the rules and so do I ♪ …",
    "transcript_srt": "1\n00:00:01,360 --> 00:00:03,040\n[♪♪♪]\n…",
    "transcript_vtt": "WEBVTT\n\n00:00:01.360 --> 00:00:03.040\n[♪♪♪]\n…",
    "wordCount": 412,
    "transcriptSkipped": false,
    "transcriptError": null
}
```

#### Key output fields

| Field | Meaning |
|-------|---------|
| `transcript[]` | Timestamped segments: `text`, `startMs`, `endMs`, `startTimeText`. |
| `transcript_only_text` | The whole transcript as one plain string — LLM-ready. |
| `transcript_srt` / `transcript_vtt` | Complete subtitle files as strings — save and use directly. |
| `transcriptSource` | Which step produced it: `captions` (human), `auto-captions` (YouTube ASR), or `whisper`. |
| `language` / `isTranslated` | Caption language returned, and whether it came from auto-translation. |
| `videoId`, `title`, `author`, `channelId` | Video identity. |
| `viewCount`, `lengthSeconds`, `keywords`, `shortDescription`, `thumbnail` | Metadata that rides along free. |
| `wordCount` | Word count of the transcript. |
| `transcriptError` / `transcriptSkipped` | Set only when every source failed for a video. Those rows are not billed. |

### How to get a YouTube transcript

1. Open the Actor and click **Try for free**.
2. Paste one or more video URLs into **YouTube video URLs**.
3. (Optional) Set **Caption language** to a code like `de` or `es`, or leave it empty for the original.
4. (Optional) Turn on **Whisper AI fallback** to transcribe videos that have no captions.
5. Click **Start**. When the run finishes, open **Output** / **Storage** and download the results as JSON, CSV, Excel, or copy the `transcript_srt` / `transcript_vtt` strings straight into a `.srt` / `.vtt` file.

You can also [schedule](https://docs.apify.com/platform/schedules) the Actor and call it from your own code via the [API](https://apify.com/parsebird/youtube-transcript-scraper/api).

### Use cases

- **LLM & RAG pipelines** — feed `transcript_only_text` into summarization, Q\&A, embeddings, or fine-tuning datasets.
- **Subtitles & localization** — pull SRT/VTT in the original language or an auto-translated one.
- **Content repurposing** — turn videos into blog posts, newsletters, show notes, and social clips.
- **Research & monitoring** — collect transcripts across a topic, creator, or competitor for analysis.
- **Accessibility** — add transcripts to a media library or LMS.
- **Search** — index what was actually said in a video library, with timestamps back to the moment.

### How a run works

1. Each URL is resolved to its 11-character video ID (watch, `youtu.be`, Shorts, embed, or bare ID).
2. The video's metadata and caption-track list are fetched with browser-grade TLS through the proxy.
3. The caption track for your `language` is selected — human captions first, then YouTube's auto-generated track; auto-translation is applied when the exact track is missing.
4. The timedtext track is fetched and normalised to timestamped JSON, then rendered to SRT and VTT.
5. If there are no captions and `whisperFallback` is on, the audio is downloaded (up to `whisperMaxMinutes`), extracted with ffmpeg, and transcribed with **OpenAI Whisper** (`faster-whisper`).
6. One row per video is pushed — transcript, formats, and metadata together. Videos where every source fails get a row with `transcriptError` and are not billed.

### Using the Actor via API

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run_input = {
    "startUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/shorts/abcdefghijk",
    ],
    "language": "en",
    "maxItems": 50,
}

run = client.actor("parsebird/youtube-transcript-scraper").call(run_input=run_input)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], "—", item["wordCount"], "words —", item["transcriptSource"])
    print(item["transcript_only_text"][:300])
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });

const input = {
    startUrls: ['https://youtu.be/dQw4w9WgXcQ'],
    whisperFallback: true,
};

const run = await client.actor('parsebird/youtube-transcript-scraper').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].transcript_srt);
```

The Actor runs on the [Apify platform](https://apify.com), so you also get scheduling, a full REST API, webhooks, and native integrations with Make, Zapier, Google Sheets, Slack, and more. Results export as JSON, CSV, Excel, XML, or RSS.

### Pricing

This Actor uses the **pay-per-event** pricing model, **tiered by your Apify plan**.

| Event | What it is | Free | Bronze | Silver | Gold |
|-------|-----------|------|--------|--------|------|
| `transcript` | One video row: transcript text, timestamped segments, SRT, VTT, and video metadata. | $0.005 | $0.0045 | $0.0045 | $0.004 |
| `whisper-transcript` | Added only when a caption-less video is transcribed by the Whisper AI fallback. | $0.15 | $0.125 | $0.10 | $0.075 |

A tiny [platform start fee](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) (~$0.05 per 1,000 runs) also applies. Scraping **1,000 caption transcripts costs about $5.00** on the Free plan. A video transcribed by Whisper costs `transcript` + `whisper-transcript` (about $0.155 on Free). **Videos where every caption source fails are not billed.**

### FAQ

**Do I need a YouTube API key?**
No. You only need an Apify account.

**Why do I need a proxy?**
YouTube blocks most datacenter IPs. Residential proxy (the default) is strongly recommended, especially for larger runs.

**What if a video has no captions?**
Without `whisperFallback`, the row has the video's metadata and a `transcriptError`. Turn on `whisperFallback` to transcribe the audio with Whisper AI (billed as the premium event, only when it produces text).

**Can I get the transcript in another language?**
Set `language` to an ISO code (`de`, `es`, `fr`, `ja`, …). If YouTube doesn't have that exact track, it is auto-translated and `isTranslated` is `true`.

**Which `transcriptSource` values are there?**
`captions` (human-made captions), `auto-captions` (YouTube's automatic speech recognition), and `whisper` (the in-container fallback).

**How does `maxItems` work?**
It caps the number of billed transcript rows. Videos that fail every source are not counted and not billed.

**Can I transcribe a whole channel?**
Scrape the channel's video list with a YouTube channel scraper first, then feed those URLs here.

**Can I schedule recurring runs?**
Yes. Use Apify's [scheduler](https://docs.apify.com/platform/schedules) to transcribe new uploads on any interval and route them onward with a webhook or integration.

**Something's not working — where do I report it?**
Open the **Issues** tab on the Actor page with the video URL and run ID.

### Related Actors

- [Video & Audio Transcriber](https://apify.com/parsebird/video-audio-transcriber) — transcribe TikTok, Instagram, podcasts, and 1,800+ other sites with Whisper.
- [Kick Video Downloader](https://apify.com/parsebird/kick-video-downloader) — download Kick.com VODs and clips.
- [YouTube Live Chat Scraper](https://apify.com/parsebird/youtube-live-chat-scraper) — replay chat from YouTube live streams.
- [YouTube Community Posts Scraper](https://apify.com/parsebird/youtube-community-posts-scraper) — community-tab posts, polls, and comments.
- Browse the full [ParseBird publisher page](https://apify.com/parsebird) for more.

### Legal and compliance

This Actor accesses only publicly available YouTube pages and caption data. It does not log in, and it does not bypass authentication for private, members-only, or age-restricted videos. You are responsible for using transcripts in accordance with YouTube's Terms of Service, copyright law, and — where personal data is involved — applicable privacy laws such as the GDPR and CCPA. See Apify's [guide to the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) for background.

# Actor input Schema

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

YouTube video or Shorts URLs. Standard (youtube.com/watch?v=ID), short (youtu.be/ID), Shorts (youtube.com/shorts/ID), embed, and bare 11-character video IDs are all accepted. Private, members-only, age-gated videos and in-progress live streams are not supported.

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

Hard cap on the number of transcript rows produced and billed per run.

## `language` (type: `string`):

Caption language code to return, e.g. en, de, es, pt, fr, ja. Leave empty for the video's original caption track. If the exact track is missing, YouTube auto-translation is applied.

## `whisperFallback` (type: `boolean`):

When a video has no usable captions, download its audio and transcribe it with OpenAI Whisper (faster-whisper) inside the Actor. Billed as a separate premium event, only when it actually produces a transcript.

## `whisperMaxMinutes` (type: `integer`):

Per-video cap for the Whisper fallback. Longer videos are transcribed only up to this many minutes.

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

How many videos to fetch in parallel. Whisper transcription always runs one video at a time.

## `cookies` (type: `string`):

Optional Netscape-format cookies.txt content. Helps with YouTube's "sign in to confirm you're not a bot" gate on some IPs. Does not unlock private or members-only videos.

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

Proxy for reaching YouTube. Residential is strongly recommended — YouTube blocks most datacenter IPs.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "maxItems": 100,
  "language": "",
  "whisperFallback": false,
  "whisperMaxMinutes": 30,
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "startUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ],
    "maxItems": 100,
    "language": "",
    "whisperMaxMinutes": 30,
    "maxConcurrency": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/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 = {
    "startUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
    "maxItems": 100,
    "language": "",
    "whisperMaxMinutes": 30,
    "maxConcurrency": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/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 '{
  "startUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "maxItems": 100,
  "language": "",
  "whisperMaxMinutes": 30,
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call parsebird/youtube-transcript-scraper --silent --output-dataset

```

## MCP server setup

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