# YouTube Transcript Scraper + English Translation (`panix/youtube-transcript-scraper`) Actor

Get YouTube transcripts in the language actually spoken, in its own script, plus an English version for 60+ languages. Urdu in Urdu script, RTL-safe Arabic, clean Japanese and Chinese. Timestamps, SRT/VTT, RAG chunks, Shorts. From $2 per 1,000 videos. Failed videos are free.

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

## Pricing

from $2.00 / 1,000 transcript delivereds

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

## YouTube Transcript Scraper + English Translation

Get the transcript of any YouTube video or Short **in the language it is actually spoken in, written in that language's own script**, and an **English version for 60+ languages**. Optionally add YouTube's original caption text, timestamps, SRT/VTT subtitles and RAG-ready chunks. You choose one of three levels and **only pay for transcripts you actually receive**.

- **Original language first.** Spanish stays Spanish, Japanese stays Japanese, Urdu is written in Urdu script.
- **English for 60+ languages**, translated offline inside the Actor. English videos and creator English subtitles are never charged for translation.
- **From $2.00 per 1,000 videos.** Failed, removed and caption-less videos are free.
- **Right-to-left and CJK done properly.** Arabic, Urdu, Persian and Hebrew get RTL-safe subtitles; Japanese and Chinese are joined without stray spaces.
- **No API keys, no proxies, no AI account.** Works from the Console, the API, MCP agents, n8n, Make and Zapier.

Built for AI agents, LLM and RAG pipelines, content repurposing, research, media monitoring, SEO, and n8n / Make / Zapier automations.

### Three versions of every video, side by side

Most tools return one block of text and leave you to guess what it is. This Actor tells you exactly what you got:

```json
{
  "videoId": "27B0VvApWLg",
  "title": "Pakistan, Turkey, Qatar and Indonesia - Defense Deal | 6PM Headlines Geo News",
  "language": "ur",
  "captionLanguage": "hi",
  "textDirection": "rtl",
  "scriptConverted": true,
  "transcriptOriginal": "ملتان میں 15 سال کا یتیم لڑکا تیز رفتار گاڑی سے کچل دیا گیا۔ ...",
  "transcriptCaption":  "मुल्तान में 15 साल का यतीम लड़का तेज रफ्तार गाड़ी से कुचल दिया गया। ...",
  "transcriptEnglish":  "A 15-year-old orphan boy was crushed by a speeding car ...",
  "englishSource": "machine-translation"
}
```

| Field | What it is |
|---|---|
| `transcriptOriginal` | The spoken language, in its own script. Urdu is written in Urdu script, even though YouTube captions it in Hindi script. |
| `transcriptCaption` | Exactly what YouTube's caption track says, cleaned. Identical to the original for most videos. |
| `transcriptEnglish` | An English version. It comes from the creator's own English subtitles when they exist, and from offline machine translation otherwise. `englishSource` tells you which. |

### Choose your level

| Level | You get | Price |
|---|---|---|
| **Original** | `transcriptOriginal`, language detection, text direction, word count, video metadata and chapters | **$2.00 per 1,000 videos** |
| **Captions** (default) | Everything in Original, plus timestamped segments, `transcriptCaption`, SRT, WebVTT, Markdown and RAG chunks | **$3.00 per 1,000 videos** |
| **English** | Everything in Captions, plus `transcriptEnglish`, English segments, English SRT/VTT and English text on every chunk | **$3.00 per 1,000 videos**, plus **$0.50 per 1,000 minutes** of video only when we machine-translate |

You pay for translation only when translation actually happens:

- **English videos:** no translation charge. You get the same transcript in the English fields.
- **Creator English subtitles:** when the creator uploaded English subtitles, we return those. No translation charge.
- **Other languages:** $0.0005 per started minute of speech, about **$0.005 for a 10-minute video**.
- **Languages we can't translate well yet:** you still get the transcript, without an English version and without a translation charge.

Each run also has a small start fee of **$0.001 per GB of memory**: $0.001 for the Original and Captions levels, $0.002 for the English level, which needs more memory for translation.

Examples:

