# YouTube Transcript Scraper - Subtitles, SRT & VTT (`cheapapi/youtube-transcript-scraper`) Actor

Get YouTube transcripts and subtitles from any video URL: full text, timestamps, SRT/VTT, language, auto-caption flag, translation to 100+ languages.

- **URL**: https://apify.com/cheapapi/youtube-transcript-scraper.md
- **Developed by:** [CheapAPI](https://apify.com/cheapapi) (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

Pay per event + usage

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 - Subtitles, SRT & VTT

Get the full transcript of any YouTube video (plain text, timestamped segments, SRT or WebVTT) from a link or video ID, in the caption language you prefer, with optional translation into 100+ languages.

### Why this Actor

- **$3.50 per 1,000 transcripts on every plan ($0.0035 per video), plus Apify platform usage.** That event fee is 30% or more below the four most-used YouTube transcript Actors in Apify Store, which charge $0.005 to $0.01 per video; platform usage, billed separately by Apify, narrows that gap. Some smaller Actors charge less (see the comparison below). With the optional Fast processing add-on the total is $0.005 per video.
- **Simple, transparent charges.** $0.0035 per delivered transcript; a video that has no transcript costs $0.0033 for the lookup, and each extra language tried costs $0.0033. Invalid links and lookups the data source rejects cost nothing, and there is no start fee. Apify platform usage is billed separately.
- **Budget control:** set a maximum cost per run and the Actor stops cleanly before it goes over, including the Fast add-on.
- **4 output formats in one run:** plain text, timestamped segments, SRT and WebVTT, in rows of 26 fields when all four formats are selected (22 fields plus the formats you pick).
- **Only new videos:** on scheduled runs, videos already delivered by an earlier run are skipped before any request, so you never pay twice for the same transcript.
- **Language priority list and translation:** give up to 3 caption languages in order (for example `de`, then `en`). Each video gets the first one it has, or its default captions if it has none of them. You can also translate every transcript into 100+ languages.

Tested live on 2026-09-29: standard and fast processing, the language priority list, translation, SRT/VTT output and the Free-plan allowance. The maximum-cost stop, **Only new videos** and saving each transcript as soon as it is ready are covered by automated tests against a simulated data service.

### Compared with alternatives

Price for 1,000 videos with captions on the Apify Free plan and on Gold (Platinum and Diamond pay the Gold price for this Actor). The alternatives' prices are as listed and add no platform usage on top. This Actor does: Apify platform usage is billed separately by Apify on top of the prices shown ("+ usage"; see [Pricing](#pricing) for typical amounts). Features as described in each Actor's public input and README.

| Alternative | Free plan | Gold plan | Channel / playlist input | SRT + VTT | Language priority list | Translation | Videos without captions free |
|---|---|---|---|---|---|---|---|
| Most-used YouTube transcript Actor (~25,200 users, one video per run) | $10.00 | $7.00 | ✗ | ✗ | ✗ | one target language | not stated |
| Second most-used transcript Actor (~11,700 users) | $5.00 | $5.00 | channel | ✗ | ✗ | ✗ | ✓ |
| Third most-used transcript Actor (~8,500 users; optional video metadata) | $7.00 | $5.00 | ✗ | ✗ (XML or text) | ✗ (English preferred) | ✗ | not stated |
| Fourth most-used transcript Actor (~8,200 users) | $10.00 | $10.00 | ✗ | ✗ | ✗ | ✗ | not stated |
| Low-cost Actor (~2,500 users) | $1.00 + $0.00005 per run | $0.70 + $0.00005 per run | channel, playlist, search | ✓ (one format per run) | ✓ | ✓ | not stated |
| Cheapest per-video Actor (~4,100 users, max 100 transcripts per run) | about $0.02 | about $0.02 | channel | ✓ | ✓ | ✓ | ✓ (except a $0.00001 row fee) |
| **This Actor** | **$3.50** + usage | **$3.50** + usage | ✗ (two-step recipe below) | ✓ (all formats in one run) | ✓ (up to 3) | ✓ (100+ languages) | ✗ ($0.0033 per video checked) |

Prices from public Apify Store listings, checked September 2026 (the four most-used Actors charge the same on Platinum and Diamond as on Gold). With the optional Fast processing add-on this Actor costs $5.00 per 1,000 plus usage, which is not cheaper than the second most-used Actor ($5.00) or the third one on Gold ($5.00).

To be clear: several smaller Actors are much cheaper per video than this one (the two in the table cost $0.02 to $1.00 per 1,000, and others with 1,000 to 2,500 users charge about $0.70 to $1.00 per 1,000, some plus a start fee), and three Actors in the table (the second most-used one and both low-cost ones) accept a channel link directly, which this Actor does not. What this Actor offers is an event fee 30% or more below the four most-used transcript Actors ($3.50 vs $5.00 to $10.00 per 1,000; platform usage is extra here, so the real difference depends on your run), all four output formats in the same row, a language priority list with `matchedLanguage` / `languageUnavailable` on each row, translation into 100+ languages, up to 10,000 videos per run, and a clean stop at your maximum cost per run. Unlike two of the Actors above, videos without captions are not free here ($0.0033 per video checked): every lookup is a real, paid request for us whether or not captions exist, so it is charged at cost-covering price instead of being hidden in a higher per-transcript price. If you mainly need the lowest price per video or channel input in one step, a cheaper Actor may suit you better.

### Not included

- **No AI transcription for videos without captions.** The Actor reads the captions YouTube already has (uploaded or automatic). Videos with no captions return no transcript; the lookup costs $0.0033 (`video-checked`).
- **No video metadata beyond the title.** Channel name, upload date, view, like and comment counts are not included. Get them with our [YouTube Search Scraper](https://apify.com/cheapapi/youtube-search-scraper).
- **No channel, playlist or keyword input.** This Actor can't list a channel's uploads or a playlist's videos by itself. Use the two-step recipe under [Transcripts for a channel, playlist or keyword](#transcripts-for-a-channel-playlist-or-keyword).
- **No comments.** Use our [YouTube Comments Scraper](https://apify.com/cheapapi/youtube-comments-scraper).
- **No list of available caption languages** without fetching a transcript.

### What data you get

One row per video. The fields marked "when selected" depend on **Output formats**.

| Field | Type | Example |
|---|---|---|
| `id` | string | `91562ec09954574c` (stable: same video + delivered language = same ID in every run) |
| `input` | string | `https://www.youtube.com/watch?v=Y8Wu4rSNJms` |
| `videoId` | string | `Y8Wu4rSNJms` |
| `videoUrl` | string | `https://www.youtube.com/watch?v=Y8Wu4rSNJms` |
| `title` | string / null | `How to set up BMW eDrive Modes in the New Generation of BMW Plug-In Hybrids` |
| `transcriptAvailable` | boolean | `true` |
| `language` | string / null | `it` (language of the delivered text) |
| `originalLanguage` | string / null | `en` (language of the captions on YouTube) |
| `isTranslated` | boolean | `true` |
| `translatedTo` | string / null | `it` |
| `isAutoGenerated` | boolean / null | `true` (automatic captions, detected from caption timing) |
| `segmentsCount` | integer | `30` |
| `durationSeconds` | number | `75.12` (end of the last caption line) |
| `wordCount` / `characterCount` | integer | `185` / `1234` |
| `text` | string | `Elettrifica la tua efficienza di guida. La tecnologia ibrida plug-in ...` (when selected) |
| `segments` | array | `[{ "start": 1.12, "end": 6, "duration": 4.88, "text": "..." }]` (when selected) |
| `srt` | string | `1\n00:00:01,120 --> 00:00:06,000\n...` (when selected) |
| `vtt` | string | `WEBVTT\n\n00:00:01.120 --> 00:00:06.000\n...` (when selected) |
| `requestedLanguages` | array / null | `["de", "en"]` (your language list, null when empty) |
| `matchedLanguage` | string / null | `en` (the language from your list that was delivered) |
| `languageUnavailable` | boolean | `false` (`true` = none of your languages existed, default captions delivered) |
| `requestedTranslation` | string / null | `it` |
| `country` | string | `US` |
| `collectedAt` / `scrapedAt` | ISO date (`collectedAt` can be null) | `2026-09-28T15:53:26.688Z` (`collectedAt` = when the captions were collected, `scrapedAt` = when this run started) |
| `reason` | string | `No captions found for this video` (only on rows with `transcriptAvailable: false`) |

**Always filled when `transcriptAvailable` is `true`:** `id`, `input`, `videoId`, `videoUrl`, `transcriptAvailable`, `isTranslated`, `segmentsCount` (at least 1), `durationSeconds`, `wordCount`, `characterCount`, `languageUnavailable`, `country`, `scrapedAt`, and every format you selected (`text`, `segments`, `srt`, `vtt`).
**Can be `null`:** `title`, `language` and `originalLanguage` (when the caption language is not reported), `translatedTo` (no translation), `isAutoGenerated` (fewer than 4 caption lines), `requestedLanguages`, `matchedLanguage` and `requestedTranslation` (when you did not set them, or no language on your list was available), and `collectedAt`.

Rows for videos without a transcript (only when **Include videos without a transcript** is on) contain `id`, `input`, `videoId`, `videoUrl`, `title`, `transcriptAvailable: false`, a `reason`, `requestedLanguages`, `requestedTranslation` and `scrapedAt`.

### How to use

1. Open the Actor in Apify Console and paste video links or IDs into **YouTube videos**. Watch, youtu.be, Shorts, embed and live links all work.
2. Optional: add **Transcript languages** in order of preference (for example `de`, then `en`), and set **Translate to** (for example `es`).
3. Pick the **Output formats** you need. Plain text and segments are selected by default.
4. Leave **Processing speed** on Standard (usually a few minutes) or choose **Fast processing** (about 1 minute, +$0.0015 per video).
5. Optional: set **Maximum cost per run** in the run options.
6. Click **Start**, then download the results as JSON, CSV, Excel or HTML, or read them through the API.

Ready-to-paste input:

```json
{
    "videos": [
        "https://www.youtube.com/watch?v=aircAruvnKk",
        "https://youtu.be/dQw4w9WgXcQ"
    ],
    "transcriptLanguages": ["de", "en"],
    "translateTo": "es",
    "outputFormats": ["text", "segments", "srt"],
    "processingSpeed": "standard"
}
```

#### API

```bash
curl -X POST "https://api.apify.com/v2/acts/cheapapi~youtube-transcript-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"videos":["https://www.youtube.com/watch?v=aircAruvnKk"],"transcriptLanguages":["en"],"outputFormats":["text"]}'
```

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_TOKEN>' });
const run = await client.actor('cheapapi/youtube-transcript-scraper').call({
    videos: ['https://www.youtube.com/watch?v=aircAruvnKk'],
    transcriptLanguages: ['en'],
    outputFormats: ['text', 'segments'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].text);
```

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_TOKEN>")
run = client.actor("cheapapi/youtube-transcript-scraper").call(run_input={
    "videos": ["https://www.youtube.com/watch?v=aircAruvnKk"],
    "transcriptLanguages": ["en"],
    "outputFormats": ["text", "segments"],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item["wordCount"])
```

#### Transcripts for a channel, playlist or keyword

This Actor takes video links or IDs. To find videos first, run our [YouTube Search Scraper](https://apify.com/cheapapi/youtube-search-scraper) with a topic, keyword or channel name (sort by upload date and keep only `video` rows), then pass its `url` or `videoId` values into **YouTube videos**. Objects with a `url` field (`[{"url": "https://..."}]`) are accepted too.

Note that search results for a channel name usually include the channel's recent videos, but they are not a complete upload list and can include other channels' videos (filter on `channelId`). For a complete channel or playlist, paste the video links you have, or use an Actor that accepts channel links (see the comparison above).

### Use cases

- **AI and LLM pipelines**: summarize videos, build RAG knowledge bases, generate notes or quizzes from lectures.
- **Content repurposing**: turn videos into blog posts, newsletters, show notes and social posts.
- **SEO and research**: analyze what competitors say in their videos, mine keywords and topics at scale.
- **Subtitles and localization**: export SRT/VTT files and translate captions into other languages.
- **Media monitoring**: track mentions of brands, products or people across many videos.
- **Accessibility and archiving**: keep searchable text copies of your own video library.

### Advanced options

| Option | Default | Meaning |
|---|---|---|
| **Transcript languages** (`transcriptLanguages`) | empty | Up to 3 caption language codes in order of preference (e.g. `de`, `en`, `pt-BR`, `zh-Hans`). Each video gets the first one it has captions in; if it has none, its default captions (`languageUnavailable: true`). Empty = the video's default captions. Each further language tried for a video costs $0.0033 (`extra-lookup`) |
| **Translate to** (`translateTo`) | empty | Translate the transcript into this language: pick a common one from the list (English, Spanish, German, Japanese, Chinese...) or type any code YouTube supports (100+ languages) |
| **Output formats** (`outputFormats`) | `text`, `segments` | Any of `text`, `segments`, `srt`, `vtt` |
| **Processing speed** (`processingSpeed`) | `standard` | Standard: usually a few minutes (up to ~45 minutes at peak times); each transcript is saved as soon as it is ready. Fast processing: about 1 minute, +$0.0015 per lookup (normally one per video) |
| **Timestamps in plain text** (`includeTimestampsInText`) | `false` | `text` becomes one line per caption with a `[m:ss]` prefix |
| **Include videos without a transcript** (`includeVideosWithoutTranscript`) | `false` | Adds a row with `transcriptAvailable: false` and a `reason` (no charge for the row; the lookup itself is `video-checked`) |
| **Max videos** (`maxVideos`) | `0` (no limit) | Process only the first N videos of the list (up to 10,000) |
| **Only new videos** (`onlyNewVideos`) | `false` | Skip videos whose transcript an earlier run with this option already delivered (same **Transcript languages** and **Translate to**). Skipped videos are not requested and cost nothing; videos that had no transcript are checked again. **Max videos** then counts only new videos |
| **Processed videos store name** (`processedVideosStore`) | `youtube-transcripts-processed` | Key-value store in your Apify account that remembers the delivered videos. Use one name per project or channel; delete the store to start over |
| **Country** (`country`) | `US` | Country YouTube is opened from (code or name). Matters for region-restricted videos |
| **Interface language** (`interfaceLanguage`) | `en` | Language of the YouTube interface (not the transcript language) |
| **Operating system** (`operatingSystem`) | `windows` | `windows` or `macos` desktop browser |
| **Device** (`device`) | `desktop` | Only desktop is supported for transcripts |

How the language list works: the first language is requested for every video. Only videos that don't have it are asked again for the next language on your list, so a fallback adds processing time but never adds cost. If captions come back in another language that is also on your list, they are accepted without another request.

### Output example

Example output (text and segments shortened; this sample is an Italian translation of English captions):

```json
{
    "id": "91562ec09954574c",
    "input": "https://www.youtube.com/watch?v=Y8Wu4rSNJms",
    "videoId": "Y8Wu4rSNJms",
    "videoUrl": "https://www.youtube.com/watch?v=Y8Wu4rSNJms",
    "title": "How to set up BMW eDrive Modes in the New Generation of BMW Plug-In Hybrids",
    "transcriptAvailable": true,
    "language": "it",
    "originalLanguage": "en",
    "isTranslated": true,
    "translatedTo": "it",
    "isAutoGenerated": true,
    "segmentsCount": 30,
    "durationSeconds": 75.12,
    "wordCount": 185,
    "characterCount": 1234,
    "text": "Elettrifica la tua efficienza di guida. La tecnologia ibrida plug-in delle BMW con sistema operativo 8 ti offre il contr ...",
    "segments": [
        { "start": 1.12, "end": 6, "duration": 4.88, "text": "Elettrifica la tua efficienza di guida. La tecnologia" },
        { "start": 3.679, "end": 8.48, "duration": 4.801, "text": "ibrida plug-in delle BMW con" }
    ],
    "srt": "1\n00:00:01,120 --> 00:00:06,000\nElettrifica la tua efficienza di guida. La tecnologia\n\n2\n00:00:03,679 --> 00:00:08,480\nibrida plug-in delle BMW con\n...",
    "requestedLanguages": ["de", "en"],
    "matchedLanguage": "en",
    "languageUnavailable": false,
    "requestedTranslation": "it",
    "country": "US",
    "collectedAt": "2026-09-27T03:12:15.000Z",
    "scrapedAt": "2026-09-29T05:07:23.113Z"
}
```

The `RUN_SUMMARY` record in the key-value store lists how many transcripts were delivered, how many already processed videos were skipped (`skippedAlreadyProcessed`), which videos had none (and why), the processing speed used, how many fallback-language requests were needed, and how many transcripts were delivered in a language outside your list.

### Pricing

**Typical cost: $0.35 for 100 videos with captions ($3.50 per 1,000), plus Apify platform usage billed separately.**

**Apify Free plan:** Apify does not pay developers for usage on its Free plan, so on the Free plan this Actor can be used for up to **$0.25 of results per calendar month** — enough to try it on a small input. When the allowance is used up, the run ends with a clear message (not an error). Any paid Apify plan removes the limit; prices are the same.

Pay per event, the same price on every plan. Every lookup we make for a video is paid by exactly one of these events:

| Event | Price (all plans) | When |
|---|---|---|
| `transcript` | **$0.0035** ($3.50 per 1,000) | A video whose transcript is delivered (pays for its first lookup) |
| `video-checked` | $0.0033 | A video that was looked up but has no transcript: no captions, none in your languages, or no data (private, removed, age-restricted) |
| `extra-lookup` | $0.0033 | Each additional lookup because a video lacks the first language on your **Transcript languages** list (the next language, or its default captions) |
| `fast-processing` | $0.0015 | Optional add-on, only with **Fast processing (about 1 minute)**: once per lookup |

Invalid links, lookups the data source rejects, videos skipped by **Only new videos**, and videos skipped because of your maximum cost are free. A lookup that was accepted but could not be collected in time, or whose submission got no answer because of a network problem, may already have been paid, so it is charged like a lookup without a transcript (`video-checked`, or `extra-lookup` for a later language). There is no start fee.

Apify platform usage is billed separately by Apify (at the default 256 MB a small run typically uses about $0.001–$0.005). Standard processing waits for results, so runs last longer than a quick lookup and use more: roughly 0.02 compute units (about $0.005–$0.01) per 5 minutes of run time at 256 MB. Fast processing shortens the run. The prices and examples below are event fees only.

With an empty **Transcript languages** list every video is exactly one lookup; with languages, a video that has your first language is also one lookup.

Examples:

- **100 videos**, standard: 100 x $0.0035 = **$0.35**.
- **1,000 videos** with fast processing: 1,000 x ($0.0035 + $0.0015) = **$5.00**.
- **10,000 videos**, standard, 9,200 of them with captions: 9,200 x $0.0035 + 800 x $0.0033 = **$34.84**.
- **1 video, languages `de`, `en`**, the video only has English: $0.0033 (`extra-lookup`) + $0.0035 = **$0.0068**.
- **1 video, languages `de`, `en`, `es`**, the video has no captions and every language answers "not available" (worst case): $0.0033 (`video-checked`) + 3 x $0.0033 (`extra-lookup`: `en`, `es`, default captions) = **$0.0132**. The same video without a language list: **$0.0033**.

Set **Maximum cost per run** in the run options. The Actor stops cleanly when the limit is reached (the add-on and any extra lookups are included in the calculation), and you are never charged past it. When the limit leaves no room to try another language, the video keeps the best result found so far.

### Integrations

Connect the Actor to **Make**, **Zapier**, **n8n**, **Google Sheets**, Slack or your own backend with Apify integrations and **webhooks** (for example, a webhook on "run succeeded" that pushes transcripts into your app). Use **Schedules** to process new videos daily. Use the **API** (`run-sync-get-dataset-items`) to get transcripts in a single HTTP call, or the Apify **MCP server** to let AI agents call the Actor.

### FAQ

**Is there a limit on the Apify Free plan, and is platform usage included?**
Free plan: up to $0.25 of this Actor's results per calendar month, enough to try it. Apify pays developers nothing for Free-plan usage while our data costs are real, so this keeps the Actor sustainable. Runs that reach the allowance stop cleanly and keep everything collected so far; the allowance resets on the 1st of the month. Any paid Apify plan has no limit. Platform usage (compute) is not included on any plan: Apify bills it separately. At the default 256 MB a small run typically uses about $0.001–$0.005; a standard run that waits longer uses roughly $0.005–$0.01 per 5 minutes. Each run's usage is shown in Apify Console.

**Is it legal to scrape YouTube transcripts?**
The Actor collects captions that YouTube shows publicly to every visitor. You are responsible for how you use the text: respect copyright, YouTube's terms and privacy law (e.g. GDPR) in your use case. When in doubt, ask a lawyer.

**How fresh is the data?**
Every transcript is collected live when you run the Actor. `collectedAt` shows when.

**How long does a run take?**
Standard processing usually delivers results within a few minutes (up to ~45 minutes at peak times). You don't have to wait for the whole run: each transcript is saved to the dataset as soon as it is ready, and the log shows how many are ready with an estimate of the time left. With **Fast processing** most runs finish in about 1 minute. Each fallback-language round adds roughly the same time again, but only for the videos that need it.

**Why did I get fewer results than videos?**
Some videos have no captions at all (captions disabled, music without lyrics, very new uploads), are private, age-restricted or removed, or the maximum cost per run was reached. They are listed with a reason in `RUN_SUMMARY` (or as rows when **Include videos without a transcript** is on).

**What happens when a video doesn't have my language?**
The Actor tries the next language on your **Transcript languages** list. If the video has none of them, you get its default captions with `languageUnavailable: true` and `matchedLanguage: null`, so you can filter those rows. To always get text in your language, also set **Translate to**.

**Why was I charged `video-checked` or `extra-lookup`? Do I pay for videos without a transcript?**
Yes, a little. `video-checked` ($0.0033) is charged once for each video that was looked up but has no transcript to deliver (no captions, none in your languages, or no data for the video): checking a video costs us the same whether or not it has captions, and charging that lookup separately keeps the transcript price low instead of spreading the cost over every delivered transcript. Invalid links, videos skipped by **Only new videos** and videos not requested because of your maximum cost are free. `extra-lookup` ($0.0033) is charged for each additional lookup made because a video lacks the first language on your **Transcript languages** list. `RUN_SUMMARY` shows `videosCheckedCharged`, `extraLookupsCharged` and `languageFallbackRequests`. To avoid extra lookups, leave **Transcript languages** empty (default captions) or put the language most of your videos have first, and use **Translate to** for everything else.

**How do I control my spending?**
Set **Maximum cost per run** in the run options, or use **Max videos** to cap a long list. The run stops before the limit and `RUN_SUMMARY` shows `stoppedByBudget: true`.

**Can I scrape a whole channel or playlist, or monitor one regularly?**
Not directly: this Actor needs video links or IDs. Our [YouTube Search Scraper](https://apify.com/cheapapi/youtube-search-scraper) can find a channel's recent videos by searching for its name, but that is not a guaranteed complete list (see [Transcripts for a channel, playlist or keyword](#transcripts-for-a-channel-playlist-or-keyword)). To monitor, schedule a YouTube Search Scraper run and chain this Actor with a webhook or a Make/Zapier scenario, with **Only new videos** on: videos already delivered by an earlier run are skipped before any request and cost nothing. Use a separate **Processed videos store name** per channel or project. Each row's `id` also stays the same across runs for the same video and language, so you can deduplicate on `id` when you store results.

**Which export formats are available?**
JSON, JSONL, CSV, Excel, XML, HTML and RSS from the dataset. SRT and VTT files come as strings in each row; save them as `.srt` / `.vtt`.

**Where do I get help?**
Open an issue on the Actor's **Issues** tab in Apify Console. We read and answer every issue.

### Limitations

- `isAutoGenerated` is detected from caption timing, not read from YouTube, and may be wrong for unusual caption files.
- Translations are machine translations provided by YouTube.
- The language list accepts up to 3 languages.
- Private, members-only and removed videos can't be processed. Region-restricted videos may need the right **Country**.
- Standard processing usually takes a few minutes and can take up to ~45 minutes at peak times (transcripts are saved as they arrive). Choose **Fast processing** (paid add-on) if you need results in about a minute.
- **Only new videos** remembers up to 100,000 delivered videos per store and language setting; videos without a transcript are not remembered and are checked (and charged) again.

### Privacy

The Actor collects only public caption text, the video title and the link. It does not collect viewer data, comments or account information. Captions can contain names or other personal data spoken in a video. If you store or publish transcripts, you are responsible for handling such data lawfully (for example under GDPR).

# Actor input Schema

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

Video links or 11-character video IDs (youtube.com/watch, youtu.be, Shorts, embed and live links). One result row per video. Channel and playlist links are not accepted: to find videos by keyword or channel name, run our YouTube Search Scraper (cheapapi/youtube-search-scraper) first and paste its url or videoId values here (search results, not a complete upload list).

## `transcriptLanguages` (type: `array`):

Up to 3 caption language codes, best first (e.g. en, then de, then es; also pt-BR, zh-Hans). Each video gets the first language on the list that it has captions in. If it has none of them, you get its default captions and the row is marked languageUnavailable = true. Leave empty for the video's default captions. Each further language tried for a video adds processing time and costs $0.0033 (extra-lookup); a video that has your first language is a single lookup.

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

Optional: translate every transcript into this language. Pick one of the common languages from the list, or type any other language code YouTube supports (100+ languages, e.g. sv, el, he, fa). Leave empty for no translation. Translations are machine translations made by YouTube.

## `outputFormats` (type: `array`):

Which transcript formats to include in each row. Plain text and timestamped segments by default; add SRT and/or WebVTT subtitle files as strings.

## `processingSpeed` (type: `string`):

Standard: results usually within a few minutes (can take up to ~45 minutes at peak times); each transcript is saved to the dataset as soon as it is ready, and the log shows the progress with an estimate of the time left. Fast processing: about 1 minute, for an extra $0.0015 per lookup (normally one per video; also for the video-checked and extra-lookup events).

## `includeTimestampsInText` (type: `boolean`):

Put each caption line on its own line with a \[m:ss] timestamp in the "text" field instead of one continuous paragraph.

## `includeVideosWithoutTranscript` (type: `boolean`):

Also add a row for videos that have no captions, with transcriptAvailable = false and a short reason. The row itself is free; the lookup of such a video is charged as video-checked ($0.0033) either way. Off by default; they are always listed in the run summary.

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

Stop after this many videos from the list (0 = no limit). Useful for testing a long list.

## `onlyNewVideos` (type: `boolean`):

Skip videos whose transcript an earlier run with this option already delivered (with the same Transcript languages and Translate to settings). Skipped videos are not requested and cost nothing. Videos that had no transcript are checked again (and charged as video-checked) because captions are often added later. "Max videos" then counts only new videos.

## `processedVideosStore` (type: `string`):

Name of the key-value store in your Apify account that remembers the delivered videos (lowercase letters, digits and hyphens). Use a different name per project or channel to keep separate lists; delete the store to start over. Default: youtube-transcripts-processed.

## `country` (type: `string`):

Country YouTube is opened from, as a code or name (US, GB, DE, "Germany"). Matters only for videos that are region-restricted. Default: US.

## `interfaceLanguage` (type: `string`):

Language of the YouTube interface (code such as en, de, es). This is not the transcript language; use "Transcript languages" for that. Default: en.

## `operatingSystem` (type: `string`):

Operating system of the desktop browser YouTube is opened with.

## `device` (type: `string`):

Device type YouTube is opened with. Only desktop is supported for transcripts.

## Actor input object example

```json
{
  "videos": [
    "https://www.youtube.com/watch?v=aircAruvnKk"
  ],
  "transcriptLanguages": [],
  "outputFormats": [
    "text",
    "segments"
  ],
  "processingSpeed": "standard",
  "includeTimestampsInText": false,
  "includeVideosWithoutTranscript": false,
  "maxVideos": 0,
  "onlyNewVideos": false,
  "processedVideosStore": "youtube-transcripts-processed",
  "country": "US",
  "interfaceLanguage": "en",
  "operatingSystem": "windows",
  "device": "desktop"
}
```

# Actor output Schema

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

No description

## `summary` (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=aircAruvnKk"
    ],
    "outputFormats": [
        "text",
        "segments"
    ],
    "processingSpeed": "standard"
};

// Run the Actor and wait for it to finish
const run = await client.actor("cheapapi/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=aircAruvnKk"],
    "outputFormats": [
        "text",
        "segments",
    ],
    "processingSpeed": "standard",
}

# Run the Actor and wait for it to finish
run = client.actor("cheapapi/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=aircAruvnKk"
  ],
  "outputFormats": [
    "text",
    "segments"
  ],
  "processingSpeed": "standard"
}' |
apify call cheapapi/youtube-transcript-scraper --silent --output-dataset

```

## MCP server setup

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