# YouTube Transcript Scraper – Subtitles, SRT, Channels (`brii3343/youtube-transcript-scraper`) Actor

Extract YouTube transcripts and subtitles from videos, Shorts, whole channels and playlists. Get plain text for AI, timestamped segments, SRT and VTT, in the video's original language or the one you choose. Pay only for transcripts: videos without captions are free.

- **URL**: https://apify.com/brii3343/youtube-transcript-scraper.md
- **Developed by:** [Brian Gastaldelli](https://apify.com/brii3343) (community)
- **Categories:** Videos, AI, Developer tools
- **Stats:** 2 total users, 1 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.
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 — transcripts and subtitles from videos, Shorts, channels and playlists

Paste YouTube links and get the full transcript of every video: plain text for AI and search, timestamped segments, and ready-to-use **SRT** or **WebVTT** subtitles. Works with single videos, Shorts, live replays, **whole channels** and **playlists**, in any language the video has captions for.

#### Why this Actor

- **Reliable.** In our tests on 331 videos from 11 channels in 5 languages (English, Hindi, Spanish, Portuguese, Japanese), every video that has captions was transcribed and none ended up blocked. Failed attempts are retried automatically from a different IP.
- **Pay only for transcripts.** Videos without captions, private, age-restricted, unavailable or invalid links are returned with a clear status and **are not charged**.
- **Channels and playlists in one go.** Give `@handle`, a channel URL or a playlist and set how many of the newest videos to transcribe.
- **The right language.** By default you get the language that is actually spoken in the video, even on videos with AI-dubbed audio tracks (where YouTube lists auto-captions for every dub). Ask for a specific language with one field.
- **Creator captions first.** Captions written by the creator are more accurate than automatic ones: they are picked first, or you can choose only one type.
- **Fast.** One video takes about 10 seconds from start to finish; 150 videos about 2 minutes.

#### Use cases

- **AI and LLM pipelines**: feed transcripts to ChatGPT, Claude or your RAG system to summarize, answer questions or extract insights.
- **Content repurposing**: turn videos into blog posts, newsletters, social posts and show notes.
- **SEO and research**: analyze what competitors and creators talk about across whole channels.
- **Subtitles**: download SRT or VTT files for editing, translation or accessibility.
- **Automation**: call it from n8n, Make, Zapier or the Apify API with one video per run.

#### Input

| Field | Description |
|---|---|
| YouTube URLs | Videos, Shorts, live replays, channels or playlists, one per line. Video IDs, `@handles` and playlist IDs work too. |
| Language | Language code such as `en`, `es`, `de`, `pt-BR`. Empty = the video's original language. |
| Caption type | Best available (creator captions first), only creator captions, or only automatic captions. |
| Include timestamped segments | Adds `segments` with start, end and text of every caption line (default: on). |
| Subtitle files | Also return `srt` and/or `vtt` text. |
| Max videos per channel or playlist | Newest videos to transcribe from each channel or playlist (default: 50). |
| Parallel videos | Videos transcribed at the same time (default: 10). |

Example input:

```json
{
  "urls": ["https://www.youtube.com/watch?v=arj7oStGLkU", "@3blue1brown"],
  "language": "en",
  "subtitleFormats": ["srt"],
  "maxVideosPerSource": 20
}
```

#### Output

One item per video. Real output (shortened):

```json
{
  "input": "@3blue1brown",
  "videoId": "ausLKMojXaY",
  "url": "https://www.youtube.com/watch?v=ausLKMojXaY",
  "status": "ok",
  "title": "The Phone Number puzzle",
  "channelName": "3Blue1Brown",
  "channelId": "UCYO_jab_esuFRV4b17AJtAw",
  "durationSeconds": 44,
  "viewCount": 566886,
  "language": "en",
  "languageName": "English",
  "isAutoGenerated": false,
  "wordCount": 158,
  "characterCount": 832,
  "text": "Here's a surprising fact. If you take your phone number, it's possible to find another whole number bigger than zero such that...",
  "segments": [
    { "start": 0, "end": 0.95, "duration": 0.95, "text": "Here's a surprising fact." },
    { "start": 1.2, "end": 2.399, "duration": 1.199, "text": "If you take your phone number," }
  ],
  "srt": "1\n00:00:00,000 --> 00:00:00,950\nHere's a surprising fact.\n\n2\n00:00:01,200 --> 00:00:02,399\nIf you take your phone number,\n...",
  "availableLanguages": [
    { "code": "en", "name": "English", "isAutoGenerated": false },
    { "code": "en", "name": "English (auto-generated)", "isAutoGenerated": true }
  ],
  "description": "Part of a monthly series of puzzles...",
  "keywords": ["Mathematics", "three blue one brown"],
  "thumbnail": "https://i.ytimg.com/vi/ausLKMojXaY/sddefault.jpg",
  "isLive": false,
  "source": { "type": "channel", "input": "@3blue1brown", "title": "3Blue1Brown", "channelId": "UCYO_jab_esuFRV4b17AJtAw" },
  "scrapedAt": "2026-09-28T20:10:29.515Z"
}
```

`status` is one of:

| Status | Meaning | Charged |
|---|---|---|
| `ok` | Transcript returned | yes |
| `no_captions` | The video has no captions at all | no |
| `language_not_available` | No captions in the language you asked for; `availableLanguages` lists what the video has | no |
| `age_restricted`, `private`, `members_only` | YouTube requires a signed-in account | no |
| `unavailable`, `not_started` | Deleted, invalid, or a live stream / premiere that has not started | no |
| `not_found`, `invalid_input` | Channel or playlist not found, or not a YouTube link | no |
| `blocked`, `error` | YouTube refused every retry (rare); try again later | no |

#### Honest limits

- The Actor reads the captions YouTube already has (written by the creator or generated automatically). Videos without any captions, often short music-only Shorts, return `no_captions`: it does not transcribe audio.
- Automatic translation into other languages is not offered: YouTube now blocks it for automated requests. You get every language the video actually has.
- Age-restricted, private and members-only videos need a signed-in account and are skipped (not charged).
- The publish date and like count are not included; title, channel, duration, views, description, keywords and thumbnail are.

# Actor input Schema

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

Videos, Shorts, live replays, channels or playlists, one per line. Video IDs, <code>@handles</code> and playlist IDs work too. For channels and playlists, the newest videos are transcribed up to the limit below.

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

Language code of the transcript you want, for example <code>en</code>, <code>es</code>, <code>de</code>, <code>pt-BR</code>. Leave empty to get the video's original language. If the video has no captions in this language, the item lists the languages it does have (not charged).

## `captionType` (type: `string`):

Captions written by the creator are usually more accurate than the automatic ones. 'Best available' picks creator captions first, then automatic.

## `includeTimestamps` (type: `boolean`):

Add a <code>segments</code> list with start, end and text of every caption line. The full plain text is always included.

## `subtitleFormats` (type: `array`):

Also return the transcript as ready-to-use subtitle text.

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

How many videos to transcribe from each channel or playlist, newest first. Ignored for single videos.

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

How many videos to transcribe at the same time.

## Actor input object example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=arj7oStGLkU",
    "https://youtu.be/aircAruvnKk"
  ],
  "language": "",
  "captionType": "any",
  "includeTimestamps": true,
  "subtitleFormats": [],
  "maxVideosPerSource": 50,
  "maxConcurrency": 10
}
```

# Actor output Schema

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

One item per video: transcript text, timestamped segments, optional SRT/VTT and video details.

# 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=arj7oStGLkU",
        "https://youtu.be/aircAruvnKk"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("brii3343/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=arj7oStGLkU",
        "https://youtu.be/aircAruvnKk",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("brii3343/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=arj7oStGLkU",
    "https://youtu.be/aircAruvnKk"
  ]
}' |
apify call brii3343/youtube-transcript-scraper --silent --output-dataset

```

## MCP server setup

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