| Job | Level | Cost |
|---|---|---|
| 1,000 Shorts, text only | Original | **$2.00** |
| 1,000 English videos with timestamps and SRT | Captions | **$3.00** |
| 1,000 English videos at the English level | English | **$3.00** (nothing to translate) |
| 100 Spanish news videos of 10 minutes, with English | English | $0.30 + $0.50 = **$0.80** |
| 1 Urdu podcast of 60 minutes, with English | English | $0.003 + $0.03 = **$0.033** |

Start fees are not included in the examples. Every result row shows exactly what it was charged in `chargedEvents`.

### Why this Actor

We tested the most-used YouTube transcript tools on the same set of hard videos before building this one. These are the problems we found, and how this Actor handles them:

| Common problem | This Actor |
|---|---|
| Non-English videos come back machine-translated into English, or fail with "no transcript in requested language" | The **original spoken language** by default, with the English version as a separate, clearly labelled field |
| Urdu videos come back in Hindi script, because YouTube has no Urdu speech recognition | **Urdu is detected and written in Urdu script.** YouTube's text is kept alongside it |
| Pashto or Persian videos come back as meaningless Hindi text | **Detected and flagged.** You get the creator's English subtitles when they exist, otherwise a free error explaining why |
| Auto-dubbed videos return the captions of a dub (for example Arabic for an English video) | Detects the **original audio track** and its captions |
| Auto-generated "\[Music]" captions picked over human-made captions | **Human-made captions first**, in the spoken language |
| Japanese and Chinese text broken up by spaces between caption lines | **Joined correctly**, without spaces. Korean and Thai keep theirs |
| Arabic, Persian, Urdu and Hebrew subtitles with punctuation on the wrong side | **Right-to-left marks** in SRT/VTT, `dir="rtl"` in Markdown, and `textDirection` on every result |
| `&#39;` and other HTML codes left in the text, or the transcript returned as a stringified list | Clean UTF-8 text and real JSON arrays |
| One broken URL crashes the whole run | Each video is isolated. Tested on 4-hour podcasts and 2.4-hour live replays |
| You pay for removed videos, videos without captions, and invalid URLs | **You only pay for delivered transcripts** |
| Transcripts sent to a third-party AI service for translation | Translation runs **inside the Actor**, offline. Your content isn't sent anywhere else |

### How to use it

1. Paste one or more YouTube URLs or video IDs into **YouTube video URLs or IDs**.
2. Choose the level you need: **Original**, **Captions**, or **English**.
3. Optionally turn on SRT, VTT, Markdown or RAG chunks.
4. Click **Start**. Results appear as the videos finish. Download them as JSON, CSV, Excel or HTML, or read them through the API.

The English level automatically runs with 2 GB of memory for translation, and the other levels with 512 MB. You don't need to change anything. In our tests it translated about an hour of non-English video per minute of run time.

