# YouTube Transcript Scraper: Original Language, SRT, Markdown (`massa182/youtube-transcript`) Actor

Get YouTube transcripts in the video's original language, not the wrong language of a random caption track. Videos, playlists, channels or search to text, SRT or Markdown. $3 per 1,000.

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

## Pricing

from $3.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.

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: Original Language, SRT and Markdown

![Any YouTube video, playlist, channel or search to clean text, SRT or Markdown in the original language](https://api.apify.com/v2/key-value-stores/U4mYcnNiXR3Z974D7/records/readme-how-it-works)

Get clean transcripts from any YouTube video, playlist, channel or search, **in the language the video is actually spoken in**. Each transcript comes as plain text, timestamped text, SRT subtitles and Markdown, together with the title, channel, duration and language.

**$3 per 1,000 transcripts. You only pay when a transcript is delivered.** Videos without captions are free.

### Why this one

![The first caption track is often the wrong language; this Actor returns the original language](https://api.apify.com/v2/key-value-stores/U4mYcnNiXR3Z974D7/records/readme-wrong-language)

- **Original language by default.** You get the language the video is spoken in, not a random caption track. Human-made captions come first; auto-generated captions are used only when there are none. Dubbed videos are handled too: the original audio track is detected.
- **Every format you need.** Plain text, timestamped text, SRT subtitles and Markdown in one run, plus optional raw segments with start times.
- **Any input.** Video links or IDs, playlists, whole channels and search terms.
- **$3 per 1,000 transcripts.** You pay only for delivered transcripts.
- **Videos without captions are free.** They come back clearly marked `no_captions` and are never charged.

### What you can do with it

- **AI and RAG:** feed lectures, podcasts and tutorials to ChatGPT, Claude, LangChain or LlamaIndex. Use `includeSegments` for timestamped chunks.
- **Summaries and newsletters:** turn a channel's weekly uploads into notes.
- **Content repurposing and SEO:** blog posts, show notes and quotes from your own videos.
- **Subtitles:** download ready-to-use `.srt` files.
- **Research:** analyse what is being said across a whole channel or search topic.

### How to use

1. Paste one or more items in **Videos, playlists, channels or search terms**, one per line:
   - `https://www.youtube.com/watch?v=UF8uR6Z6KLc` (also `youtu.be/…`, `/shorts/…`, `/live/…`, or just the 11-character ID)
   - `https://www.youtube.com/playlist?list=PL…`
   - `https://www.youtube.com/@TED` (also `/channel/UC…`, `/c/…`, `/user/…`)
   - `machine learning lecture` (any search term)
2. Set **Max videos per playlist, channel or search** (default 20).
3. Optional: type a **Language** code (`en`, `es`, `pt`, `de`, `ja`…) if you want a specific language instead of the original.
4. Click **Start**. Results appear in the Output tab and can be exported as JSON, CSV, Excel or HTML.

#### Input example

```json
{
  "sources": [
    "https://www.youtube.com/watch?v=5MuIMqhT8DM",
    "https://www.youtube.com/@TED",
    "python tutorial for beginners"
  ],
  "maxVideosPerSource": 20,
  "outputFormats": ["text", "srt", "markdown"]
}
```

#### Output example

Illustrative example (values shortened):

```json
{
  "videoId": "AbCdEfGh123",
  "url": "https://www.youtube.com/watch?v=AbCdEfGh123",
  "title": "How Seeds Grow: A Short Introduction",
  "channelName": "Example Channel",
  "channelId": "UCxxxxxxxxxxxxxxxxxxxxxx",
  "duration": "08:42",
  "durationSeconds": 522,
  "originalLanguage": "en",
  "language": "en",
  "captionType": "manual",
  "availableLanguages": ["en", "en (auto)", "es", "pt"],
  "status": "ok",
  "charged": true,
  "wordCount": 1240,
  "text": "Welcome back to the channel. Today we look at how a small seed becomes a tall tree...",
  "timestampedText": "[00:00] Welcome back to the channel.\n[00:03] Today we look at how a small seed becomes a tall tree.\n...",
  "srt": "1\n00:00:00,000 --> 00:00:03,000\nWelcome back to the channel.\n\n2\n...",
  "markdown": "# How Seeds Grow: A Short Introduction\n\n- **Channel:** Example Channel\n...",
  "source": "https://www.youtube.com/watch?v=AbCdEfGh123"
}
```

#### Status values

| `status` | Meaning | Charged |
|---|---|---|
| `ok` | Transcript delivered | Yes |
| `no_captions` | The video has no captions at all (common for music, live streams and some Shorts) | No |
| `language_not_available` | You asked for a language the video doesn't have and YouTube refused auto-translation. See `availableLanguages` | No |
| `original_language_not_available` | Only captions in other languages exist. Set `language` to one of `availableLanguages` | No |
| `unavailable` | Private, deleted, age-restricted or region-blocked video | No |
| `error` | Temporary failure after several retries | No |

### Pricing

Pay-per-event: **$0.003 per delivered transcript ($3 per 1,000)**, plus a tiny start fee of $0.00005 per run. Nothing is charged for videos without captions, unavailable videos or errors. You can cap the cost of any run with the *Max total charge* option in the run settings; the Actor stops as soon as the cap is reached.

Platform usage (proxies and compute) is included in the price.

### Use it from code

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("massa182/youtube-transcript").call(run_input={
    "sources": ["https://www.youtube.com/@TED"], "maxVideosPerSource": 10})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item.get("language"), item.get("wordCount"))
```

**JavaScript**

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('massa182/youtube-transcript').call({ sources: ['5MuIMqhT8DM'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

It also works with Make, Zapier, n8n, LangChain and the Apify MCP server for AI agents.

### FAQ

**Which language do I get?**
By default, the language spoken in the video. The Actor reads the original audio track (important for dubbed videos) and the speech-recognition track to find it, then delivers human-made captions in that language, or YouTube's auto-generated captions if there are no human ones.

**Can I get another language?**
Yes, set `language`. If the video has captions in that language you get them. If not, the Actor tries YouTube's auto-translation, which YouTube often refuses; in that case the item is not charged and `availableLanguages` lists what exists.

**Only human captions?**
Turn off *Use auto-generated captions*. Videos with only auto-generated captions will then come back as `no_captions` and are not charged.

**Very long videos?**
Supported (tested with 12-hour lectures). If a single result is too large for one dataset item (rare, over about 8 MB), the large formats are saved to the run's key-value store and the item contains a link (`srtUrl`, `markdownUrl`, ...).

**How fast is it?**
In our tests, 50 videos took about one and a half minutes with the default settings (10 in parallel).

**Is it legal?**
The Actor only reads publicly available captions that anyone can see on YouTube. You are responsible for how you use the data, including copyright and YouTube's terms. Don't use it for personal data you have no legal basis to process.

### Support

Found a problem or need a feature? Open an issue in the **Issues** tab.

# Actor input Schema

## `sources` (type: `array`):

One per line. Accepts video links (watch, youtu.be, shorts, live), video IDs, playlist links, channel links (@handle, /channel/UC..., /c/, /user/) and plain search terms.

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

Limit for each playlist, channel or search term. Single video links always count as 1.

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

Leave empty to get the video's ORIGINAL language (recommended). Or type a language code like en, es, pt, de, ja. If the video has no captions in that language, YouTube auto-translation is tried (marked captionType = translated); when YouTube refuses it, the item comes back as language_not_available with the list of available languages and is not charged.

## `includeAutoGenerated` (type: `boolean`):

Manual (human) captions are always preferred. Turn off to accept only manual captions.

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

Which transcript formats to include in each result.

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

Adds the list of caption segments with start time and duration in seconds. Useful for RAG chunking and video editing tools.

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

How many videos to process at the same time.

## Actor input object example

```json
{
  "sources": [
    "https://www.youtube.com/watch?v=UF8uR6Z6KLc"
  ],
  "maxVideosPerSource": 20,
  "includeAutoGenerated": true,
  "outputFormats": [
    "text",
    "timestamped",
    "srt",
    "markdown"
  ],
  "includeSegments": false,
  "maxConcurrency": 10
}
```

# Actor output Schema

## `overview` (type: `string`):

One item per video: title, channel, duration, original and delivered language, caption type, status, charged flag and the plain-text transcript.

## `srt` (type: `string`):

No description

## `markdown` (type: `string`):

No description

## `allData` (type: `string`):

Every field, including timestamped text and optional raw segments.

## `largeFiles` (type: `string`):

Only used for very long videos whose transcript does not fit in one dataset item; the item links to these files.

# 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 = {
    "sources": [
        "https://www.youtube.com/watch?v=UF8uR6Z6KLc"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("massa182/youtube-transcript").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 = { "sources": ["https://www.youtube.com/watch?v=UF8uR6Z6KLc"] }

# Run the Actor and wait for it to finish
run = client.actor("massa182/youtube-transcript").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 '{
  "sources": [
    "https://www.youtube.com/watch?v=UF8uR6Z6KLc"
  ]
}' |
apify call massa182/youtube-transcript --silent --output-dataset

```

## MCP server setup

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

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/uJAcbQFVtfVjJoi32/builds/tUF1BV2MKqrF23NSo/openapi.json
