# 🎬 YouTube Subtitles & Captions Scraper | $5/1k | SRT & VTT (`tecolabs/youtube-subtitles-captions-scraper`) Actor

Download YouTube subtitles and captions in bulk — plain text, SRT or VTT. $5 per 1,000 videos, charged only when subtitles are actually returned.

- **URL**: https://apify.com/tecolabs/youtube-subtitles-captions-scraper.md
- **Developed by:** [Teco](https://apify.com/tecolabs) (community)
- **Categories:** Videos, Agents, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 subtitles extracteds

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 Subtitles & Captions Scraper | $5/1k | SRT & VTT

Download **YouTube subtitles and captions** in bulk — as plain text, **SRT** or **VTT** files.

Paste a list of YouTube links, pick a language, get the captions back. No login, no API key, no
browser automation. **$5 per 1,000 videos**, and you are charged only when subtitles are actually
returned.

### What you get

| | |
|---|---|
| 💰 **Price** | **$5 per 1,000 videos** — flat. Failed videos are free. |
| 📄 **Formats** | Plain text · Timed segments · **SRT** · **VTT** |
| 🔗 **Input** | Watch URLs, `youtu.be` links, **Shorts**, **Live** URLs, or bare video IDs |
| 🌍 **Languages** | Any language the video has. Human-written captions preferred over auto-generated |
| 📦 **Bulk** | Paste hundreds of links in one run. Duplicates removed, so no double charging |

### How this one is different

| What usually goes wrong | What this Actor does |
|---|---|
| You get one blob of text — the timings are gone | Exports **SRT** and **VTT** with real timings, ready to drop into Premiere, DaVinci Resolve, CapCut, or a `<track>` tag |
| Videos that fail quietly vanish from the output | **Every input comes back as a row** — with the reason it failed, plus `availableLanguages` so your next run can ask for the right code |
| You pay for videos that returned nothing | **Charged only when subtitles are actually returned** |
| Datacenter IPs report "no subtitles" for videos that clearly have them | **Residential proxy by default.** Measured on the same 10 videos: **9/10 with residential, 6/10 with datacenter** — and the missing 3 reported "no subtitles" while having them |
| API keys, OAuth or browser sessions to set up | None. Paste links and run |

### Input

```json
{
  "videoUrls": [
    { "url": "https://www.youtube.com/watch?v=aircAruvnKk" },
    { "url": "https://youtu.be/dQw4w9WgXcQ" },
    { "url": "https://www.youtube.com/shorts/abc123XYZ99" }
  ],
  "language": "en",
  "outputFormat": "srt",
  "maxVideos": 500
}
```

| Field | Type | Default | Notes |
|---|---|---|---|
| `videoUrls` | array | — | **Required.** Any mix of URL formats or bare video IDs |
| `language` | string | `en` | ISO 639-1 code: `en`, `es`, `de`, `fr`, `pt`, `ja`, `hi`, … |
| `outputFormat` | string | `plain` | `plain` · `segments` · `srt` · `vtt` |
| `maxVideos` | integer | — | Spending guard. Stops after N videos |
| `proxyConfiguration` | object | Residential | YouTube blocks datacenter IPs — keep the default |

### Output

One row per video.

```json
{
  "videoId": "aircAruvnKk",
  "url": "https://www.youtube.com/watch?v=aircAruvnKk",
  "title": "But what is a neural network?",
  "author": "3Blue1Brown",
  "durationSeconds": 1120,
  "language": "en",
  "isAutoGenerated": false,
  "availableLanguages": ["en", "es", "ja", "de"],
  "characterCount": 18145,
  "transcript": "1\n00:00:04,220 --> 00:00:07,900\nThis is a 3...",
  "error": null
}
```

With `outputFormat: "segments"` you get a `segments` array instead of `transcript`:

```json
"segments": [
  { "start": 4.22, "duration": 3.68, "text": "This is a 3" },
  { "start": 7.90, "duration": 2.94, "text": "It's a mess of neurons" }
]
```

Export the dataset as **JSON, CSV, Excel, XML or HTML** from the Apify Console, or pull it
through the API.

### Use cases

- **Subtitle, translate and repurpose video** — SRT/VTT with real timings, ready for your editor
  or your translator
- **Feed videos to an LLM** — plain text output drops straight into ChatGPT, Claude or your own
  pipeline for summaries, Q\&A and topic extraction
- **Content research** — pull captions across a competitor's videos and search them for terms
- **Dataset building** — bulk speech text for training, search indexes or RAG
- **Accessibility** — attach a `.vtt` track to video on your own site

### FAQ

**Does it work on Shorts and Live replays?**
Yes. Watch URLs, `youtu.be` short links, `/shorts/`, `/live/`, `/embed/` and bare 11-character
video IDs are all accepted.

**What if a video has no subtitles?**
You get a row with `error` explaining it, and you are not charged for that video.

**What if my language isn't available?**
Same — a row with `error`, plus `availableLanguages` listing what the video does have, so your
next run can ask for the right code.

**Auto-generated or human captions?**
Whichever the video has. When both exist for your language, the human-written track wins, because
auto-generated captions carry recognition errors. The `isAutoGenerated` field tells you which one
you got.

**Do I need a YouTube API key or an account?**
No. Nothing to configure beyond the input form.

**Why residential proxies?**
Because datacenter IPs fail silently. YouTube does not block them — it returns a perfectly normal
response with the caption tracks quietly removed. Measured on the same 10 videos: **9/10 with
residential, 6/10 with datacenter**, and the 3 missing ones reported "no subtitles" even though
they clearly have them. Keep the default unless you enjoy debugging phantom failures.

**How much does a run actually cost?**
$5 per 1,000 videos on the subtitles themselves, plus Apify platform usage (proxy traffic and
compute), which is small: a typical 20-minute video moves about 12 KB.

### Legal

This Actor reads caption tracks that YouTube publishes for public videos. You are responsible for
how you use the output — check YouTube's Terms of Service and the copyright of the material you
process. It does not download video or audio, and does not access private, unlisted or
age-restricted content.

# Actor input Schema

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

Paste any number of YouTube links. Watch links, youtu.be links, Shorts and Live URLs all work — and so do bare video IDs. Duplicates are removed automatically, so you are never charged twice for the same video.

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

ISO 639-1 code, for example `en`, `es`, `de`, `ja`. Human-written subtitles are preferred over auto-generated ones when both exist. If the language is missing the video is still reported, with the list of languages that ARE available — so you know what to ask for next.

## `outputFormat` (type: `string`):

`Plain text` for feeding an LLM or reading. `Timed segments` for building your own tooling. `SRT` / `VTT` for subtitle files.

## `maxVideos` (type: `integer`):

Hard stop on how many videos this run may process. Leave empty for no limit. Use it as a spending guard when you paste a long list.

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

YouTube blocks datacenter IPs, so residential proxies are the reliable choice. Leave the default unless you know you need something else.

## Actor input object example

```json
{
  "videoUrls": [
    {
      "url": "https://www.youtube.com/watch?v=aircAruvnKk"
    }
  ],
  "language": "en",
  "outputFormat": "plain",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `subtitles` (type: `string`):

Every processed video: title, channel, length, language, whether the track was auto-generated, character count, and the subtitles in the format you selected.

# 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": [
        {
            "url": "https://www.youtube.com/watch?v=aircAruvnKk"
        }
    ],
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("tecolabs/youtube-subtitles-captions-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": [{ "url": "https://www.youtube.com/watch?v=aircAruvnKk" }],
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("tecolabs/youtube-subtitles-captions-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 '{
  "videoUrls": [
    {
      "url": "https://www.youtube.com/watch?v=aircAruvnKk"
    }
  ],
  "language": "en"
}' |
apify call tecolabs/youtube-subtitles-captions-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tecolabs/youtube-subtitles-captions-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/8tvu6IrXMwmufYTwf/builds/6jFplP5Qa12VN1vac/openapi.json