#### Input example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=iG9CE55wbtY",
    "https://youtu.be/27B0VvApWLg",
    "https://www.youtube.com/shorts/Y8IJi7iP5vk"
  ],
  "outputLevel": "english",
  "removeNonSpeechTags": true,
  "includeSrt": true,
  "includeChunks": true
}
```

#### Output fields

| Field | Levels | Notes |
|---|---|---|
| `status`, `errorCode`, `errorMessage` | all | `ok` or `error`. Errors are never charged |
| `language`, `captionLanguage`, `languageDetection` | all | The spoken language, the caption track's language, and why they differ (when they do) |
| `textDirection`, `scriptConverted`, `isAutoGenerated` | all | `rtl` or `ltr`; `true` when the script was converted (Urdu) |
| `transcriptOriginal` (also `transcript`) | all | The spoken language in its own script |
| `wordCount`, `characterCount` | all | Chinese, Japanese and Thai count characters |
| `title`, `channelName`, `durationSeconds`, `viewCount`, `keywords`, `thumbnailUrl`, `description`, `chapters` | all | Free metadata |
| `availableLanguages` | all | Every caption track the video has |
| `transcriptCaption`, `segments`, `srt`, `vtt`, `markdown`, `chunks` | Captions, English | Timed data in the original script |
| `transcriptEnglish`, `englishSource`, `englishModel`, `englishSegments`, `srtEnglish`, `vttEnglish`, `chunks[].textEnglish` | English | `englishSource` is `original`, `creator-subtitles` or `machine-translation` |
| `warnings`, `chargedEvents`, `attempts` | all | Plain-language notes, what this row cost, and retries used |

A failed video looks like this, and is free:

```json
{
  "position": 3,
  "videoId": "WJ3-F02-F_Y",
  "status": "error",
  "errorCode": "NO_CAPTIONS",
  "errorMessage": "The video has no captions or subtitles (manual or auto-generated).",
  "chargedEvents": {},
  "charged": false
}
```

The run also saves a `SUMMARY` record in its key-value store, with counts of transcripts and failures by reason.

### Languages

The **Original** and **Captions** levels work in every language YouTube has captions for: the 60+ languages YouTube captions automatically, plus any language a creator uploaded subtitles in.

**English** is available for more than 60 languages. Each language goes to the open translation model with the best published test score for it, and only when that score is high enough. Otherwise you still get the transcript, just without an English version and without a translation charge.

The 50 languages with the most YouTube viewing, by our estimate from YouTube users per country and regional viewing data (YouTube doesn't publish views by language):

| # | Language | Original & Captions | English |
|---|---|---|---|
| 1 | English | Yes | Already English (free) |
| 2 | Spanish | Yes | Yes, single-language model |
| 3 | Hindi | Yes | Yes, single-language model |
| 4 | Russian | Yes | Yes, single-language model |
| 5 | Portuguese | Yes | Yes, language-family model |
| 6 | French | Yes | Yes, single-language model |
| 7 | German | Yes | Yes, single-language model |
| 8 | Arabic | Yes | Yes, single-language model |
| 9 | Indonesian | Yes | Yes, single-language model |
| 10 | Turkish | Yes | Yes, single-language model |
| 11 | Italian | Yes | Yes, single-language model |
| 12 | Japanese | Yes | Yes, single-language model |
| 13 | Bengali | Yes | Yes, single-language model |
| 14 | Vietnamese | Yes | Yes, single-language model |
| 15 | Polish | Yes | Yes, language-family model |
| 16 | Thai | Yes | Yes, single-language model |
| 17 | Korean | Yes | Yes, single-language model |
| 18 | Urdu | Yes, written in Urdu script (YouTube captions it in Hindi script) | Yes, single-language model |
| 19 | Filipino | Yes | Yes, single-language model |
| 20 | Chinese | Yes | Yes, single-language model |
| 21 | Dutch | Yes | Yes, language-family model |
| 22 | Telugu | Yes | Not yet (never charged) |
| 23 | Tamil | Yes | Yes, multilingual model (gist) |
| 24 | Romanian | Yes | Yes, language-family model |
| 25 | Ukrainian | Yes | Yes, language-family model |
| 26 | Marathi | Yes | Yes, single-language model |
| 27 | Punjabi | Yes | Yes, single-language model |
| 28 | Persian | Yes | Not yet (never charged) |
| 29 | Kannada | Yes | Not yet (never charged) |
| 30 | Czech | Yes | Yes, language-family model |
| 31 | Malayalam | Yes | Yes, multilingual model (gist) |
| 32 | Malay | Yes | Yes, language-family model |
| 33 | Swedish | Yes | Yes, language-family model |
| 34 | Hungarian | Yes | Yes, multilingual model (gist) |
| 35 | Gujarati | Yes | Yes, language-family model |
| 36 | Bhojpuri | When the creator uploaded captions | Yes, language-family model |
| 37 | Burmese | Yes | Not yet (never charged) |
| 38 | Greek | Yes | Yes, language-family model |
| 39 | Hebrew | Yes | Yes, multilingual model (gist) |
| 40 | Odia | When the creator uploaded captions | Not yet (never charged) |
| 41 | Uzbek | Yes | Not yet (never charged) |
| 42 | Khmer | Yes | Not yet (never charged) |
| 43 | Nepali | Yes | Not yet (never charged) |
| 44 | Serbian | When the creator uploaded captions | Yes, language-family model |
| 45 | Kurdish | When the creator uploaded captions | Not yet (never charged) |
| 46 | Swahili | Yes | Not yet (never charged) |
| 47 | Bulgarian | Yes | Yes, language-family model |
| 48 | Pashto | When the creator uploaded captions. YouTube's Hindi auto-captions for Pashto are flagged, not returned | Creator English subtitles only |
| 49 | Danish | Yes | Yes, language-family model |
| 50 | Finnish | Yes | Yes, multilingual model (gist) |

English is also available for Catalan, Galician, Croatian, Bosnian, Albanian, Lithuanian, Latvian, Estonian, Slovenian, Macedonian, Belarusian, Armenian, Georgian, Azerbaijani, Afrikaans, Icelandic, Basque, Irish, Welsh, Sinhala, Maithili, Zulu, Xhosa, Maltese and a few more. When a creator uploaded English subtitles, those are returned for any language, free of translation charges.

Language-specific handling:

| Language | Special handling |
|---|---|
| Urdu | Detected from Urdu vocabulary and Pakistani metadata, then converted from Hindi script to Urdu script. Turn off with **Write Urdu in Urdu script** |
| Pashto, Persian | When YouTube captions them with its Hindi recognizer, the result is flagged as `CAPTIONS_LANGUAGE_MISMATCH`. Creator English subtitles are returned when they exist |
| Japanese, Chinese | Caption lines are joined without spaces. Word counts and chunk sizes use characters |
| Thai, Lao, Khmer, Myanmar | Phrase spaces are kept. Counts use characters |
| Arabic, Persian, Urdu, Hebrew, Pashto | `textDirection: "rtl"`, RTL marks in subtitle files, `dir="rtl"` in Markdown. Stray invisible direction characters from YouTube are removed |

By our estimate, the languages with an English version cover over 90% of YouTube viewing. Machine translation is best on clear speech such as news, lectures and talks. It is weaker on slang, very casual speech and mixed languages, for example Hindi videos with a lot of English words. When the creator uploaded English subtitles, those are used instead.

### Error codes (all free)

| Code | Meaning |
|---|---|
| `NO_CAPTIONS` | The video has no captions at all (often music-only videos) |
| `CAPTIONS_LANGUAGE_MISMATCH` | The only captions were made by YouTube's recognizer for a different language (common for Pashto). The message lists human-made tracks you can request instead |
| `AGE_RESTRICTED` | YouTube requires a signed-in adult account |
| `PRIVATE` | The video is private |
| `MEMBERS_ONLY` | Channel members only |
| `UNAVAILABLE` | Removed, deleted, or the ID doesn't exist |
| `LIVE_NOT_FINISHED` | The live stream or premiere hasn't ended yet |
| `UNPLAYABLE` | YouTube refuses playback here (often region-locked) |
| `LOGIN_REQUIRED` | Another sign-in wall |
| `INVALID_URL` | Not a YouTube video URL or ID |
| `BLOCKED` | YouTube refused every retry. Running it again usually works |
| `FAILED` | Unexpected error. Please report it in the Issues tab |

### Use it with AI tools and automations

- **AI agents (MCP).** Add this Actor to the [Apify MCP server](https://mcp.apify.com) and let Claude, Cursor or ChatGPT fetch transcripts on demand.
- **RAG.** Turn on `includeChunks` and send `chunks[]` straight to Pinecone, Qdrant, Supabase pgvector, Weaviate or Chroma. On the English level each chunk carries both the original text and `textEnglish`, so you can embed in one language and show the other. Store `url` as metadata so answers can link to the exact second.
- **n8n / Make / Zapier.** Use the Apify integration and set "Run Actor" to wait for the result, then map `transcriptOriginal`, `transcriptEnglish` or `markdown` to your next step.
- **API (Python):**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("panix/youtube-transcript-scraper").call(
    run_input={"videoUrls": ["https://www.youtube.com/watch?v=27B0VvApWLg"], "outputLevel": "english"}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["status"], item.get("language"), item.get("transcriptEnglish", "")[:200])
```

