# YouTube Transcript Scraper – Captions, Subtitles & Video Data (`openharvest/youtube-transcript-scraper`) Actor

YouTube transcript scraper: get the full transcript, captions or subtitles of any public YouTube video, with timestamps, in any available language (human-made or auto-generated), plus video title, channel, views, duration and publish date. No login or API key.

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

## Pricing

$2.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 – Captions, Subtitles & Video Data

YouTube transcript scraper: get the full transcript, captions or subtitles of any public YouTube video, with timestamps, in any available language (human-made or auto-generated), plus video title, channel, views, duration and publish date. No login or API key.

**Price: $2.00 per 1,000 transcripts.** Videos without captions, private or removed videos and blocked requests produce a free error row and are **never charged**.

Use this instead of a general web crawler or a browser-based YouTube scraper when you need the **spoken text** of videos, fast and in a clean format for LLMs, RAG, search or analysis.

### What data do you get?

- 📝 **Full transcript** as one plain-text field (`transcript`), ready for LLMs and NLP
- ⏱ **Timestamped segments**: start time, duration and text of every caption line (`segments`)
- 🌍 **Language info**: language code and name of the returned captions, whether they are **auto-generated** (speech recognition) or **human-made**, and the list of **all caption languages** the video has
- 🎬 **Video metadata**: title, channel name, channel ID and URL, publish date, duration, view count, category, keywords (tags), description (e-mail addresses and phone numbers removed), thumbnail URL, live-stream flag
- 🔢 **Counts**: number of caption lines, words and characters

Works with normal videos, **Shorts**, past live streams, music videos, lectures and podcasts, including multi-hour videos (we tested a 4.5-hour course: 50,000+ words in one item).

### Why use this YouTube transcript scraper?

- **Reliable**: in our test runs on Apify, 100% of the captioned videos returned a transcript (65 of 65, none ended blocked). The Actor rotates residential IPs automatically when YouTube shows a bot check, so you don't need to set up a proxy.
- **Fast**: plain HTTP requests, no browser. About 1 second per video, 5 videos in parallel.
- **Fair**: you pay only for transcripts you receive. Errors are free.
- **No login, no API key, no YouTube quota.**
- **Clean output**: flat fields, HTML entities decoded, formatting tags removed.

### Use cases

- **AI and LLM pipelines**: summarize videos, build RAG knowledge bases from lectures, podcasts and tutorials, or create training and evaluation data.
- **Content repurposing**: turn videos into blog posts, newsletters, show notes, social posts or subtitles.
- **SEO and marketing research**: see what competitors say in their videos and which keywords they use.
- **Market and brand monitoring**: search the spoken content of product reviews, earnings calls and news videos for brand or product mentions.
- **Education and accessibility**: get readable text versions of lessons and talks.
- **Academic research**: build text datasets of public video content for linguistics, media and political science studies.

### How to get YouTube transcripts

1. Click **Try for free** / **Start**.
2. Paste one or more video links into **YouTube videos** (`https://www.youtube.com/watch?v=...`, `https://youtu.be/...`, `/shorts/...` or just the 11-character video ID).
3. Optionally choose a **Transcript language** (e.g. `en`, `de`, `es`) and **Caption type**.
4. Click **Start** and download your data as JSON, CSV, Excel, XML or HTML, or connect it to Make, Zapier, n8n, Google Sheets, webhooks or the Apify API.

### Input

| Field | Type | Description |
|---|---|---|
| `videos` | array of strings | Video URLs or IDs. Watch, youtu.be, Shorts, live, embed and mobile links all work. Channel and playlist links are not supported. |
| `language` | string | Optional language code (`en`, `de`, `pt-BR`, ...). Empty = the video's original spoken language. |
| `captionType` | `any` / `manual` / `auto` | `any` (default) prefers human-made captions and falls back to auto-generated ones. |
| `languageFallback` | boolean | If the video has no captions in `language`, return the original-language transcript (default `true`). If `false`, you get a free error row instead. |
| `includeTimestamps` | boolean | Add the `segments` array with start time and duration of each line (default `true`). |
| `includeMetadata` | boolean | Add publish date, duration, views, category, keywords, description and thumbnail (default `true`). |
| `proxyConfiguration` | object | Leave off. The Actor handles proxies itself. |

Example input:

```json
{
    "videos": [
        "https://www.youtube.com/watch?v=iG9CE55wbtY",
        "https://youtu.be/arj7oStGLkU",
        "UF8uR6Z6KLc"
    ],
    "language": "en",
    "captionType": "any",
    "includeTimestamps": true,
    "includeMetadata": true
}
```

### Output

Each dataset item has a `type`: `transcript` or `error`. Real output from a run on Apify (shortened; the real item has all 427 segments and 65 caption languages):

