# YouTube Transcript API (`catalyst-labs/youtube-transcript-api`) Actor

YouTube transcripts with timestamps and full video metadata from videos, Shorts, playlists, channels and search. Language choice, auto vs human captions flagged, SRT/VTT/text, incremental channel monitoring. Pay only for delivered transcripts.

- **URL**: https://apify.com/catalyst-labs/youtube-transcript-api.md
- **Developed by:** [Catalyst Labs](https://apify.com/catalyst-labs) (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 $5.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

### What is YouTube Transcript API?

**YouTube Transcript API** returns clean, timestamped **transcripts with full video metadata** for any public YouTube video, Short, playlist, channel or search term, in bulk. Every result says which **language** it is in and whether the captions are **human-made or auto-generated**. Output comes as paragraph text, **LLM-ready text** (sound cues like \[Music] and ♪ removed), timestamped segments, **SRT** or **WebVTT**.

You **pay only for transcripts delivered**. Videos without captions, private or deleted videos, live streams, invalid links and anything YouTube blocks are reported with a clear status and a fix hint, and are **never charged**.

On Apify you also get an API, MCP access for AI agents, scheduling, webhooks and integrations (Make, Zapier, n8n, Google Sheets and more).

### How to use it

1. Paste videos, Shorts, playlists, channel URLs or `@handles` into **YouTube videos...** (one per line), and/or add **search terms**.
2. Set **Max videos per source** (channels return newest first), an optional **date range**, and your **preferred languages**.
3. Click **Start**. Each video becomes one row in the **Output** tab: title, channel, subscribers, publish date, views, likes, comments, duration, language, text and segments.

***

### For AI agents

**What it does:** turns YouTube videos into text an LLM can read, with timestamps for citing. One dataset record per video.

**Minimal input:**

```json
{ "videos": ["https://www.youtube.com/watch?v=jNQXAC9IVRw"] }
```

**Channel research input:**

```json
{ "videos": ["https://www.youtube.com/@veritasium"], "maxVideosPerSource": 10, "publishedAfter": "30 days", "outputFormats": ["text"] }
```

- **MCP tool name:** `catalyst-labs--youtube-transcript-api` (connect `https://mcp.apify.com/?tools=catalyst-labs/youtube-transcript-api`).
- **Cost:** $0.008 per delivered transcript on the Free plan ($0.007 Bronze, $0.006 Silver, $0.005 Gold and above), with no run-start fee. A first call with 1 video costs $0.008; a call that delivers nothing costs nothing. Every requested format (text, LLM-ready text, segments, SRT, VTT) and the metadata are included in the one transcript price. Failed, filtered and skipped videos are free. Pass `maxTotalChargeUsd` in the run options for a hard cap; videos beyond it are marked `SPENDING_LIMIT` and the run still ends as SUCCEEDED. `maxVideosPerSource` (default 50) limits channels, playlists and searches.
- **Key output fields:** `videoId`, `url`, `status` (`success`/`failed`/`skipped`), `title`, `channelName`, `channelId`, `subscriberCount`, `publishDate`, `viewCount`, `likeCount`, `commentCount`, `durationSeconds`, `keywords`, `thumbnailUrl`, `language`, `isAutoGenerated`, `requestedLanguageFound`, `languageFallback`, `originalLanguage`, `availableLanguages`, `text`, `llmText` (with `outputFormats: ["llm"]`), `punctuatedText`, `punctuatedSegments`, `punctuationRestored` and `punctuationSource` (with `punctuate: true`), `segments` (`start`, `duration`, `text` in seconds), `srt`, `vtt`, `wordCount`, `errorType`, `retryable`, `hint`.
- **Error types** (every failed row has `retryable: true/false`): `NO_CAPTIONS`, `CAPTIONS_NOT_READY` (published under 24 h ago, no captions yet; retry later), `LANGUAGE_NOT_AVAILABLE`, `TRANSLATION_UNAVAILABLE`, `VIDEO_UNAVAILABLE`, `AGE_RESTRICTED`, `MEMBERS_ONLY`, `LIVE_STREAM`, `SOURCE_EMPTY`, `INVALID_INPUT`, `BLOCKED`, `NETWORK_ERROR`, `SPENDING_LIMIT`.
- **Speed:** about 300 videos in 3.5 minutes at `maxConcurrency` 10 (cloud test, October 2026).
- **Punctuation restoration (opt-in, `punctuate: true`):** adds about 3 to 10 seconds per 1,000 words, only on the tracks that need it, at the default 512 MB. More memory makes it faster.
- **Known limits:** videos without captions are reported, not charged (no audio transcription). Age-restricted and members-only videos are not supported. YouTube's machine translation (`translateTo`) is best effort: YouTube usually refuses it for server traffic (HTTP 429 in our October 2026 tests), and then the original-language captions are returned with a `warning`. Translate `text` with your own LLM or translation service if you need another language. `subscriberCount` and `commentCount` are the rounded values YouTube displays (for example 2.4M).

### When to choose this tool

Facts you can check in the output:

- **Bulk sources in one run:** videos, Shorts, playlists, channels (`@handle`, `/channel/UC...`, plus `/shorts` and `/streams` tabs) and YouTube search terms (relevance, newest, most viewed or Shorts only), de-duplicated.

- **Newest N, date range and incremental monitoring:** `maxVideosPerSource`, `publishedAfter`/`publishedBefore` (exact upload dates) and `onlyNewVideos`, which on a schedule returns only uploads published since the last run.

- **Language control with honest flags:** preferred-language list where `en` also matches regional tracks (en-GB, en-US) and a human-made track in any variant is used before an auto-generated one; if no requested language exists, the video's original spoken language is returned and flagged (`requestedLanguageFound: false`, `languageFallback: "originalLanguage"`, plus a `warning`). `isAutoGenerated`, `originalLanguage` and `availableLanguages` are on every record.

- **Five formats per transcript at one price:** paragraph text, LLM-ready text (`llmText`: \[Music], \[Applause], (laughs), ♪ and >> markers removed; the raw `text` is kept), timestamped segments, SRT and WebVTT.

- **Punctuation for auto-captions that have none (opt-in, no extra charge):** YouTube punctuates most new auto-generated captions, but older uploads often come as one lowercase stream (`so today i want to talk about stress how many of you`). In our October 2026 sample, 6 of 26 auto-caption tracks had no punctuation, and all 6 were uploaded before 2026. With `punctuate: true`, those tracks get sentence punctuation and capitalization from a model that runs inside the Actor, returned as `punctuatedText` and `punctuatedSegments` (same timestamps), and used in `llmText`. The raw `text` and `segments` never change. Human-made captions and auto-captions YouTube already punctuated are left alone (`punctuationSource`: `creator` or `youtube`). Restored tracks are marked `punctuationRestored: true`. On 8 videos (about 44,000 words), we scored the model against the creators' own captions: F1 0.59 for sentence ends, 0.48 for commas, 0.54 for question marks and 0.73 for capitalization. It reads much better than unpunctuated text, but it is less accurate than YouTube's own punctuation where YouTube provides it. Supports English and 44 other space-separated languages, but not Japanese, Chinese or Thai.

- **Rich metadata for niche research:** title, channel, channel subscriber count, publish date, views, likes, comment count, duration, tags, thumbnail and optional description, in the same transcript price.

- **Built-in anti-blocking:** if YouTube blocks the server, the Actor switches automatically to Apify datacenter and then residential proxy, at no extra charge to you.

- **Tested before release (October 2026, Apify cloud):** 299 of 300 videos from 6 large channels delivered (the other had no captions); in a mixed 51-item test, every captioned video was delivered and every failure (no captions, deleted, live, invalid) was reported correctly and not charged. Covered English, Spanish, Japanese, German and Hindi videos, Shorts, and videos up to 7.7 hours long.

- **Priced per delivered transcript only, at $0.008 on the Free plan down to $0.005 on Gold, with no run-start fee.** Failures are written as free rows with `errorType`, `retryable` and `hint`; very fresh uploads without captions yet are reported as `CAPTIONS_NOT_READY` (retryable) rather than `NO_CAPTIONS`. For comparison (Apify Store pricing as listed on 18 Oct 2026): several popular YouTube transcript Actors charge the generic per-dataset-row event (`apify-default-dataset-item`), and some also charge a per-run start event (`apify-actor-start`), while this Actor charges only its `transcript` event, so rows for failed videos and runs that deliver nothing cost nothing.

- **Run summary for automations:** the `OUTPUT` record lists every input with its status, counts and a fix hint.

Choose a different tool when you need transcripts for videos **without** captions (speech-to-text), the text of comments and replies (this Actor returns only the comment count), or translations into a language the video has no captions in.

### Who is it for?

#### YouTubers and creators (including faceless channels)

- **Competitor and niche research:** pull the last 50 videos of every channel in your niche with views, likes and publish dates, then see which topics, hooks and structures actually get views.
- **Scriptwriting:** study how top videos open, pace and close. Feed transcripts to your LLM to outline a script in your own voice, not to copy.
- **Repurposing:** turn your own videos into blog posts, newsletters, threads, Shorts scripts and chapters, with timestamps intact (SRT/VTT for subtitles).

#### Automation and bot-run channel operators

- **Daily competitor monitoring:** schedule `onlyNewVideos` on a list of channels and get only the new uploads' transcripts, ready for your pipeline (Make, n8n, Zapier, Sheets, webhooks).
- **Clean inputs for content pipelines:** stable JSON fields, clear `errorType` on every failure, and a run summary so automations never break on an empty video.

#### AI agents and LLM apps

- One MCP tool call gives an agent the transcript and metadata of any video, channel or search, with timestamps for citations and a spending cap.

#### Researchers and teams

- Build searchable corpora from channels or search results, by language and date.

### Input example

```json
{
  "videos": ["https://www.youtube.com/@mkbhd", "https://www.youtube.com/playlist?list=PLFgquLnL59alCl_2TQvOiD5Vgm1hCaGSI", "https://youtu.be/dQw4w9WgXcQ"],
  "searchQueries": ["faceless youtube channel ideas"],
  "maxVideosPerSource": 20,
  "publishedAfter": "60 days",
  "languages": ["en", "es"],
  "outputFormats": ["text", "segments", "srt"]
}
```

### Output example

```json
{
  "videoId": "jNQXAC9IVRw",
  "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
  "status": "success",
  "title": "Me at the zoo",
  "channelName": "jawed",
  "channelId": "UC4QobU6STFB0P71PMvOGN5A",
  "durationSeconds": 19,
  "viewCount": 445125794,
  "publishDate": "2005-04-23",
  "likeCount": 20089124,
  "commentCount": 10000000,
  "subscriberCount": 6700000,
  "language": "en",
  "isAutoGenerated": false,
  "requestedLanguageFound": true,
  "languageFallback": null,
  "originalLanguage": "en",
  "availableLanguages": [{ "languageCode": "en", "name": "English", "isAutoGenerated": false }, { "languageCode": "de", "name": "German", "isAutoGenerated": false }],
  "text": "All right, so here we are, in front of the elephants ...",
  "segments": [{ "start": 1.2, "duration": 2.16, "text": "All right, so here we are, in front of the elephants" }],
  "wordCount": 39,
  "charged": true
}
```

A video without captions:

```json
{ "videoId": "8c7KOGxeY3w", "status": "failed", "errorType": "NO_CAPTIONS", "retryable": false, "hint": "The video has no captions (not even auto-generated). Nothing was charged.", "title": "...", "charged": false }
```

With `outputFormats: ["text", "llm"]`, a music video's `text` keeps the captions as written (`♪ We're no strangers to love ♪ ...`) and `llmText` drops the annotations (`We're no strangers to love ...`).

### How much does it cost?

Pay per event. You pay only for transcripts delivered, with no run-start fee and no separate charge for Apify platform usage or proxies. Prices drop with your Apify plan.

| Event | Free | Bronze | Silver | Gold and above |
| --- | --- | --- | --- | --- |
| Transcript delivered (one video, all formats + metadata) | $0.008 | $0.007 | $0.006 | $0.005 |

**Never charged:** videos without captions, private, deleted, age-restricted or members-only videos, live streams, invalid links, blocked requests, videos filtered out by date or monitoring, and videos skipped by your spending cap.

**Cost examples (Free plan):**

- 1 video: $0.008.
- The last 50 videos of one channel: $0.40.
- 1,000 transcripts: $8 ($5 on Gold).
- Daily monitoring of 20 channels that post about 1 video a day each (`onlyNewVideos`): about $0.16 a day (about $0.10 on Gold).

Set `maxTotalChargeUsd` in the run options (or "Max cost per run" in Console) to put a hard ceiling on any run.

### FAQ

**Are auto-generated captions included?** Yes, unless you choose "Human-made only". Every record has `isAutoGenerated`, so you can filter.

**Why do some auto-generated transcripts have no punctuation?** YouTube adds punctuation to most new auto-captions but not to many older ones. Set `punctuate: true` to restore it on those tracks, at no extra charge. The result is in `punctuatedText`, and `text` stays exactly as YouTube sent it. See "When to choose this tool" for measured accuracy.

**What happens with videos that have no captions?** They are reported as `NO_CAPTIONS` (`retryable: false`) and not charged. If the video was published less than 24 hours ago, it is reported as `CAPTIONS_NOT_READY` (`retryable: true`), because YouTube usually adds auto-generated captions within a few hours. This Actor does not transcribe audio.

**I asked for English but the video is in German. What do I get?** With the default settings, the German captions (human-made if they exist), with `requestedLanguageFound: false`, `languageFallback: "originalLanguage"`, `originalLanguage: "de"` and a `warning`. Turn off **Fall back to the video's original language** to get a free `LANGUAGE_NOT_AVAILABLE` row instead.

**Why not YouTube's auto-translate?** YouTube serves its machine translations to its own apps but usually refuses them for automated server requests. Some tools work around this by running a separate machine-translation service on the original captions. This Actor returns the original captions and flags them, so you can translate them with the model or service you already use.

**Do I need a proxy?** No. The Actor handles YouTube blocking itself and switches proxies automatically at no extra cost. You can still set your own proxy.

**How does incremental monitoring work?** Turn on **Only new videos** and give the monitor a name. The first run backfills up to "Max videos per source"; later runs return only videos uploaded since. Schedule it daily in Apify.

**Is the publish date exact?** Yes, `publishDate` is the upload date shown on the video page (day precision). Date filters use it.

**Is it legal?** It reads publicly available captions and metadata. You are responsible for how you use transcripts (copyright, YouTube's terms). Use them for research, analysis and your own content, not to republish others' work.

**Something broke?** Open an issue on the **Issues** tab with the video URL and run ID.

# Actor input Schema

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

One per line: video, Shorts or youtu.be links, 11-character video IDs, playlist URLs, or channel URLs/@handles (add /shorts or /streams for those tabs). Channels return newest videos first.

## `searchQueries` (type: `array`):

Optional. Each term is searched on YouTube and its top videos are transcribed (up to "Max videos per source").

## `searchSort` (type: `string`):

How search results are ordered.

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

Cap per playlist, channel tab or search term (newest first for channels). 0 = all. Single video links are always included.

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

Overall cap across all sources. 0 = no cap.

## `publishedAfter` (type: `string`):

Only videos published on/after this date: YYYY-MM-DD or relative like "30 days". Uses exact upload dates.

## `publishedBefore` (type: `string`):

Only videos published on/before this date: YYYY-MM-DD or relative like "7 days".

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

Skip videos this monitor already delivered in earlier runs (not charged). Schedule the run daily to track competitor channels.

## `monitorId` (type: `string`):

Optional name for the incremental-monitoring memory, e.g. "competitors-tech". Defaults to the list of sources.

## `languages` (type: `array`):

Caption languages in order of preference (ISO codes, e.g. en, es, pt-BR). The first one available is returned. Regional variants count: "en" also matches en-GB and en-US, and a human-made track in any variant is used before an auto-generated one.

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

Which caption tracks may be used. Every result says whether it is auto-generated.

## `preferManual` (type: `boolean`):

When both exist in a language (including regional variants such as en-GB / en-US), use the human-made track.

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

Optional ISO code, best effort. If none of the preferred languages exists, ask YouTube for its machine translation. YouTube often refuses these requests from servers; then the original captions are returned with a warning (or TRANSLATION_UNAVAILABLE if fallback is off). Never charged when it fails.

## `fallbackToAnyLanguage` (type: `boolean`):

If no preferred language (or translation) exists, return the video's original spoken language (human-made track if there is one), or the best available track, instead of failing. The result then has requestedLanguageFound=false, languageFallback ("originalLanguage" or "anyLanguage") and a warning.

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

One or more formats per transcript. All formats cost the same. "LLM-ready text" adds llmText: the same words with sound cues (\[Music], \[Applause], (laughs)), music notes and >> speaker markers removed; the raw text field is unchanged.

## `punctuate` (type: `boolean`):

Some YouTube auto-generated captions come as one long lowercase stream with no punctuation. When enabled, those tracks get sentence punctuation (. , ?) and capitalization restored by a built-in model, returned as punctuatedText (and punctuatedSegments). The raw text and segments are never changed. Human-made captions and auto-captions YouTube already punctuated are left as they are. No extra charge. Supported: English and 44 other space-separated languages (not Japanese/Chinese).

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

Title, channel, duration, views, tags, thumbnail.

## `includeDetails` (type: `boolean`):

Adds publishDate, likeCount, commentCount and the channel's subscriberCount (one extra request per video, no extra charge). YouTube rounds comment counts above 1,000 and subscriber counts (e.g. 2.4M), so those are approximate. Turned on automatically when you use a date filter.

## `includeDescription` (type: `boolean`):

Adds the full video description.

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

Leave empty for automatic mode: the Actor starts without a proxy and, if YouTube blocks it, switches to Apify datacenter and then residential proxy at no extra cost to you. Set your own proxy here to override.

## `disableAutoProxy` (type: `boolean`):

Only for debugging: never switch to a proxy automatically.

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

Videos fetched in parallel.

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

Retries with backoff (and a fresh proxy session) after rate limits or network errors.

## Actor input object example

```json
{
  "videos": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    "https://www.youtube.com/@TED"
  ],
  "searchSort": "relevance",
  "maxVideosPerSource": 5,
  "maxVideos": 0,
  "onlyNewVideos": false,
  "languages": [
    "en"
  ],
  "captionType": "any",
  "preferManual": true,
  "fallbackToAnyLanguage": true,
  "outputFormats": [
    "text",
    "segments"
  ],
  "punctuate": false,
  "includeMetadata": true,
  "includeDetails": true,
  "includeDescription": false,
  "disableAutoProxy": false,
  "maxConcurrency": 5,
  "maxRetries": 3
}
```

# Actor output Schema

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

Records with text, LLM-ready text, segments, SRT/VTT and metadata (plus punctuatedText/punctuatedSegments with punctuate: true).

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

Counts, error types and charged events.

# 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=jNQXAC9IVRw",
        "https://www.youtube.com/@TED"
    ],
    "maxVideosPerSource": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("catalyst-labs/youtube-transcript-api").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=jNQXAC9IVRw",
        "https://www.youtube.com/@TED",
    ],
    "maxVideosPerSource": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("catalyst-labs/youtube-transcript-api").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=jNQXAC9IVRw",
    "https://www.youtube.com/@TED"
  ],
  "maxVideosPerSource": 5
}' |
apify call catalyst-labs/youtube-transcript-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,catalyst-labs/youtube-transcript-api"
        }
    }
}
```

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/9ffm7oCsXgtaDkJzr/builds/2bVxX1Pz8wHZhPwbH/openapi.json
