# YouTube Transcript Scraper (Captions API) (`honestdata/youtube-transcript-scraper`) Actor

Get the transcript of any YouTube video as text and timed segments. Every transcript is labelled manual or auto-generated, flags a different language than the one you asked for, and shows how much of the video it covers. Videos without one are listed free.

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

from $1.20 / 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 does YouTube Transcript Scraper do?

It gets the **transcript of any [YouTube](https://www.youtube.com) video** as clean text and timed segments, in bulk. Paste video links or ids, pick a language, and get one row per video. It's a **YouTube captions API alternative** built for **AI and research pipelines**: summarising videos, feeding RAG, quoting talks and analysing what channels say.

**In short:** $2 per 1,000 transcripts, in bulk, each one labelled manual or auto-generated, and videos without a transcript are free.

### Why use it?

- **Manual or auto-generated, labelled.** Every transcript says whether the channel uploaded it (`manual`) or YouTube's speech recognition wrote it (`auto-generated`). They are not equally trustworthy, and most tools don't tell you which one you got.
- **No silent language swaps.** Ask for English and the video only has Korean? You get the Korean transcript labelled `languageMatched: false`, or, if you turn fallback off, a free "not available" row. Never a wrong-language transcript passed off as a match.
- **You see how much of the video it covers.** `coveragePct` is the share of the video with spoken words on screen. A transcript that covers 20% of a talk is flagged by the number, not hidden.
- **Sound tags counted, styling stripped.** `[Music]`, `(Applause)` and `♪ ♪` lines are counted in `nonSpeechSegments`. Styled captions (colour codes, invisible characters, every line doubled) are cleaned, so word counts are real.
- **Videos without a transcript are free.** Private, deleted, region-locked, members-only, or simply no captions: you get a row saying why (`unavailableReason`) and pay nothing for it.
- **Reliable, and tested every day.** When YouTube asks for a sign-in check, the video is retried on a fresh connection (moving to a residential IP) instead of failing. An automated check also fetches real transcripts every morning and checks the text itself, not just that the run finished.

| Video | Captions | Language | Asked for | Covers | Words |
|---|---|---|---|---:|---:|
| Do schools kill creativity? (TED) | manual | en | yes | 77.5% | 3,170 |
| The Egg - A Short Story | auto-generated | en | yes | 91.9% | 910 |
| PSY - GANGNAM STYLE | auto-generated | ko | no (asked en) | 80.2% | 194 |
| Charlie bit my finger - again! | auto-generated | en | yes | 48.6% | 24 |

### What data can you get from YouTube?

| Field | What it is |
|---|---|
| `videoId`, `url`, `title` | The video |
| `channelName`, `channelId` | The channel |
| `durationSeconds`, `viewCount`, `isLive` | Length, views and whether it's a live stream |
| `transcriptAvailable` | `true`, or `false` with `unavailableReason` and `unavailableMessage` |
| `captionType` | `manual` or `auto-generated` |
| `languageCode`, `language`, `requestedLanguage`, `languageMatched` | The transcript's language, and whether it's the one you asked for |
| `text` | The whole transcript as one string |
| `segments` | Timed lines: `[{ "start": 1.2, "duration": 2.16, "text": "..." }]`, in seconds |
| `coveragePct`, `nonSpeechSegments`, `segmentCount`, `wordCount` | How much of the video it covers, sound tags, and counts |
| `availableTranscripts` | Every caption track the video has (language and type) |

Reasons a video has no transcript: `no_captions`, `language_not_available`, `private`, `unavailable` (deleted or never existed), `age_restricted`, `members_only`, `region_blocked`, `paid`, `live_not_started`, `unplayable`, `empty_transcript`, and `blocked` (YouTube refused every retry).

### How to get YouTube transcripts in bulk

1. Open the Actor and click **Try for free**.
2. Paste **YouTube video links or ids**, one per line (watch, youtu.be, Shorts, live and embed links all work).
3. Set the **language** you want, e.g. `en`, or leave it empty for the language spoken in the video.
4. Click **Start**.
5. Download the transcripts as JSON, CSV or Excel, or read them through the API.

### How much does it cost to get YouTube transcripts?

**$0.002 per transcript delivered**, so **1,000 transcripts cost $2**. Videos without a transcript are listed free, and each video is fetched once even if you paste it twice. There's also a tiny start fee of $0.00005 per run.

Apify's free plan includes $5 of monthly credit, which covers about **2,500 transcripts a month**. The run checks your max charge before fetching and stops cleanly when it's reached.

### Input

See the **Input** tab for every option:

- **YouTube videos**: links (watch, youtu.be, Shorts, live, embed) or 11-character ids
- **Language**: e.g. `en`, `es`, `pt-BR`. Empty means the language spoken in the video. `en` also matches `en-US` and `en-GB`.
- **Use the video's own language if yours isn't there**: on by default

### Output

You can download the dataset as JSON, CSV, Excel, XML or HTML. Two real rows (text and segments shortened):

```json
[
  {
    "videoId": "l5aZJBLAu1E",
    "url": "https://www.youtube.com/watch?v=l5aZJBLAu1E",
    "title": "The Weather Girls - It's Raining Men (Official Video)",
    "channelName": "TheWeatherGirlsVEVO",
    "durationSeconds": 294,
    "viewCount": 122391588,
    "isLive": false,
    "transcriptAvailable": true,
    "captionType": "manual",
    "languageCode": "en",
    "requestedLanguage": "en",
    "languageMatched": true,
    "coveragePct": 78.4,
    "nonSpeechSegments": 2,
    "segmentCount": 71,
    "wordCount": 485,
    "text": "(intriguing music) - Hi. - Hi, we are your weather girls. - Uh huh. - And have we got news for you! ...",
    "segments": [
      { "start": 0.68, "duration": 2.917, "text": "(intriguing music)" },
      { "start": 14.762, "duration": 0.833, "text": "- Hi." }
    ]
  },
  {
    "videoId": "2JK7NMfvZTY",
    "url": "https://www.youtube.com/watch?v=2JK7NMfvZTY",
    "durationSeconds": 10387,
    "transcriptAvailable": false,
    "unavailableReason": "no_captions",
    "unavailableMessage": "This video has no captions or transcript.",
    "segmentCount": 0,
    "wordCount": 0,
    "text": null,
    "segments": []
  }
]
```

The second video has no captions at all, so its row says why and costs nothing.

### Tips

- **Check `captionType` before you rely on a transcript.** Auto-generated captions are speech recognition: names, numbers and lyrics are often wrong. On **songs**, YouTube sometimes even picks the wrong language: in our tests Italian songs came back as Spanish or Romanian captions.
- **Manual captions are labelled by the uploader**, and labels can be wrong: Despacito's "English" track is the Spanish lyrics.
- **Many videos have no captions at all**, mostly music videos and languages YouTube can't auto-caption. We checked our answers against YouTube's own watch page (41 videos, 35 of them without captions) and the iPhone app's player (49 videos): they matched every time.

### FAQ

**Can I give a channel or playlist?** Not yet. Video links or ids only.

**Do I need a proxy?** No. Apify Proxy is on by default: each video is tried on a data-center IP first and moves to residential only if YouTube refuses. Videos are read from the US (or the proxy country you pick), and anything blocked there shows as `region_blocked`.

**Can it translate?** No. You get the tracks the video really has.

**Can I use it from code or an AI assistant?** Yes. Use the Apify API or the Python and JavaScript clients (see the **API** tab), connect it to Make, Zapier or Google Sheets, or schedule it. AI assistants such as Claude and Cursor can call it through Apify's MCP server: `https://mcp.apify.com?tools=honestdata/youtube-transcript-scraper`.

**Is it legal to scrape YouTube transcripts?** It reads the public captions of public videos and collects no account data. Transcripts can mention people by name, so handle them under the rules that apply to you (such as the GDPR) and respect creators' copyright when you reuse them.

**Found a problem?** Open an issue in the **Issues** tab. We read every report.

**Found it useful?** A short review on this page helps other people find it.

### More from Honest Data

- [Google Trends Scraper: Unlimited Keywords on One Scale](https://apify.com/honestdata/google-trends-one-scale): compare up to 200 keywords on one scale, with error bars and glitch flags.
- [AliExpress Product Search Scraper (US)](https://apify.com/honestdata/aliexpress-product-search): search results with the real regular price, ads and promos flagged.
- [Product Demand Radar](https://apify.com/honestdata/product-demand-radar): rank product ideas by Google demand and AliExpress supply.

# Actor input Schema

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

Video links or 11-character video ids. Watch, youtu.be, Shorts, live and embed links all work. One transcript per video; duplicates are fetched once.

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

Language code of the transcript you want, like en, es, de or pt-BR. Leave empty for the language spoken in the video.

## `fallbackToOtherLanguage` (type: `boolean`):

On: a video with no captions in your language returns its original-language transcript, labelled languageMatched: false (and charged, since it is a transcript). Off: such videos are listed as not available and not charged.

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

YouTube asks data-center IPs to sign in. With plain Apify Proxy (the default) each video is tried on a data-center IP first and moves to a residential one if YouTube refuses. Pick a group to use only that group.

## Actor input object example

```json
{
  "videos": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ],
  "language": "en",
  "fallbackToOtherLanguage": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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=jNQXAC9IVRw"
    ],
    "language": "en",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("honestdata/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=jNQXAC9IVRw"],
    "language": "en",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("honestdata/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=jNQXAC9IVRw"
  ],
  "language": "en",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call honestdata/youtube-transcript-scraper --silent --output-dataset

```

## MCP server setup

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