# Youtube Transcript Scraper (`crawlerbros/youtube-transcript-scraper`) Actor

Extract transcripts and captions from YouTube videos with language selection support. Returns timestamped segments, full concatenated text, and basic video metadata.

- **URL**: https://apify.com/crawlerbros/youtube-transcript-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Videos, Social media, Developer tools
- **Stats:** 92 total users, 42 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

Extract transcripts and captions from any public YouTube video. Get timestamped segments, full plain-text transcripts, language metadata, and core video info — ready for AI pipelines, content analysis, summarization, translation, and research.

When a video has no captions at all (uploader disabled them, or it's music-only with no on-screen text), an optional **Whisper AI fallback** can transcribe the audio directly so you still get a usable transcript.

### What you get

For each video the scraper returns:

| Field | Description |
| --- | --- |
| `video_id` | YouTube 11-character video ID |
| `title` | Video title |
| `channel_name` | Channel display name |
| `channel_id` | Channel ID (when available) |
| `duration_seconds` | Video duration in seconds (when available) |
| `views` | View count (when available) |
| `published_date` | Publish date in `YYYY-MM-DD` (when available) |
| `thumbnail` | Thumbnail URL |
| `transcript_language` | Language code of the extracted transcript (e.g. `en`, `es`, `ko`) |
| `transcript_language_name` | Full language name |
| `is_auto_generated` | `true` if the transcript is YouTube's auto-caption, `false` for manually uploaded captions or Whisper output |
| `transcript_source` | `library` / `innertube` / `playwright_dom` / `whisper` — tells you which path produced the transcript |
| `language_probability` | Whisper's language-detection confidence (only set when `transcript_source=whisper`) |
| `available_languages` | Array of every transcript language available for the video |
| `segments` | Timestamped segments — `start`, `dur`, `text` |
| `segment_count` | Number of segments returned |
| `full_text` | Complete transcript joined into a single string |
| `success` | `true` when a transcript was extracted, `false` otherwise |
| `error` | Reason text when `success=false` |
| `inputUrl` | The URL you submitted |
| `scrapedAt` | ISO 8601 UTC timestamp |

Empty fields are dropped from each record so the dataset stays clean.

### Input

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `videoUrls` | Array | **required** | YouTube watch URLs, `youtu.be` short links, Shorts URLs, embed URLs, or plain 11-char video IDs. |
| `language` | String | `""` | Preferred language code (`en`, `es`, `fr`, `de`, `ja`, `ko`, …). Empty = best available. |
| `includeAutoGenerated` | Boolean | `true` | Include YouTube auto-captions when manual ones aren't available. |
| `useWhisper` | Boolean | `false` | Fall back to local Whisper transcription when YouTube has no transcript. Adds ~30-180 s per video. |
| `whisperModel` | Enum | `base` | `tiny` (fastest), `base` (balanced), `small` (most accurate). Pick `small` for music or noisy audio. |

#### Supported URL formats

- `https://www.youtube.com/watch?v=dQw4w9WgXcQ`
- `https://youtu.be/dQw4w9WgXcQ`
- `https://www.youtube.com/shorts/VIDEO_ID`
- `https://www.youtube.com/embed/VIDEO_ID`
- Plain 11-char ID: `dQw4w9WgXcQ`

#### Example input — multiple videos, English preferred

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/9bZkp7q19f0",
    "https://www.youtube.com/shorts/abc123XYZ45"
  ],
  "language": "en",
  "includeAutoGenerated": true
}
```

#### Example input — Whisper fallback for transcripts-disabled videos

```json
{
  "videoUrls": ["https://www.youtube.com/watch?v=XqZsoesa55w"],
  "useWhisper": true,
  "whisperModel": "small"
}
```

### Example output

```json
{
  "video_id": "dQw4w9WgXcQ",
  "title": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)",
  "channel_name": "Rick Astley",
  "channel_id": "UCuAXFkgsw1L7xaCfnd5JJOw",
  "duration_seconds": 213,
  "views": 1769190465,
  "published_date": "2009-10-24",
  "thumbnail": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
  "transcript_language": "en",
  "transcript_language_name": "English",
  "is_auto_generated": false,
  "transcript_source": "library",
  "available_languages": [
    { "code": "en", "name": "English", "is_auto_generated": false },
    { "code": "es-419", "name": "Spanish (Latin America)", "is_auto_generated": false }
  ],
  "segments": [
    { "start": "1.360", "dur": "1.680", "text": "[♪♪♪]" },
    { "start": "18.640", "dur": "3.240", "text": "We're no strangers to love" }
  ],
  "segment_count": 61,
  "full_text": "[♪♪♪] We're no strangers to love You know the rules and so do I ...",
  "success": true,
  "inputUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "scrapedAt": "2026-05-05T13:42:18Z"
}
```

### Use cases

- **AI training data** — Build text corpora from YouTube content for LLM fine-tuning or RAG pipelines.
- **Content repurposing** — Turn long videos into blog posts, summaries, or social copy.
- **Research and analysis** — Pull spoken content from lectures, interviews, podcasts, and documentaries.
- **Subtitles and accessibility** — Retrieve captions for translation or accessibility workflows.
- **SEO and keyword research** — Analyse spoken keywords and topics across YouTube content.
- **Competitive intelligence** — Monitor what competitors say in their videos.
- **Education** — Extract transcripts from online courses for indexing or study notes.
- **Sentiment analysis** — Run sentiment or topic models against transcripts at scale.

### FAQ

**Which videos can I scrape?**
Any public YouTube video that has either manually created captions or auto-generated captions. Private videos, deleted videos, and members-only videos cannot be scraped — those return `success=false` with a clear error.

**What if a video has no captions at all?**
Set `useWhisper: true` to download the audio and transcribe it locally with Whisper (faster-whisper). For clear speech, `whisperModel=base` is the sweet spot. For music, noisy audio, or short clips, use `whisperModel=small` for noticeably better accuracy.

**What if my requested language isn't available?**
The scraper first tries an exact match (`en`), then variants (`en` matches `en-GB`, `en-US`), then falls back to the best available transcript. The `available_languages` field always lists everything available.

**What's the difference between `transcript_source` values?**

- `library` — pulled from YouTube's published caption tracks (fastest, most reliable, real human captions for popular videos).
- `innertube` — pulled from YouTube's internal API when the library couldn't reach it.
- `playwright_dom` — extracted from the in-page transcript panel as a last resort.
- `whisper` — generated locally from the audio with Whisper AI when YouTube has no captions at all.

**How accurate are auto-generated captions vs Whisper?**
YouTube auto-captions are generally accurate for clear English speech. Whisper `base` is comparable for clean audio, and Whisper `small` typically beats YouTube on accents, multiple speakers, and noisy audio. Both struggle on music with non-vocal singing.

**The Whisper output looks like garbage / repetitive text.**
Whisper-tiny on music or near-silent clips can hallucinate repetitive phrases. The actor automatically detects this (low language-detection confidence + identical segment text) and returns `success=false` with an actionable error pointing you at a larger model. Re-run with `whisperModel=small` for music videos.

**Can I scrape multiple videos in one run?**
Yes — pass an array of URLs. Each video is processed sequentially and pushed as its own dataset row.

**How current is the data?**
Live — every run hits YouTube at request time. Schedule the actor for daily / hourly refreshes.

### Limitations

- Private, members-only, age-restricted, and deleted videos cannot be scraped.
- Whisper transcription uses CPU, so it adds 30-180 s per video depending on length and model size.
- Whisper accuracy on heavy music or pure-instrumental audio is fundamentally limited regardless of model size.
- YouTube can change its caption infrastructure; the scraper has multiple fallback paths but a transient outage may still cause `success=false` for individual videos.

### YouTube Scraper Suite

This actor is part of a complete YouTube data extraction toolkit. Explore the full suite:

| Actor | Description |
|-------|-------------|
| [YouTube Channel Scraper](https://apify.com/crawlerbros/youtube-channel-scraper) | Channel metadata, subscriber counts, and full video catalogs |
| [YouTube Channel Scraper Fast](https://apify.com/crawlerbros/youtube-channel-scraper-fast) | Streamlined channel scraper for high-volume and speed-sensitive workflows |
| [YouTube Comment Scraper](https://apify.com/crawlerbros/youtube-comment-scraper) | Comments, replies, likes, author info, and pinned/hearted status |
| [YouTube Email Scraper](https://apify.com/crawlerbros/youtube-email-scraper) | Creator contact emails from channel pages, Instagram, TikTok, and Linktree |
| [YouTube Hashtag Scraper](https://apify.com/crawlerbros/youtube-hashtag-scraper) | Videos and Shorts tagged with specific hashtags |
| [YouTube Playlist Scraper](https://apify.com/crawlerbros/youtube-playlist-scraper) | All videos and metadata from any YouTube playlist |
| [YouTube Search Scraper](https://apify.com/crawlerbros/youtube-search-scraper) | Search results including videos, channels, and playlists |
| [YouTube Shorts Scraper](https://apify.com/crawlerbros/youtube-shorts-scraper) | Shorts from channels or hashtags with full view and like metadata |
| [YouTube Transcript Scraper](https://apify.com/crawlerbros/youtube-transcript-scraper) | Timed transcripts and captions with optional Whisper AI fallback |
| [YouTube Trending Scraper](https://apify.com/crawlerbros/youtube-trending-scraper) | Ranked trending videos by category — Gaming, Music, News, Movies |
| [YouTube Video Details Scraper](https://apify.com/crawlerbros/youtube-video-details-scraper) | Comprehensive video metadata, chapters, endscreen, captions, and comments |
| [YouTube Video Downloader](https://apify.com/crawlerbros/youtube-video-downloader) | Download videos, playlists, and channels in any quality with metadata |

# Actor input Schema

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

YouTube video URLs, short links (youtu.be), shorts URLs, or plain video IDs.

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

Preferred transcript language code (e.g., 'en', 'es', 'fr'). Leave empty for default language. If the requested language is not available, the scraper will attempt translation or fall back to the default.

## `includeAutoGenerated` (type: `boolean`):

Whether to include auto-generated captions when manual captions are not available.

## `useWhisper` (type: `boolean`):

When YouTube has no transcript (disabled captions, music-only, or blocked), download the audio and transcribe with Whisper AI (faster-whisper, CPU). Adds ~30-180 s per video. Enabled by default to guarantee transcript output even when YouTube captions are unavailable.

## `whisperModel` (type: `string`):

Whisper model size to use when `useWhisper` is enabled. Larger = more accurate but slower and more RAM. 'base' is balanced.

## `proxyCountry` (type: `string`):

Country/region for the proxy IP. Useful if transcripts are geo-blocked in the default US region.

## `outputFormat` (type: `string`):

Controls how transcript data is included in the output. 'full' = all fields including segments array. 'text\_only' = only full\_text (no segments array, smaller output). 'segments\_only' = only the segments array (no full\_text).

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "language": "",
  "includeAutoGenerated": true,
  "useWhisper": true,
  "whisperModel": "base",
  "proxyCountry": "US",
  "outputFormat": "full"
}
```

# Actor output Schema

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

Dataset with scraped YouTube video transcripts including timestamped segments, full text, language info, and video metadata (title, channel, views, duration, thumbnail).

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

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

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

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/OJfIBDtjxMoOD6hCf/builds/d43dC8kOy7zazesdW/openapi.json