- **API (cURL, synchronous):**

```bash
curl -X POST "https://api.apify.com/v2/acts/panix~youtube-transcript-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer <YOUR_APIFY_TOKEN>" -H "Content-Type: application/json" \
  -d '{"videoUrls": ["https://youtu.be/8jPQjjsBbIc"], "outputLevel": "original"}'
```

### How it works

The Actor reads the same caption data the YouTube mobile apps use. It doesn't run a browser or download any video or audio, which keeps it fast and inexpensive. Each video is fetched through a residential IP. If YouTube refuses a request, the Actor switches to a second app client and then to a fresh IP, up to the retry limit you set.

English translation uses open-source OPUS-MT models (University of Helsinki, Apache-2.0) running on CPU inside the Actor. No paid AI service is involved, and your transcripts are not sent anywhere.

### Tested

The Actor returned the correct transcript for all 17 videos with captions on our benchmark of 20 deliberately difficult YouTube URLs. The set covered:

- Short, 20-minute and 4-hour videos, plus a live replay.
- Shorts.
- Auto-dubbed videos.
- Urdu, Hindi and Spanish.
- A 64-track TED talk.
- A music video.
- Odd URL formats.

The other 3 (no captions, age-restricted, removed) returned clear, free error rows. On Apify, a batch of 50 normal talks returned 50 of 50 transcripts in about 40 seconds.

