# YouTube Transcripts: Videos, Playlists & Channels (`t3data/youtube-transcripts`) Actor

Get YouTube transcripts as clean text, timestamped segments, SRT, or AI-ready chunks for RAG. Paste videos, whole playlists or channels, pick your languages, and never pay for videos without captions.

- **URL**: https://apify.com/t3data/youtube-transcripts.md
- **Developed by:** [T3 Data](https://apify.com/t3data) (community)
- **Categories:** Videos, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 transcripts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## YouTube Transcripts: Videos, Playlists & Channels

A **YouTube transcript API** with no API key and no quota. Paste a video, a playlist or a whole channel and get every transcript as clean text, timestamped segments, SRT subtitles or **AI-ready chunks for RAG**. **You only pay for transcripts you get**: videos without captions are free.

| | |
|---|---|
| 💲 **Price** | $5 per 1,000 transcripts. Failed videos are free. |
| ⚡ **Speed** | ~60 transcripts in 20–30 seconds |
| 📥 **Input** | Video URLs or IDs, Shorts, live replays, playlists, channels (`@handle`) |
| 📤 **Output** | Text, timestamped segments, SRT, RAG chunks, video metadata |
| 🌍 **Languages** | Any language YouTube has. You set the order of preference. |

### What people use it for

- **AI / LLM pipelines**: load chunks into a vector database, or feed transcripts to summarizers and agents
- **Content repurposing**: turn videos into blog posts, newsletters, show notes and social threads
- **Research and competitor analysis**: what does a channel talk about across hundreds of videos?
- **Subtitles and accessibility**: ready-made `.srt` files
- **SEO**: text versions of your own videos

### How to use it

1. Paste one or more YouTube URLs (videos, playlists or channels) into **YouTube URLs**.
2. Optional: set languages, turn on **AI-ready chunks**, or add SRT.
3. Click **Start**, then download the results as JSON, CSV or Excel, or fetch them through the API.

### For AI agents and automations

- **One job:** get the transcript (text, timestamps, SRT or RAG chunks) of YouTube videos, playlists or channels. Minimal input: `{ "urls": ["https://www.youtube.com/watch?v=jNQXAC9IVRw"] }`
- **Fast enough for a single tool call:** 1–10 videos finish in under 15 seconds; ~60 in 20–30 seconds, which fits inside the Apify MCP server's default 30-second wait. For big jobs, start the run asynchronously and read the dataset when it finishes.
- **Where the results are:** dataset items (fields below). A **run summary** is in the key-value store record `OUTPUT`: `status` (`SUCCEEDED`, `PARTIAL`, `STOPPED_AT_SPEND_LIMIT`, `ABORTED`, `NO_RESULTS`, `SOURCE_UNAVAILABLE`), `results`, `errorsByCode` and a plain-English `message`.
- **Predictable billing:** pay per event. Only successful transcripts are charged; error rows are free.
- **Respects "Max cost per run":** it never starts work your budget can't pay for, then stops cleanly with status `STOPPED_AT_SPEND_LIMIT`. Everything fetched up to that point is kept.
- **Graceful on abort and restarts:** partial results are always kept, and a platform restart resumes without duplicates or double charges.
- **Honest failures:** if the source blocks every request or changes its format, the run fails with a clear message and you pay $0, instead of quietly returning empty results.
- Works with the **Apify MCP server** (Claude, Cursor, other agents), agentic payments, and the API.

### Input examples

One video:

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

The last 100 uploads of a channel, chunked for RAG:

```json
{ "urls": ["https://www.youtube.com/@mkbhd"], "maxVideosPerPlaylist": 100, "includeChunks": true, "chunkMaxWords": 300, "includeSegments": false }
```

Spanish first, then English, with SRT included:

```json
{ "urls": ["https://youtu.be/NFvDHYMzj9U"], "languages": ["es", "en"], "includeSrt": true }
```

### Output

One item per video. From a real run (arrays shortened):

```json
{
  "status": "ok",
  "videoId": "jNQXAC9IVRw",
  "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
  "title": "Me at the zoo",
  "channelName": "jawed",
  "channelId": "UC4QobU6STFB0P71PMvOGN5A",
  "durationSeconds": 19,
  "viewCount": 444364886,
  "language": "en",
  "isAutoGenerated": false,
  "availableLanguages": [{ "code": "en", "name": "English", "isAutoGenerated": false }, { "code": "de", "name": "German", "isAutoGenerated": false }],
  "text": "All right, so here we are, in front of the elephants the cool thing about these guys is that they have really... really really long trunks ...",
  "segments": [{ "start": 1.2, "duration": 2.16, "text": "All right, so here we are, in front of the elephants" }]
}
```

With **AI-ready chunks** on, each video also gets a `chunks` array. Every chunk carries its own timestamped link and metadata, so you can embed it as is:

```json
{ "chunkId": "QVv3mQzlrN0-1", "index": 1, "text": "And I'm gonna try to make it quick...", "wordCount": 193, "startSeconds": 50.76, "endSeconds": 104.8, "url": "https://www.youtube.com/watch?v=QVv3mQzlrN0&t=50s", "videoId": "QVv3mQzlrN0", "title": "Apple Homeview Impressions: Not Convinced!", "channelName": "Marques Brownlee" }
```

| Field | Meaning |
|---|---|
| `text` | Full transcript as one string |
| `segments` | `{start, duration, text}` per caption line, in seconds |
| `srt` | Ready-to-save SRT subtitles (optional) |
| `chunks` | Overlapping RAG chunks with timestamps, links and metadata (optional) |
| `language` / `isAutoGenerated` | Which caption track you got, and whether YouTube generated it automatically |
| `availableLanguages` | Every caption track on the video |
| `title`, `channelName`, `channelId`, `durationSeconds`, `viewCount`, `isLive`, `description` | Video metadata (the description is optional) |
| `status` / `errorCode` | `ok`, or why there's no transcript (free) |

### Cost examples

| Job | Transcripts | Cost |
|---|---|---|
| 10 videos | 10 | $0.05 |
| A channel's last 200 videos | 200 | $1.00 |
| 5,000 videos for an AI dataset | 5,000 | $25.00 |

Videos without captions in any of these jobs cost $0. Set **Max cost per run** to cap any run, and the actor stops cleanly at the limit.

### Integrations

- **API**: `client.actor("t3data/youtube-transcripts").call({ urls: [...] })` (JS), or `client.actor("t3data/youtube-transcripts").call(run_input={"urls": [...]})` (Python). Full snippets are on the **API** tab.
- **AI agents (MCP)**: available as a tool through the Apify MCP server, so Claude, Cursor and other agents can fetch transcripts on demand.
- **n8n node**: install `n8n-nodes-t3data-youtube-transcripts` (n8n → Settings → Community Nodes → Install) for a ready-made node with all the options above, also usable as an AI Agent tool. [npm package](https://www.npmjs.com/package/n8n-nodes-t3data-youtube-transcripts)
- **No-code**: Make, Zapier, Google Sheets, Slack and webhooks, through Apify integrations.
- **Export**: JSON, CSV, Excel, XML, HTML or RSS.

### Error codes (never charged)

| Code | Meaning |
|---|---|
| `NO_CAPTIONS` | The video has no captions or auto-generated transcript |
| `EMPTY_TRANSCRIPT` | A caption track exists but is empty |
| `VIDEO_UNAVAILABLE` | Private, deleted or unavailable in this region |
| `AGE_RESTRICTED_OR_PRIVATE` | Needs a signed-in account |
| `INVALID_URL` | Not a YouTube video, playlist or channel link |
| `PLAYLIST_NOT_FOUND` / `CHANNEL_NOT_FOUND` | The playlist is private, or the channel handle doesn't exist |
| `SOURCE_UNAVAILABLE` (run status) | Every request was blocked, or the source changed its format. The run fails with $0 charged; retry later |
| `BLOCKED` | YouTube kept refusing after every retry (rare; try again) |

### FAQ

**No transcript for a video?** Check whether the video shows a "Show transcript" button on YouTube. If it doesn't, there are no captions to fetch, and the video comes back as `NO_CAPTIONS`, free.

**Wrong language?** `languages` is an order of preference. If none of your languages exist on the video, you get the video's own language. `availableLanguages` shows everything the video has.

**Do I need a proxy or a YouTube API key?** No. A residential proxy and IP rotation are built in, and their cost is included in the price.

**Is it legal?** It reads only publicly available captions, the same text anyone can open on YouTube. How you use the data is up to you, so respect copyright and YouTube's terms for your use case.

**Something broke?** Open an issue on the **Issues** tab with the video URL. Fixes usually ship within a day.

### Limits

- Private, members-only and age-restricted videos aren't supported, since they need a signed-in account.
- Streams that are still live have no transcript until they end.
- Translation isn't offered. You get the caption tracks the video actually has.

### More from T3 Data

- [YouTube Comments Scraper](https://apify.com/t3data/youtube-comments): comments and replies with likes, pinned and creator-hearted flags
- [YouTube Channel & Shorts Scraper](https://apify.com/t3data/youtube-channel): channel info plus every video and Short with exact views, likes and dates
- [Google News Scraper](https://apify.com/t3data/google-news): news by keyword, topic or location, with real article URLs and full text
- [Google Ads Transparency Scraper](https://apify.com/t3data/google-ads-transparency): every ad an advertiser or domain runs on Google, with dates, images and YouTube videos
- [Google Trends Scraper](https://apify.com/t3data/google-trends): interest over time, by region, related queries, and trending now
- [Google Hotels Scraper](https://apify.com/t3data/google-hotels): hotel prices, ratings and booking-site prices for any city and dates

***

*This Actor is an independent tool. It is not affiliated with, endorsed by, or sponsored by YouTube or Google. It only accesses publicly available captions.*

# Actor input Schema

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

Video URLs (watch, youtu.be, Shorts, live), plain video IDs, playlist URLs, or channel URLs (@handle, /channel/UC…). Playlists and channels are expanded to their videos.

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

Language codes in order of preference (e.g. en, es, de). If none match, the video's own language is used.

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

Use creator-uploaded captions over auto-generated ones when both exist.

## `maxVideosPerPlaylist` (type: `integer`):

For channels, the most recent uploads are taken first.

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

Adds a `segments` array with start time, duration and text for each caption line.

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

Adds a ready-to-save `srt` field.

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

Adds the full video description text.

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

Adds a `chunks` array: the transcript split into overlapping pieces of about N words, each with start/end time, a timestamped video link and video metadata. Drop straight into a vector database. No extra cost.

## `chunkMaxWords` (type: `integer`):

Target size of each chunk in words (about 1.3 tokens per word). 200–400 works well for most embedding models.

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

How many words of the previous chunk to repeat at the start of the next, so context isn't cut mid-thought. 0 disables overlap.

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

How many videos to process at the same time.

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

Residential proxy is strongly recommended — YouTube blocks datacenter IPs. Proxy cost is included in the price.

## Actor input object example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ],
  "languages": [
    "en"
  ],
  "preferManualCaptions": true,
  "maxVideosPerPlaylist": 50,
  "includeSegments": true,
  "includeSrt": false,
  "includeDescription": false,
  "includeChunks": false,
  "chunkMaxWords": 300,
  "chunkOverlapWords": 30,
  "maxConcurrency": 25,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

One item per video: transcript text, segments, SRT and metadata, or an error code (not charged).

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

One JSON object: status (SUCCEEDED, PARTIAL, STOPPED_AT_SPEND_LIMIT, ABORTED, NO_RESULTS, SOURCE_UNAVAILABLE), results count, failed inputs by error code, and a plain-English message.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://www.youtube.com/watch?v=jNQXAC9IVRw"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("t3data/youtube-transcripts").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": ["https://www.youtube.com/watch?v=jNQXAC9IVRw"] }

# Run the Actor and wait for it to finish
run = client.actor("t3data/youtube-transcripts").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ]
}' |
apify call t3data/youtube-transcripts --silent --output-dataset

```

## MCP server setup

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

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/bxGWdkJYAMVnNmUjK/builds/btWDkZLmg5NrJwCkY/openapi.json