```json
{
    "type": "transcript",
    "videoId": "iG9CE55wbtY",
    "url": "https://www.youtube.com/watch?v=iG9CE55wbtY",
    "title": "Do schools kill creativity? | Sir Ken Robinson | TED",
    "channelName": "TED",
    "channelId": "UCAuUUnT6oDeKwE6v1NGQxug",
    "channelUrl": "https://www.youtube.com/channel/UCAuUUnT6oDeKwE6v1NGQxug",
    "publishDate": "2007-01-06T21:00:34-08:00",
    "durationSeconds": 1203,
    "viewCount": 25025865,
    "category": "Education",
    "keywords": ["Ken", "Robinson", "TED", "TEDTalks"],
    "description": "Sir Ken Robinson makes an entertaining and profoundly moving case for creating an education system that nurtures creativity ...",
    "thumbnailUrl": "https://i.ytimg.com/vi/iG9CE55wbtY/sddefault.jpg",
    "isLiveContent": false,
    "language": "en",
    "languageName": "English",
    "isAutoGenerated": false,
    "requestedLanguageMissing": false,
    "availableLanguages": [
        { "languageCode": "af", "languageName": "Afrikaans", "isAutoGenerated": false },
        { "languageCode": "sq", "languageName": "Albanian", "isAutoGenerated": false },
        { "languageCode": "ar", "languageName": "Arabic", "isAutoGenerated": false }
    ],
    "segmentCount": 427,
    "wordCount": 3170,
    "characterCount": 17574,
    "transcript": "Good morning. How are you? (Audience) Good. It's been great, hasn't it? I've been blown away by the whole thing. In fact, I'm leaving. (Laughter) ...",
    "segments": [
        { "start": 27.103, "duration": 2.575, "text": "Good morning. How are you?" },
        { "start": 29.702, "duration": 1.403, "text": "(Audience) Good." },
        { "start": 31.129, "duration": 1.668, "text": "It's been great, hasn't it?" }
    ],
    "scrapedAt": "2026-10-08T16:18:54.178Z"
}
```

**Error row (free):**

```json
{
    "type": "error",
    "videoId": "LXb3EKWsInQ",
    "url": "https://www.youtube.com/watch?v=LXb3EKWsInQ",
    "title": "COSTA RICA IN 4K 60fps HDR (ULTRA HD)",
    "errorCode": "NO_CAPTIONS",
    "error": "This video has no captions or transcript.",
    "availableLanguages": []
}
```

Possible `errorCode` values: `NO_CAPTIONS`, `LANGUAGE_NOT_AVAILABLE`, `VIDEO_UNAVAILABLE`, `PRIVATE_VIDEO`, `AGE_RESTRICTED`, `MEMBERS_ONLY`, `LIVE_NOT_STARTED`, `BLOCKED`, `CAPTIONS_FAILED`, `INVALID_INPUT`, `SCRAPE_FAILED`.

Times in `segments` are in seconds. The dataset has two ready-made views in Apify Console: **Overview** and **Video metadata**.

### Pricing

This Actor uses **pay-per-event** pricing. You pay only for transcripts you get. Platform usage and proxies are included.

| Event | Price | When it is charged |
|---|---|---|
| `transcript` | **$0.002** per video ($2.00 / 1,000) | Each transcript saved to the dataset |
| Errors | **Free** | No captions, unavailable/private/age-restricted videos, blocked requests, invalid input |

Examples:

| Job | Cost |
|---|---|
| 10 videos | **$0.02** |
| 1,000 videos | **$2.00** |
| 10,000 videos | **$20.00** |

Long videos cost the same as short ones. Tip: set **Max cost per run** in the run options. The scraper stops cleanly when your budget is reached.

### Use with AI agents (MCP)

