# YouTube Transcript Scraper API: Subtitles, Captions, Channels (`andracore/youtube-transcript-scraper`) Actor

Get YouTube transcripts, subtitles and captions from videos, Shorts, playlists and whole channels as text, timestamped JSON, SRT or VTT. Any language, auto-generated captions and translation. YouTube to text for AI. Pay only for transcripts.

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

## Pricing

from $3.25 / 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?

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

## YouTube Transcript Scraper API: Subtitles, Captions, Channels

Get the transcript, subtitles and captions of YouTube videos, whole channels and playlists as **plain text, timestamped JSON, SRT or VTT**. Works with manual and auto-generated captions in any language. No API key, no browser, no login.

Turn YouTube to text in a few clicks, or call it as a YouTube transcript API from your code or AI agent.

![How the YouTube Transcript Scraper works: paste a video, playlist or channel link, the scraper fetches the captions, and you get a clean transcript as text, JSON, SRT or VTT](https://api.apify.com/v2/key-value-stores/zZwndLrYGfCvgDJLT/records/youtube-transcript-scraper-how-it-works.png?signature=eUwRpBk57FtDJQkkrylx)

### Why use this YouTube transcript scraper

- **Channels and full playlists.** Paste a channel link to get the transcripts of its newest videos, or a playlist link to get every video in it, not just the first 100.
- **You only pay for transcripts.** Videos without captions, music without speech, unavailable videos and failed requests are listed with the reason and are not charged.
- **Fast.** Five videos at a time. In our tests, 100 videos from one channel took about a minute.
- **Four output formats.** Plain text for LLMs and search, timestamped JSON for analysis, SRT and VTT for subtitle workflows, or all at once.
- **Any language.** You get captions in your preferred language when the video has them, and the original captions otherwise. YouTube machine translation is available too.
- **No API key or quota.** Uses YouTube's internal mobile API. No Data API key, no daily limits.

### YouTube transcript data you get for each video

| Field | What it is |
|---|---|
| `title`, `author`, `channelId` | Video and channel metadata |
| `lengthSeconds`, `viewCount` | Duration and views when the transcript was fetched |
| `language` | Language of the returned transcript |
| `isAutoGenerated` | True when the captions were auto-generated by YouTube |
| `preferredLanguageFound` | False when the video has no captions in your preferred language and the original ones were returned |
| `isTranslated` | True when the transcript was machine-translated |
| `translationError` | Only when you ask for a translation: why YouTube did not translate this video |
| `transcript` | Full text as one string (text and all formats) |
| `segments` | Timestamped segments with `startMs`, `durationMs`, `text` (timestamped and all formats) |
| `srt` | Standard SRT subtitle file |
| `vtt` | Standard WebVTT subtitle file |
| `availableLanguages` | Every caption track the video has |
| `error` | Why the video has no transcript. These rows are not charged |

### Use cases for YouTube transcripts

- **LLM context.** Feed video transcripts to GPT, Claude or any language model for summaries, Q\&A or extraction.
- **Channel research.** Pull every transcript from a creator or competitor channel and analyze topics, keywords and claims.
- **SEO research.** Get the text of YouTube videos that rank for your keywords.
- **Content repurposing.** Turn videos into blog posts, newsletters or social media threads.
- **Subtitle download.** Get SRT or VTT files for any video.
- **Dataset building.** Batch-process channels and playlists for research or training data.

### How to get YouTube transcripts

1. Paste links in **YouTube links or video IDs**: videos, playlists or channels.
2. Pick a **Preferred language** (default: English).
3. Choose an **Output format** (default: plain text).
4. Set **Max videos** (default: 50).
5. Click **Start**, then download the results as JSON, CSV, Excel or HTML, or read them through the Apify API.

#### Links you can use

| Link | What you get |
|---|---|
| `youtube.com/watch?v=...`, `youtu.be/...`, `youtube.com/shorts/...` or the 11-character video ID | That video |
| `youtube.com/playlist?list=...` | Every video in the playlist, in playlist order |
| `youtube.com/@channel` or `youtube.com/@channel/videos` | The channel's newest long videos |
| `youtube.com/@channel/shorts` | The channel's newest Shorts |
| `youtube.com/@channel/streams` | The channel's past live streams |

Channel links can also be `youtube.com/channel/UC...`, `youtube.com/c/name` or just `@channel`.

#### Input examples

Single video:

```json
{
  "urls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
  "language": "en",
  "outputFormat": "text"
}
```

The 100 newest videos of a channel:

```json
{
  "urls": ["https://www.youtube.com/@3blue1brown"],
  "maxVideos": 100
}
```

A playlist in Portuguese, as SRT subtitles:

```json
{
  "urls": ["https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi"],
  "language": "pt",
  "outputFormat": "srt"
}
```

Videos translated to Spanish, all formats:

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/jNQXAC9IVRw"
  ],
  "translateTo": "es",
  "outputFormat": "all"
}
```

### YouTube subtitles as SRT or VTT

Set **Output format** to SRT or VTT to get standard subtitle files that video editors and players open directly. Each video's file comes in the `srt` or `vtt` field, ready to save as a `.srt` or `.vtt` file. Choose **All formats at once** to get text, timestamped segments, SRT and VTT in one run.

### YouTube transcript API

Run the scraper from your own code and get the transcripts back as JSON. Python:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("andracore/youtube-transcript-scraper").call(
    run_input={"urls": ["https://www.youtube.com/@3blue1brown"], "maxVideos": 20}
)
for video in client.dataset(run.default_dataset_id).iterate_items():
    print(video.get("title"), video.get("transcript") or video.get("error"))
```

