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

Get the full transcript of any YouTube video or Short — plain text, SRT or VTT — with title, channel, views, duration and every available subtitle language

- **URL**: https://apify.com/mina\_safwat/youtube-transcript-scraper.md
- **Developed by:** [Mina](https://apify.com/mina_safwat) (community)
- **Categories:** Videos, Developer tools, Automation
- **Stats:** 2 total users, 1 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. 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

Paste YouTube links, get the full spoken text back — as clean paragraphs for AI prompts, or as timestamped SRT/VTT subtitle files. No cookies, no login, no API key of your own.

### What does YouTube Transcript Scraper do?

It takes any list of [YouTube](https://www.youtube.com) videos and returns each one's complete transcript along with the details you usually need next to it: title, channel, view count, duration, tags, thumbnail, and every subtitle language the video offers. Videos, Shorts, live replays and podcasts all work the same way.

Because it runs on Apify you can call it from the API, schedule it, feed it a list from Google Sheets, and export the results to JSON, CSV, Excel or straight into your own pipeline.

### Why use it?

- **Feed AI models.** Plain-text transcripts are the cheapest way to summarise, translate, or answer questions about hours of video.
- **Build RAG and search.** Turn a channel's back catalogue into searchable text.
- **Repurpose content.** Blog posts, newsletters, LinkedIn threads and show notes all start from the transcript.
- **Ship subtitles.** SRT and VTT output drops straight into a video player or editor.
- **Research at scale.** Compare what competitors, candidates or creators actually say, not just their titles.
- **Accessibility.** Give any video a readable text alternative.

### How to use it

1. Click **Try for free**.
2. Paste your YouTube links into **YouTube videos** — one per line.
3. Optionally set the language, the transcript format, or a translation target.
4. Click **Start**, then download the results as JSON, CSV or Excel.

Every link format works: `youtube.com/watch?v=…`, `youtu.be/…`, `youtube.com/shorts/…`, `youtube.com/live/…`, `youtube.com/embed/…`, and bare 11-character video ids. Extra parameters like `&t=90s` or `&list=…` are ignored, so you can paste straight from the address bar.

### Input

| Field | What it does |
|---|---|
| `video_urls` | Your videos, one per line. Links or bare ids, mixed freely. |
| `languages` | Comma-separated preference order, e.g. `en, es, de`. `en` also matches en-US and en-GB. Falls back to the closest available track. |
| `translate_to` | Optional 2-letter code. YouTube translates the subtitles for you. If a video offers no translation, the original language is returned instead of nothing. |
| `allow_auto_generated` | On by default, so videos with only automatic captions still return a transcript. Turn off for human-written subtitles only. |
| `text_format` | `plain` (one paragraph), `srt`, or `vtt`. |
| `include_segments` | Adds a `segments` array with the start time, duration and text of every caption line. |
| `concurrency` | How many videos run at once (1–20). |
| `proxy_configuration` | Residential is the default and is strongly recommended. |

```json
{
    "video_urls": [
        "https://www.youtube.com/watch?v=aircAruvnKk",
        "https://youtu.be/5MgBikgcWnY",
        "https://www.youtube.com/shorts/ImRy_PiXstI"
    ],
    "languages": "en",
    "text_format": "plain",
    "include_segments": true,
    "proxy_configuration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

### Output

One row per video:

```json
{
    "video_id": "jNQXAC9IVRw",
    "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    "title": "Me at the zoo",
    "channel": "jawed",
    "channel_id": "UC4QobU6STFB0P71PMvOGN5A",
    "channel_url": "https://www.youtube.com/channel/UC4QobU6STFB0P71PMvOGN5A",
    "description": "The first video on YouTube…",
    "duration_seconds": 19,
    "view_count": 406065439,
    "keywords": ["me at the zoo", "jawed karim", "first youtube video"],
    "is_live": false,
    "thumbnail": "https://i.ytimg.com/vi/jNQXAC9IVRw/hqdefault.jpg",
    "language_code": "en",
    "language": "English",
    "is_auto_generated": false,
    "available_languages": ["de", "en"],
    "transcript": "All right, so here we are, in front of the elephants…",
    "word_count": 39,
    "character_count": 217,
    "scraped_at": "2026-08-24T12:35:04.371676+00:00",
    "segments": [
        { "start": 1.2, "duration": 2.16, "text": "All right, so here we are, in front of the elephants" },
        { "start": 5.318, "duration": 2.656, "text": "the cool thing about these guys is that they have really..." }
    ]
}
```

With `text_format` set to `srt` or `vtt`, the `transcript` field holds a ready-to-save subtitle file instead of a paragraph.

#### Dataset views

- **Transcripts** — thumbnail, title, channel, language, word count and the transcript itself. The one you will use most.
- **Timed lines** — the caption lines with their start times, for anything that needs to jump to a moment in the video.
- **Video details** — channel, tags, duration, views and the full list of subtitle languages.

### Cost estimation

You are charged per result, and one result is one video with a transcript.

| Run | Results | Notes |
|---|---|---|
| 10 videos | 10 | A single playlist or a day's uploads. |
| 500 videos | 500 | A mid-sized channel's back catalogue. |
| 5,000 videos | 5,000 | A research dataset. |

**Videos with no transcript are not charged.** They are skipped and listed under `VIDEOS_WITHOUT_TRANSCRIPT` in the run's key-value store, with the reason for each, so you always know what was left out.

### Tips

- Raise **Videos at a time** to 10–20 for long lists; lower it if videos start being skipped.
- Turn off **Include timed lines** when you only need the text — smaller exports, faster downloads.
- Keep residential proxies on. YouTube returns transcripts far less reliably to datacenter addresses.
- Ask for a language you know exists. `languages` is a preference, not a filter — if none of your codes match, the closest available track is used and `language_code` in the output tells you what you got.

### FAQ

**Which videos have transcripts?** Most videos with speech do, either human-written or automatic. Music videos, silent clips, and some very new uploads have none.

**Are private or members-only videos supported?** No. Only videos anyone can watch.

**Does it work on Shorts?** Yes, when the Short has captions.

**Can I get a whole channel or playlist at once?** Not yet — pass the individual video links for now.

**Is scraping YouTube legal?** Collecting publicly available data is generally legal, but what you do with it is your responsibility — respect copyright and the platform's terms. If you plan to publish or redistribute transcripts, take legal advice first.

Found a problem or want a field added? Open an issue on the Actor's **Issues** tab.

### SEO Keywords

youtube transcript scraper, youtube subtitles downloader, video transcript api, youtube captions extractor, srt and vtt transcripts, youtube shorts transcript, video to text youtube, subtitle language extraction, transcripts for content repurposing, youtube transcript api

# Actor input Schema

## `video_urls` (type: `array`):

One video per line. Watch links, youtu.be links, Shorts, embeds and bare 11-character video ids all work, and you can mix them freely.

## `languages` (type: `string`):

Comma-separated language codes in order of preference, e.g. "en, es, de". A code like "en" also accepts en-US and en-GB. If none of them exist for a video, the closest available track is used instead.

## `translate_to` (type: `string`):

Optional 2-letter code, e.g. "es". Leave empty to keep the original language. Translation is done by YouTube itself, so quality varies.

## `allow_auto_generated` (type: `boolean`):

Keep this on to fall back to YouTube's automatic captions when a video has no human-written subtitles. Turn it off to collect only human-written subtitles.

## `text_format` (type: `string`):

How the transcript field is written. Plain text suits summarising and RAG pipelines; SRT and VTT drop straight into a video player.

## `include_segments` (type: `boolean`):

Adds a segments array with the start time, duration and text of every caption line, alongside the full transcript.

## `concurrency` (type: `integer`):

How many videos are collected in parallel. Raise it for large lists; lower it if you see videos being skipped.

## `proxy_configuration` (type: `object`):

Residential addresses are recommended — YouTube serves far fewer transcripts to datacenter addresses.

## Actor input object example

```json
{
  "video_urls": [
    "https://www.youtube.com/watch?v=aircAruvnKk",
    "https://youtu.be/5MgBikgcWnY",
    "https://www.youtube.com/shorts/ImRy_PiXstI"
  ],
  "languages": "en",
  "allow_auto_generated": true,
  "text_format": "plain",
  "include_segments": true,
  "concurrency": 5,
  "proxy_configuration": {
    "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 = {
    "video_urls": [
        "https://www.youtube.com/watch?v=aircAruvnKk",
        "https://youtu.be/5MgBikgcWnY",
        "https://www.youtube.com/shorts/ImRy_PiXstI"
    ],
    "languages": "en",
    "text_format": "plain",
    "concurrency": 5,
    "proxy_configuration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("mina_safwat/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 = {
    "video_urls": [
        "https://www.youtube.com/watch?v=aircAruvnKk",
        "https://youtu.be/5MgBikgcWnY",
        "https://www.youtube.com/shorts/ImRy_PiXstI",
    ],
    "languages": "en",
    "text_format": "plain",
    "concurrency": 5,
    "proxy_configuration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("mina_safwat/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 '{
  "video_urls": [
    "https://www.youtube.com/watch?v=aircAruvnKk",
    "https://youtu.be/5MgBikgcWnY",
    "https://www.youtube.com/shorts/ImRy_PiXstI"
  ],
  "languages": "en",
  "text_format": "plain",
  "concurrency": 5,
  "proxy_configuration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call mina_safwat/youtube-transcript-scraper --silent --output-dataset

```

## MCP server setup

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