Add the Actor as a tool in the [Apify MCP server](https://mcp.apify.com) (`https://mcp.apify.com?tools=openharvest/youtube-transcript-scraper`), or let agents find it with `search-actors` ("youtube transcript").

Example `call-actor` input for "Summarize this YouTube video for me":

```json
{ "videos": ["https://www.youtube.com/watch?v=UF8uR6Z6KLc"], "includeTimestamps": false, "includeMetadata": false }
```

Example input for "Get the German subtitles of these two talks, with timestamps":

```json
{ "videos": ["https://youtu.be/arj7oStGLkU", "https://youtu.be/iG9CE55wbtY"], "language": "de", "languageFallback": false }
```

Tip for agents: `includeTimestamps: false` keeps the output small (just `transcript`), which saves context tokens.

### FAQ

**Which videos work?**
Any public or unlisted video that has captions: human-made subtitles or YouTube's auto-generated captions. Most spoken videos in common languages have auto-generated captions. Pure music or nature videos often have none; you get a free `NO_CAPTIONS` row.

**Can I get the transcript in another language?**
Yes, if the video has captions in that language (see `availableLanguages`). Machine translation of captions is not supported: YouTube blocks translated caption requests without a logged-in browser session. If your language is missing, you get the original-language transcript (`requestedLanguageMissing: true`) or, with `languageFallback: false`, a free error row.

**Does it work for Shorts and live streams?**
Shorts: yes. Live streams: yes, once the stream has ended and YouTube has processed the captions. Upcoming streams return `LIVE_NOT_STARTED`.

**Can I scrape a whole channel or playlist?**
Not in this Actor. Enter the individual video URLs.

**Can I get age-restricted, private or members-only videos?**
No. These need a logged-in account, and this Actor never logs in. They return a free error row.

**What does `BLOCKED` mean?**
YouTube showed its "confirm you're not a bot" check on every IP the Actor tried for that video. This is rare (0 of 65 videos in our tests) and temporary. Run the video again later. You are not charged.

**Do I need a proxy?**
No. On Apify the Actor uses Apify residential proxy automatically, because YouTube blocks datacenter IPs. The cost is included in the price.

**Can I run it via API or on a schedule?**
Yes. Use the Apify API, the JavaScript/Python clients, Schedules, or integrations such as Make, Zapier, n8n and Google Sheets.

### Is it legal to scrape YouTube transcripts?

The Actor reads only **public data**: the captions and basic video details that YouTube shows to any visitor without login. It does not log in, does not use cookies of real accounts, does not download video or audio, and does not collect personal data: e-mail addresses and phone numbers in video descriptions are replaced with `[email removed]` / `[phone removed]`. The channel name is included only as the public author of the video. Transcripts are copyrighted by their creators. Respect their rights, YouTube's Terms of Service and laws such as GDPR when you store, publish or train on the data. Quoting, research and analysis are usually fine; republishing full transcripts may not be. **Do not use the data for spam or unsolicited outreach.** If you are unsure, consult a lawyer.

### Related actors

By the same developer:

- Apple Podcasts Scraper – Episodes, Charts & Podcast RSS Feeds
- Bilibili Scraper – Videos, Search, Rankings, Comments & Danmaku
- Keyword Suggestions – Google, YouTube & Amazon Autocomplete
- PDF to Markdown – DOCX, PPTX, XLSX & HTML for LLM & RAG
- Substack Scraper – Newsletter Posts, Full Text & Comments
- Telegram Channel Scraper – Posts, Messages & Views, No Login

### Support & feedback

Found a bug or missing field? Open an issue in the **Issues** tab. We usually respond within a day. Feature requests are welcome.

# Actor input Schema

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

Video URLs or 11-character video IDs. Accepted formats: <code>https://www.youtube.com/watch?v=jNQXAC9IVRw</code>, <code>https://youtu.be/jNQXAC9IVRw</code>, <code>https://www.youtube.com/shorts/...</code>, <code>/live/...</code>, <code>/embed/...</code> or just <code>jNQXAC9IVRw</code>. Channel and playlist links are not supported - enter the individual videos.

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

Optional language code, e.g. <code>en</code>, <code>de</code>, <code>es</code>, <code>pt-BR</code>, <code>ja</code>. Leave empty to get the video's original (spoken) language. Human-made captions in this language are preferred over auto-generated ones.

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

<b>Any</b> prefers human-made captions and falls back to auto-generated (speech recognition) captions. <b>Human-made only</b> and <b>Auto-generated only</b> restrict the choice.

## `languageFallback` (type: `boolean`):

If the video has no captions in <b>Transcript language</b>, return the transcript in the video's original language (marked with <code>requestedLanguageMissing: true</code>). Turn off to get a free error row instead.

## `includeTimestamps` (type: `boolean`):

Add the <code>segments</code> array (start time, duration and text of every caption line). The plain-text <code>transcript</code> field is always included.

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

Add publish date, duration, view count, category, keywords (tags), description and thumbnail URL. Title and channel are always included.

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

Leave off. On the Apify platform the Actor already uses Apify residential proxy (YouTube blocks datacenter IPs) and rotates IPs automatically - the proxy cost is included in the price. Set a custom proxy only if you want to use your own.

## Actor input object example

```json
{
  "videos": [
    "https://www.youtube.com/watch?v=arj7oStGLkU",
    "https://youtu.be/jNQXAC9IVRw"
  ],
  "language": "en",
  "captionType": "any",
  "languageFallback": true,
  "includeTimestamps": true,
  "includeMetadata": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped items in the default dataset (JSON, CSV, Excel and more via the dataset export).

## `files` (type: `string`):

Records saved in the default key-value store, e.g. the run summary.

# 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/watch?v=arj7oStGLkU"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("openharvest/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",
        "https://www.youtube.com/watch?v=arj7oStGLkU",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("openharvest/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",
    "https://www.youtube.com/watch?v=arj7oStGLkU"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call openharvest/youtube-transcript-scraper --silent --output-dataset

```

## MCP server setup

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