Or with one HTTP request that waits for the run and returns the transcripts:

```bash
curl -X POST "https://api.apify.com/v2/acts/andracore~youtube-transcript-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"], "outputFormat": "text"}'
```

Your token is in Apify Console under Settings > API & Integrations. The same input works from JavaScript, Make, Zapier, n8n and the Apify MCP server for AI agents.

### Output example

```json
{
  "videoId": "dQw4w9WgXcQ",
  "videoUrl": "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": 1823062921,
  "language": "en",
  "isAutoGenerated": false,
  "isTranslated": false,
  "preferredLanguageFound": true,
  "transcript": "[♪♪♪] ♪ We're no strangers to love ♪ ♪ You know the rules and so do I ♪ ...",
  "availableLanguages": [
    { "code": "en", "name": "English", "isAutoGenerated": false },
    { "code": "en", "name": "English (auto-generated)", "isAutoGenerated": true },
    { "code": "de-DE", "name": "German (Germany)", "isAutoGenerated": false }
  ],
  "scrapedAt": "2026-10-04T05:58:41.391Z"
}
```

Timestamped format:

```json
{
  "segments": [
    { "startMs": 18640, "durationMs": 3240, "text": "♪ We're no strangers to love ♪" },
    { "startMs": 22640, "durationMs": 4320, "text": "♪ You know the rules and so do I ♪" }
  ]
}
```

A video without a transcript (not charged):

```json
{
  "videoId": "y6120QOlsfU",
  "videoUrl": "https://www.youtube.com/watch?v=y6120QOlsfU",
  "title": "Darude - Sandstorm",
  "transcript": null,
  "error": "The captions only contain music or sound tags, no speech."
}
```

### Pricing

**$4.00 per 1,000 transcripts.** Videos that fail, have no captions or have no speech are not charged. Paid Apify plans pay less: **$3.75** on Bronze, **$3.50** on Silver and **$3.25** on Gold and above, per 1,000 transcripts.

| Transcripts | Cost |
|---|---|
| 10 | $0.04 |
| 100 | $0.40 |
| 1,000 | $4.00 |

Set a maximum cost per run in the run options and the scraper stops exactly there.

### Good to know