A separate multilingual set covered Pashto, Persian, Urdu, Hindi, Japanese, Arabic, English, French, German and Spanish:

- Every original language was detected correctly.
- Urdu was written in Urdu script.
- The Pashto video, which YouTube only captions with its Hindi recognizer, was flagged at the Original and Captions levels. At the English level it returned the creator's English subtitles.
- At the English level on Apify, 7 videos totalling about 1.8 hours of speech were machine-translated in about one minute.

A second set added Portuguese, Italian, Filipino, Polish, Dutch, Romanian, Ukrainian, Bengali, Marathi, Punjabi, Telugu and Urdu podcasts and news. Every video with captions was detected in the right language and translated, except Telugu, which correctly returned its transcript without an English version and without a translation charge.

### Limitations

- It extracts **existing captions** (human-made or YouTube's auto-generated ones). It does not run speech-to-text, so a video with no captions returns `NO_CAPTIONS`.
- Auto-generated captions can mishear names and words. That is YouTube's speech recognition, and every caption-based tool returns the same text.
- Urdu script conversion is rule-based with a dictionary of common words. It reads naturally, but some rare loanwords may be spelled phonetically.
- Age-restricted, private and members-only videos need a signed-in account and are not supported.
- Channel and playlist URLs are not expanded yet: pass video URLs. This is planned.

### FAQ

**Do I need a YouTube API key, a proxy or an AI key?** No. Everything is included.

**Why do `language` and `captionLanguage` differ?** YouTube sometimes captions a language with another language's recognizer. Urdu is the most common case: it gets Hindi captions. `language` is what is spoken, and `captionLanguage` is what YouTube labelled the track.

**Can I get auto-generated captions instead of human-made ones?** Yes, turn off **Prefer human-made captions**.

**Is translation charged when the video is already in English?** No. It's also free when the creator uploaded English subtitles. You only pay the per-minute translation price when we actually machine-translate.

**Why is there a start fee?** Every run starts a container that already holds the translation models, so nothing is downloaded during your run. The $0.001 per GB start fee covers that start-up, so the per-video prices can stay low for small jobs and single-video calls from AI agents.

**How do I keep costs lowest?** Put many videos in one run instead of one video per run, and use the Original level when you don't need timestamps.

**Is scraping YouTube transcripts legal?** The Actor only reads publicly available caption data. You are responsible for how you use it, including YouTube's Terms of Service, copyright and the privacy laws that apply to you.

**Found a problem?** Open an issue in the Issues tab with the video URL. We read every one.

***

Translation models: [OPUS-MT](https://github.com/Helsinki-NLP/Opus-MT) by the Language Technology Research Group at the University of Helsinki (Apache-2.0), run with [CTranslate2](https://github.com/OpenNMT/CTranslate2) (MIT).

# Actor input Schema

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

Any format works: watch?v=, youtu.be, /shorts/, /live/, /embed/, links with \&t= or \&list=, or a bare 11-character video ID. Duplicates are removed automatically.

## `outputLevel` (type: `string`):

Original: the transcript in the language and script the video is spoken in ($2.00 per 1,000 videos). Captions: adds timestamps, YouTube's own caption text, SRT/VTT, Markdown and RAG chunks ($3.00 per 1,000). English: adds an English version for 60+ languages. English videos and the creator's own English subtitles cost nothing extra; offline machine translation is $0.50 per 1,000 minutes of video. Each run also has a start fee of $0.001 per GB of memory.

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

Leave empty to get the language the video is actually spoken in (recommended). Or enter a code such as en, es, de, hi, ur, pt-BR to pick that caption track when the video has it; otherwise the original language is returned with requestedLanguageFound: false.

## `fixUrduScript` (type: `boolean`):

YouTube captions Urdu speech with its Hindi recognizer, in Hindi (Devanagari) script. When the video is detected as Urdu, transcriptOriginal is converted to Urdu (Perso-Arabic) script. YouTube's text is kept in transcriptCaption.

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

When a video has both human-made and auto-generated captions in the same language, use the human-made ones. Turn off to prefer auto-generated captions (closer to the exact spoken words).

## `removeNonSpeechTags` (type: `boolean`):

Strip sound descriptions so the text contains only spoken words. Useful for LLM and search pipelines.

## `includeSegments` (type: `boolean`):

A segments array with start, end and duration (seconds) and text for every caption line, plus englishSegments on the English level.

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

Title, channel, duration, views, keywords, thumbnail, description and chapters. Included at no extra cost.

## `includeSrt` (type: `boolean`):

Adds a ready-to-use .srt subtitle string (and srtEnglish on the English level). Right-to-left languages get direction marks so players show punctuation correctly.

## `includeVtt` (type: `boolean`):

Adds a ready-to-use .vtt subtitle string (and vttEnglish on the English level).

## `includeMarkdown` (type: `boolean`):

The whole transcript as clean Markdown: a title header, timestamped paragraphs and chapter headings. Good for notes, Notion, docs and LLM prompts.

## `includeChunks` (type: `boolean`):

Splits the transcript into chunks for vector databases (Pinecone, Qdrant, Supabase, Weaviate). Chunks never cross a chapter boundary, and each has start/end times and a deep link to that moment of the video. On the English level each chunk also has textEnglish.

## `chunkSizeWords` (type: `integer`):

Target words per chunk; for Chinese, Japanese and Thai, characters. Roughly 1 English word = 1.3 tokens.

## `chunkOverlapWords` (type: `integer`):

Words repeated at the start of the next chunk so context is not lost at the edges. Capped at half the chunk size.

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

How many videos are fetched at the same time.

## `maxRetries` (type: `integer`):

Extra attempts, each from a fresh IP, when YouTube blocks a request. Retries are always free.

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

Residential proxy is on by default and included in the price. YouTube blocks most datacenter IPs, so only change this if you bring your own residential proxy.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    "https://www.youtube.com/watch?v=iG9CE55wbtY"
  ],
  "outputLevel": "captions",
  "fixUrduScript": true,
  "preferManualCaptions": true,
  "removeNonSpeechTags": false,
  "includeSegments": true,
  "includeMetadata": true,
  "includeSrt": false,
  "includeVtt": false,
  "includeMarkdown": false,
  "includeChunks": false,
  "chunkSizeWords": 300,
  "chunkOverlapWords": 30,
  "maxConcurrency": 10,
  "maxRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `transcripts` (type: `string`):

All results in the default dataset, one item per video, in completion order (use the 'position' field for input order).

## `summary` (type: `string`):

JSON with counts: videos, transcripts, failed, failedByReason and skippedSpendingLimit.

# 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=iG9CE55wbtY"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("panix/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=iG9CE55wbtY",
    ],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,panix/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/6ukHaiBxZ9CURveHw/builds/03PqpHFxJ8d3uc1db/openapi.json
