# YouTube Transcript Scraper: Captions, Subtitles & Text (`fguiraud/youtube-transcript-scraper`) Actor

Get the transcript of any YouTube video (or Short) as text, timestamped segments, SRT, VTT or Markdown, in any available language. Manual and auto-generated captions, video title, channel, duration and views. Fast and cheap for bulk lists and AI agents. Pay per transcript.

- **URL**: https://apify.com/fguiraud/youtube-transcript-scraper.md
- **Developed by:** [Fernando Guiraud](https://apify.com/fguiraud) (community)
- **Categories:** Videos, AI, Social media
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.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.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does YouTube Transcript Scraper do?

**YouTube Transcript Scraper** gets the **transcript of any YouTube video or Short** as **plain text, timestamped segments, SRT or VTT subtitles, Markdown with timestamps, or RAG-ready chunks**, in **any language the video has captions for**. It returns **human captions when they exist and YouTube's auto-generated captions otherwise**, plus the video's **title, channel, duration, views, keywords and description**.

Paste a list of video links or IDs and get clean transcripts in seconds, **with no YouTube API key**. Videos without captions, private or removed videos are **never billed**.

It runs on the Apify platform, so you also get an API, **scheduling**, integrations (Google Sheets, Make, Zapier, n8n, Slack) and access for **AI agents through the [Apify MCP server](https://mcp.apify.com)**.

### Why use it?

- 🤖 **AI and RAG pipelines**: feed video content to ChatGPT, Claude or your vector database, already split into chunks with timestamps.
- ✍️ **Content repurposing**: turn videos into blog posts, newsletters, social posts and show notes.
- 🔍 **Research and analysis**: analyse what competitors, creators or experts say across hundreds of videos.
- 🎓 **Study and accessibility**: searchable text of lectures and tutorials.
- 🎬 **Subtitles**: download SRT or VTT files ready for video editors.

### How to get the transcript of a YouTube video

1. Click **Try for free**.
2. Paste **YouTube links** (one per line): `youtube.com/watch?v=...`, `youtu.be/...`, Shorts and live links all work.
3. Optionally set the **preferred languages** (`en`, `es`, `de`...) and the **output formats**.
4. Click **Start**.
5. Download the transcripts as JSON, CSV or Excel, or copy them from the **Transcripts** view.

### Input

| Field | Description | Default |
|---|---|---|
| `videos` | Video links or IDs | required |
| `languages` | Preferred caption languages, in order (`es` also matches `es-419`) | the video's own |
| `fallbackToOtherLanguage` | Return another language when the preferred one does not exist | `true` |
| `preferManualCaptions` | Human captions before auto-generated ones | `true` |
| `outputs` | `text`, `segments`, `srt`, `vtt`, `markdown`, `chunks` | `text`, `segments` |
| `includeMetadata` | Channel ID, duration, views, keywords, description | `true` |

```json
{
  "videos": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "https://youtu.be/arj7oStGLkU"],
  "languages": ["en"],
  "outputs": ["text", "segments", "srt"]
}
```

### Output

One record per video. You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

```json
{
  "videoId": "dQw4w9WgXcQ",
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "status": "ok",
  "title": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)",
  "channel": "Rick Astley",
  "durationSeconds": 213,
  "viewCount": 1820283482,
  "language": "en",
  "languageName": "English",
  "isAutoGenerated": false,
  "availableLanguages": [{ "languageCode": "en", "languageName": "English", "isAutoGenerated": false }],
  "text": "♪ We're no strangers to love ♪ ♪ You know the rules and so do I ♪ ...",
  "segments": [{ "start": 18.64, "end": 21.88, "text": "♪ We're no strangers to love ♪" }],
  "wordCount": 487
}
```

### Data fields

| Field | Description |
|---|---|
| `text` | The transcript as paragraphs |
| `segments` | Lines with `start` and `end` in seconds |
| `srt`, `vtt` | Subtitle files |
| `markdown` | Paragraphs with `[HH:MM:SS]` timestamps, ready for LLMs and notes |
| `chunks` | ~1,000-character pieces with start/end time and a token estimate, for RAG |
| `language`, `isAutoGenerated` | Language of the transcript and whether YouTube generated it automatically |
| `availableLanguages` | Every caption track of the video |
| `title`, `channel`, `durationSeconds`, `viewCount`, `keywords`, `description` | Video details |
| `status` | `ok` (billed), `no-captions`, `unavailable` or `error` (not billed) |

### How much does it cost to scrape YouTube transcripts?

| Event | Price |
|---|---|
| Run start (per GB of memory, default 256 MB) | $0.001 |
| Transcript (one video, all formats, with video details) | **$0.003** |

**1,000 transcripts cost $3**, residential proxies included. Videos without captions, private or removed videos and failures are never billed. Set **Max cost per run** and the Actor stops cleanly at that limit.

### Use it with AI agents (MCP)

Add `https://mcp.apify.com?tools=fguiraud/youtube-transcript-scraper` to Claude, Cursor or any MCP client and ask:

- *"Summarize this video and list the key takeaways: https://youtu.be/arj7oStGLkU"*
- *"Get the transcripts of these 10 videos and tell me what each creator recommends."*
- *"Write a blog post based on this YouTube tutorial."*

Smallest useful input for an agent: `{"videos": ["https://youtu.be/arj7oStGLkU"], "outputs": ["text"]}`.

### Tips

- For **AI summaries** of long videos, choose `markdown` or `chunks`: timestamps let the model cite the exact moment.
- Choose only the **outputs** you need: smaller results are faster to download.
- `languages: ["es", "en"]` returns Spanish when it exists and English otherwise.
- Long runs are safe: if the platform restarts the run, finished videos are skipped and never charged twice.

### FAQ and limitations

- **Videos without captions**: some videos have neither human nor automatic captions (many Shorts, music without lyrics, very new uploads, some live streams). They come back with `status: "no-captions"` and are **not billed**.
- **Age-restricted, private and members-only videos** cannot be read without signing in; they come back as `unavailable` and are not billed.
- **Translation** into languages the video has no captions for is not included.
- **Is it legal?** The Actor reads the captions YouTube shows publicly on each video. Respect the rights of the video creators when you reuse their content.
- Found a problem or need a feature? Open an issue on the **Issues** tab. Replies within 48 hours.

### Related tools

- [Audio & Video to Text Transcription (Whisper)](https://apify.com/fguiraud/audio-video-transcriber): transcribe your own audio and video files (MP3, MP4, WAV, Google Drive or Dropbox links) with Whisper.
- [Podcast Transcript Scraper](https://apify.com/fguiraud/podcast-transcript-scraper): transcripts of any podcast by name, Apple Podcasts link or RSS feed.

# Actor input Schema

## `videos` (type: `array`):

Video links (youtube.com/watch?v=..., youtu.be/..., Shorts, live, embed) or 11-character video IDs. One per line.

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

Language codes in order of preference (en, es, pt, de, fr...). 'es' also matches regional tracks such as 'es-419'. Empty = the video's own captions.

## `fallbackToOtherLanguage` (type: `boolean`):

If none of the preferred languages exists, return the video's captions in its own language (billed). Turn off to skip those videos instead (not billed).

## `preferManualCaptions` (type: `boolean`):

Use captions written by the creator when they exist, and auto-generated ones otherwise. Turn off to prefer auto-generated captions.

## `outputs` (type: `array`):

text (paragraphs), segments (start/end/text), srt, vtt, markdown (with \[HH:MM:SS] timestamps) and chunks (for RAG).

## `includeMetadata` (type: `boolean`):

Channel ID, duration, views, keywords and description (free).

## `chunkSize` (type: `integer`):

Target size of each chunk when 'chunks' is selected.

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

How many videos are processed at the same time.

## `failOnError` (type: `boolean`):

Mark the run as FAILED when a video fails after all retries or no transcript is returned. Videos without captions do not count. Useful for monitoring pipelines.

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

YouTube blocks data-center IPs, so residential proxies are used by default (included in the price).

## Actor input object example

```json
{
  "videos": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "languages": [
    "en"
  ],
  "fallbackToOtherLanguage": true,
  "preferManualCaptions": true,
  "outputs": [
    "text",
    "segments"
  ],
  "includeMetadata": true,
  "chunkSize": 1000,
  "maxConcurrency": 5,
  "failOnError": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "videos": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ],
    "languages": [
        "en"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fguiraud/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 = {
    "videos": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
    "languages": ["en"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

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

```

## MCP server setup

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