# YouTube Transcript Scraper - Bulk Captions & Subtitles (`tubelens/youtube-transcript-scraper`) Actor

Pull transcripts from hundreds of YouTube videos in one run: plain text, timestamped segments, SRT and VTT, plus each video's title, date and channel. You only pay when a transcript comes back. One video in depth with comments? Use the Video Scraper. A whole channel? Use the Channel Scraper.

- **URL**: https://apify.com/tubelens/youtube-transcript-scraper.md
- **Developed by:** [Tubelens](https://apify.com/tubelens) (community)
- **Categories:** Videos, Social media, AI
- **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.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### YouTube transcript scraper: bulk captions, subtitles, SRT and VTT export

Paste a list of YouTube links and get every transcript back as clean text, timestamped segments, or ready-to-use subtitle files. Each row also carries the video's title, publish date, view count and channel.

**$5 per 1,000 transcripts. You are only charged when a transcript actually comes back.**

Videos with no captions cost you nothing.

### Why this scraper?

- 💸 **No charge for empty results.** Videos with no captions, deleted videos and blocked videos are all free. You pay per transcript delivered, not per URL submitted.
- 📦 **Bulk by default.** Paste hundreds of links in one run. Most transcript scrapers take one video at a time.
- 🔁 **Retries blocked videos on a fresh IP.** YouTube throttles cloud traffic hard, so a block on one video triggers an automatic retry on a new address instead of a dead row.
- 📄 **Four output shapes.** Plain text for LLM pipelines, timestamped segments for analysis, SRT and VTT when you need real subtitle files.
- 🏷️ **Metadata included free.** Title, description, publish date, duration, view count, channel, tags and thumbnails ride along with the transcript at no extra cost.
- 🌍 **Any caption language.** Ask for a language and get the human-written track if it exists, the auto-generated one if it doesn't.
- ✍️ **Tells you what you got.** Every row flags whether the captions were written by a human or auto-generated, and lists every other language the video offers.

### What data can you extract?

<table>
<tr><td>📝 Full transcript text</td><td>⏱️ Timestamped segments</td><td>🎬 SRT subtitle file</td><td>🌐 VTT subtitle file</td></tr>
<tr><td>🗣️ Caption language</td><td>🤖 Auto-generated flag</td><td>📋 Available languages</td><td>🔢 Segment count</td></tr>
<tr><td>🎥 Video title</td><td>📅 Publish date</td><td>⌛ Duration</td><td>👁️ View count</td></tr>
<tr><td>📺 Channel name and ID</td><td>🏷️ Tags</td><td>🗂️ Category</td><td>🖼️ Thumbnails</td></tr>
</table>

### Which YouTube scraper do you need?

| You have | You want | Use |
|---|---|---|
| A list of video links | Transcripts in bulk | **This scraper** |
| One video link | Transcript plus comments and channel data | YouTube Video Scraper |
| A channel | Its whole catalog of videos and Shorts | YouTube Channel Scraper |
| A keyword | Ranked search results with position | YouTube Search Scraper |

Need everything about a single video including its comments? Use the Video Scraper. Need a whole channel's back catalog? Use the Channel Scraper.

### How much does YouTube Transcript Scraper cost?

You pay **$5.00 per 1,000 transcripts**, plus a small $0.005 start fee per run.

- The Apify **Free** plan gives $5 in credits a month, about **1,000 transcripts**.
- The **$29/month Starter** plan covers about **5,800 transcripts**.

A video with no captions, a deleted video, or a private video still appears in your dataset with a `status` explaining why. None of them are charged.

### Input

| Field | Type | Description |
|---|---|---|
| `videoUrls` | array | **Required.** Watch links, youtu.be links, Shorts links or bare video IDs. Duplicates are removed automatically. |
| `language` | string | Two-letter caption language, for example `en`, `es`, `de`, `hi`. Defaults to `en`. |
| `outputFormats` | array | Any of `text`, `segments`, `srt`, `vtt`. Defaults to `text` and `segments`. |
| `includeMetadata` | boolean | Adds title, publish date, channel and more to every row. On by default, free. |
| `concurrency` | integer | Videos fetched at once, 1 to 20. Defaults to 8. |
| `maxRunSeconds` | integer | Stop starting new videos after this long and finish cleanly. |

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/jNQXAC9IVRw"
  ],
  "language": "en",
  "outputFormats": ["text", "segments"]
}
```

### Output

One row per video.

```json
{
  "videoId": "qNIk2_EVMvE",
  "url": "https://www.youtube.com/watch?v=qNIk2_EVMvE",
  "language": "English",
  "languageCode": "en",
  "isAutoGenerated": false,
  "availableLanguages": ["en"],
  "characterCount": 12673,
  "segmentCount": 131,
  "text": "Nike stock fell more than 18% on June 28th 2024 that wiped away more than $29 billion...",
  "segments": [
    { "startMs": 40, "durationMs": 6640, "text": "Nike stock fell more than 18% on June 28th 2024" }
  ],
  "metadata": {
    "title": "How To Read An Earnings Report (with ZERO experience)",
    "publishedAt": "2024-08-17T05:48:44-07:00",
    "durationSeconds": 626,
    "viewCount": 37237,
    "channelName": "Brian Feroldi",
    "category": "Education"
  },
  "status": "ok",
  "error": null
}
```

`status` is one of `ok`, `no_transcript`, `unavailable` or `blocked`. Only `ok` rows are charged, so you can filter on it without worrying about your bill.

### Use cases

- **Feed an LLM or RAG pipeline.** Pull transcripts for a whole content library as plain text, ready to chunk and embed.
- **Repurpose video into writing.** Turn talks and tutorials into blog posts, newsletters and summaries.
- **Competitor and topic research.** Read what a set of channels actually says, at scale, instead of watching hours of video.
- **Subtitle files.** Export SRT or VTT to caption a re-upload or translate a back catalog.
- **Search your own archive.** Build a searchable text index of every video you have published.
- **Accessibility.** Provide text versions of video content.

### Limitations

- **No captions means no transcript.** This scraper reads the captions YouTube already has. It does not transcribe audio, so a video with captions turned off returns `no_transcript`. You are not charged for those.
- **Auto-generated captions are rough.** When no human-written track exists, you get YouTube's automatic captions, which have no speaker labels and imperfect punctuation. The `isAutoGenerated` flag tells you which you got.
- **Language falls back rather than failing.** If you ask for a language the video doesn't have, you get the best available track instead of an error. Check `languageCode` and `availableLanguages` to see what actually came back.
- **Very long videos produce very large rows.** A nine-hour video returns over 400,000 characters. If a row would exceed the platform's size limit, subtitle formats are dropped first and the row is flagged with `truncated`.
- **Deleted and unavailable videos are skipped, not charged.** They land in your dataset with `status: "unavailable"` and the reason YouTube gave.
- **Links that aren't YouTube are skipped.** Paste a mixed list and the non-YouTube entries are ignored with a warning rather than turned into empty rows. If none of your links are YouTube links, the run finishes cleanly and tells you so instead of failing.

### FAQ

#### How much does YouTube Transcript Scraper cost?

YouTube Transcript Scraper uses pay-per-result pricing. You pay **$5.00 for 1,000 results**. The Apify Free plan gives you $5 in usage credits a month, enough for around 1,000 results. If you run regularly, the $29/month Starter plan covers about 5,800 results.

No subscription lock-in. Pause whenever.

#### Is it legal to scrape YouTube?

Scraping public data is generally allowed in the US and most of the EU, as long as you don't collect personal data covered by GDPR or CCPA without a lawful basis. This actor only touches publicly accessible pages, but how you use the output is on you.

Apify's full breakdown: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/).

#### Can I integrate YouTube Transcript Scraper with other tools?

Push results into **Make, Zapier, Slack, Airbyte, GitHub, Google Sheets, Google Drive**, and more. Apify treats every actor as a webhook source, so anything that consumes webhooks or pulls from an API works.

Full list: [Apify integrations](https://docs.apify.com/platform/integrations).

#### Can I use YouTube Transcript Scraper with the Apify API?

Yes. Every run is available via the Apify REST API:

```bash
curl -X POST "https://api.apify.com/v2/acts/tubelens~youtube-transcript-scraper/runs?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"]}'
```

Docs: [Apify API reference](https://docs.apify.com/api/v2).

#### Can I use YouTube Transcript Scraper through an MCP Server?

Yes. Apify ships an MCP server that exposes every actor as a tool, so Claude Desktop, Cursor, and any other MCP-capable client can call YouTube Transcript Scraper. Setup: [Apify MCP docs](https://docs.apify.com/platform/integrations/mcp).

### Your feedback

Found a bug or want a field that isn't there? Open an issue at
[console.apify.com/actors/8cnGTS1t6kvp9Xhvs/issues](https://console.apify.com/actors/8cnGTS1t6kvp9Xhvs/issues) and it goes straight to a human.

# Actor input Schema

## `videoUrls` (type: `array`):

YouTube video links or IDs. Paste as many as you like: every video is fetched in parallel and returns one row. Accepts watch links, youtu.be links, Shorts links, and bare 11-character IDs.

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

Two-letter language code, for example en, es, de, hi. A human-written caption track in this language is preferred, then an auto-generated one, then whatever the video has.

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

Which shapes of the transcript to include in each row. Plain text and timestamped segments are on by default. Add SRT or VTT if you need subtitle files.

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

Add title, description, publish date, duration, view count, channel, tags and thumbnails to every row. Included free with the transcript, no extra charge.

## `concurrency` (type: `integer`):

How many videos to fetch at the same time. Raise it for large batches, lower it if you hit rate limits.

## `maxRunSeconds` (type: `integer`):

Stop starting new videos after this many seconds and finish cleanly with whatever is done. Prevents a huge batch from running until the platform timeout.

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

Runs on datacenter proxy by default and automatically retries a blocked video on a residential IP.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ],
  "language": "en",
  "outputFormats": [
    "text",
    "segments"
  ],
  "includeMetadata": true,
  "concurrency": 8,
  "maxRunSeconds": 3300,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Every transcript returned by this run.

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

// Run the Actor and wait for it to finish
const run = await client.actor("tubelens/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 = { "videoUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    ] }

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

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

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

```

## CLI example

```bash
echo '{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ]
}' |
apify call tubelens/youtube-transcript-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=tubelens/youtube-transcript-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/8cnGTS1t6kvp9Xhvs/builds/BJbuZ06PkS5uvx14c/openapi.json