- **Caption coverage.** Most YouTube videos have auto-generated captions in their original language. Manual captions are less common, and preferred when available.
- **Language.** When a video has no captions in your preferred language, you get the original captions and `preferredLanguageFound` is false.
- **Translation is best effort.** YouTube refuses some machine-translation requests. The scraper retries from other IPs, and when YouTube still refuses, you get the original captions with `translationError` explaining why. In our tests about 3 in 4 translations went through. Machine translation quality varies, so verify it for critical use.
- **Private, age-restricted and members-only videos.** YouTube only shows these to signed-in users, so they are listed with the reason and not charged.
- **Music videos.** When the captions only contain tags like \[Music], the video is reported as having no speech and is not charged.
- **Residential proxy required.** YouTube blocks datacenter IPs. On Apify the scraper uses Apify residential proxies by default. You can also supply your own residential proxy URLs in the input.
- **Live streams.** Live streams in progress do not have complete captions and may return partial or empty results.

### Other Actors by Andracore

- [Google Ads Transparency Scraper](https://apify.com/andracore/google-ads-transparency-scraper): every ad a brand runs on Google, including the YouTube video ads you can transcribe here.
- [Shopify Store Analyzer](https://apify.com/andracore/shopify-store-intelligence): apps, ad pixel IDs, contacts and best sellers of any Shopify store.
- [Shopify Store Finder](https://apify.com/andracore/shopify-store-finder): find Shopify stores by keyword or niche.

### FAQ

**Do I need a YouTube API key?**
No. The scraper uses YouTube's internal mobile API, which does not require a key or quota.

**Can I get the transcripts of a whole channel?**
Yes. Paste the channel link, like `youtube.com/@channel`, and set **Max videos**. You get its newest long videos. Add `/shorts` or `/streams` to the link for Shorts or past live streams.

**What languages are supported?**
Any language YouTube has captions for. Set the preferred language to a two-letter code (en, es, pt, fr, de, ja...). A code like `pt` also matches regional tracks like `pt-BR`.

**Why did I get a different language than I asked for?**
The video has no captions in that language, so you got the original ones (`preferredLanguageFound` is false). Set **Translate to** for a machine translation.

**Why is there no transcript for some videos?**
The uploader turned captions off, the video has no speech, or it is private, age-restricted or unavailable. The `error` field says which, and these videos are not charged.

**Can I use it from my code or AI agent?**
Yes. See the YouTube transcript API section above, or connect it to your AI agent through the Apify MCP server.

Found a bug or need a feature? Open an issue in the Issues tab.

# Actor input Schema

## `urls` (type: `array`):

Videos (youtube.com/watch?v=..., youtu.be/..., youtube.com/shorts/... or a bare 11-character ID), playlists (youtube.com/playlist?list=...) and channels (youtube.com/@channel or a bare @channel). A channel gives its newest long videos; add /shorts or /streams to the channel link for Shorts or past live streams.

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

Two-letter language code (e.g. en, es, pt, fr). The scraper picks a caption track in this language when available. If the video has no captions in it, the original captions are returned and preferredLanguageFound is false. Use Translate to for a translation.

## `translateTo` (type: `string`):

Two-letter language code. When set, YouTube machine-translates the transcript into this language. Best effort: when YouTube refuses a translation, you get the original captions and translationError says why. Leave empty for the original captions.

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

How to return the transcript. Plain text is ideal for LLMs and search. SRT and VTT are standard subtitle formats.

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

Use YouTube's auto-generated captions when manual captions are not available. Most videos only have auto-generated captions.

## `maxVideos` (type: `integer`):

Stop after this many videos, counted across all links. Channels are read newest first.

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

Residential proxy is required: YouTube blocks datacenter IPs. On Apify the default is Apify's residential proxy. You can also provide your own residential proxy URLs.

## Actor input object example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "language": "en",
  "outputFormat": "text",
  "includeAutoGenerated": true,
  "maxVideos": 50,
  "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 = {
    "urls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ]
};

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

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

```

## MCP server setup

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