# YouTube Transcript Scraper — SRT/VTT + Whisper AI Fallback (`memo23/youtube-transcript-scraper`) Actor

Extract YouTube transcripts as SRT, VTT, JSON segments or plain text from any video or Short — bulk URL lists supported. 4-source extraction ladder (captions → DownSub → yt-dlp → Whisper AI for caption-less videos), language selection with auto-translate, plus title, channel and stats on every row.

- **URL**: https://apify.com/memo23/youtube-transcript-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** AI, Videos, Agents
- **Stats:** 4 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## 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 — SRT, VTT, JSON & Plain Text with Whisper AI Fallback

Turn any YouTube video or Short into a clean transcript in one run. Every row carries the full text, timestamped segments, ready-made **SRT and VTT subtitle files**, and the video's core metadata (title, channel, views, duration, description). When a video has **no captions at all**, the optional **Whisper AI fallback** downloads the audio and transcribes it with speech-to-text — something caption-only scrapers simply return empty for.

#### How it works

![How the YouTube Transcript Scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-youtube-transcript.png)

#### ✨ Why use this scraper?

- **Four-source extraction ladder** — official caption tracks first, then the DownSub subtitle service, then yt-dlp subtitle download, then Whisper AI speech-to-text. One source being blocked or missing doesn't kill your run.
- **Whisper AI for caption-less videos** — the differentiator: videos with no captions still come back transcribed (opt-in, billed as a separate premium event so you never pay it unknowingly).
- **Every format in one row** — plain text for LLM pipelines, timestamped JSON segments for analysis, SRT and VTT for subtitle workflows. No post-processing.
- **Language selection with auto-translate** — request `en`, `de`, `es`… and where the exact track is missing, YouTube's translated track is used when available.
- **Metadata included free** — title, channel, view count, duration, keywords, description and thumbnails ride along on every transcript row.
- **Bulk-friendly** — paste hundreds of URLs; failed videos are isolated and never billed.

#### 🎯 Use cases

| Who | What they do with it |
|---|---|
| **AI & LLM builders** | Feed clean plain-text transcripts into RAG pipelines, summarizers, and agents (MCP-friendly output). |
| **Content & SEO teams** | Repurpose videos into articles, show notes, and quote pulls; mine competitor channels for topics. |
| **Researchers & analysts** | Build searchable corpora from talks, interviews and news coverage, with timestamps intact. |
| **Subtitle & localization teams** | Get SRT/VTT straight from the source, plus translated tracks where YouTube offers them. |
| **Media monitoring** | Track what's being said about brands and people across YouTube at scale. |

#### 📥 Supported inputs

| Input | Example |
|---|---|
| Standard video URLs | `https://www.youtube.com/watch?v=dQw4w9WgXcQ` |
| Short links | `https://youtu.be/dQw4w9WgXcQ` |
| Shorts | `https://www.youtube.com/shorts/{id}` |

**Not supported:** private, members-only or age-gated videos, and live streams still in progress. To transcribe a whole channel, list its videos with the [YouTube Channel Videos scraper](https://apify.com/memo23/youtube-channel-video-details-scraper) and feed the URLs here.

#### 🔄 How a run works

1. Each URL is resolved to its video ID and fetched with browser-grade TLS.
2. The caption track in your requested language is located (auto-translate applied when needed).
3. If captions are missing or blocked, the ladder steps down: DownSub → yt-dlp subtitles → (opt-in) Whisper AI speech-to-text.
4. Segments are normalised to timestamped JSON and rendered to SRT and VTT.
5. One row per video is pushed — transcript, formats, and metadata together.

#### ⚙️ Input parameters

| Field | Type | Default | Notes |
|---|---|---|---|
| `startUrls` | array | — | Video/Shorts URLs, any standard form |
| `language` | string | `default` | Caption language code (`en`, `de`, …); `default` = the video's original track |
| `whisperFallback` | boolean | `false` | Whisper AI speech-to-text for caption-less videos — billed per transcribed video as a premium event |
| `maxItems` | integer | `100` | Hard cap on billed transcript rows |
| `maxConcurrency` | integer | `10` | Parallel video fetches |
| `proxy` | object | Automatic | Paid-plan runs use the actor's built-in premium residential pool automatically |

#### 📊 Output overview

One row per video. The transcript appears three ways — `transcript` (timestamped segments), `transcript_only_text` (plain text), and `transcript_srt` / `transcript_vtt` (ready-to-save subtitle files) — alongside the video's metadata. Rows where every source failed carry a `transcriptError` explaining why (and are still real video rows, with metadata).

#### 📦 Output sample

Real trimmed row from a live run:

```json
{
    "videoId": "dQw4w9WgXcQ",
    "title": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)",
    "author": "Rick Astley",
    "channelId": "UCuAXFkgsw1L7xaCfnd5JJOw",
    "lengthSeconds": "213",
    "viewCount": "1699540216",
    "transcript": [
        { "text": "[♪♪♪]", "startMs": "1360", "endMs": "3040", "startTimeText": "0:01" },
        { "text": "♪ We're no strangers to love ♪", "startMs": "18800", "endMs": "22140", "startTimeText": "0:18" }
    ],
    "transcript_only_text": "[♪♪♪] ♪ We're no strangers to love ♪ ♪ You know the rules and so do I ♪ …",
    "transcript_srt": "1\n00:00:01,360 --> 00:00:03,040\n[♪♪♪]\n…",
    "transcript_vtt": "WEBVTT\n\n00:00:01.360 --> 00:00:03.040\n[♪♪♪]\n…",
    "keywords": ["rick astley", "Never Gonna Give You Up", "nggyu"],
    "thumbnail": { "thumbnails": [{ "url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/…", "width": 168, "height": 94 }] }
}
```

#### 🗂 Key output fields

| Field | Meaning |
|---|---|
| `transcript[]` | Timestamped segments: `text`, `startMs`, `endMs`, `startTimeText` |
| `transcript_only_text` | The whole transcript as one plain string — LLM-ready |
| `transcript_srt` / `transcript_vtt` | Complete subtitle files as strings — save and use directly |
| `transcriptSource` | Which ladder step produced it (captions / downsub / yt-dlp / whisper) |
| `videoId`, `title`, `author`, `channelId` | Video identity |
| `viewCount`, `lengthSeconds`, `keywords`, `shortDescription`, `thumbnail` | Metadata that rides along free |
| `transcriptError`, `transcriptSkipped` | Present only when every source failed for a video |

#### ❓ FAQ

**What happens with videos that have no captions?**
Without `whisperFallback` they return metadata plus a `transcriptError`. With `whisperFallback: true`, the audio is downloaded and transcribed by Whisper speech-to-text — billed as a separate premium event per video, only when it actually produces a transcript. Whisper handles videos up to 30 minutes long.

**Which languages are supported?**
Any language YouTube has a caption track for. Set `language` to a code like `de` or `es`; when that exact track is missing, YouTube's auto-translated track is used where available.

**Can I transcribe a whole channel or playlist?**
Feed video URLs in bulk. To harvest a channel's URLs first, use the [YouTube Channel Videos scraper](https://apify.com/memo23/youtube-channel-video-details-scraper) and pipe its output here. Native channel expansion is on the roadmap.

**Do I need to configure proxies?**
No. Runs on a paid Apify plan go through the actor's built-in premium residential pool automatically — YouTube throttles datacenter IPs aggressively, and this keeps success rates high at volume with zero setup. Free-plan runs use Apify's automatic proxy, and the `proxy` input lets them supply their own.

**Do failed videos cost me anything?**
No placeholder-row billing games: a video that produces no row bills nothing, and Whisper is only charged when it delivers text.

#### 💬 Support

Found a bug or missing a field? Open an issue on the actor's **Issues tab** in Apify Console — issues are answered within 1–2 business days.

#### 🛠 Additional services

Need scheduled transcript archives, a merged multi-platform transcript feed (YouTube + TikTok + Instagram + Loom), or delivery straight to your database? Custom builds and SLAs available — contact me through the actor page.

#### 🔎 Explore more scrapers

Same developer, same stack: [Video & Audio Transcriber (Whisper)](https://apify.com/memo23/video-audio-transcriber), [Instagram Transcript Scraper](https://apify.com/memo23/instagram-transcript-cheerio), [YouTube Comments](https://apify.com/memo23/youtube-comments-scraper), [YouTube Search](https://apify.com/memo23/youtube-search-results-scraper) — and the full portfolio at [memo23 on Apify Store](https://apify.com/memo23).

#### 🤖 For AI Agents & LLM Apps

Built for machine consumption: `transcript_only_text` drops straight into a context window; timestamped segments support citation and chaptering; stable field names across every row. Pair with the [Video Transcripts MCP Server](https://apify.com/memo23/transcripts-mcp-server) to expose transcripts as a tool in agent frameworks. Keep `maxItems` low per call for cost control; every row is self-contained.

***

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by YouTube or Google LLC. All trademarks mentioned are the property of their respective owners.

The scraper accesses only publicly available video pages and caption data — no login, no age-gated, members-only or private content. Users are responsible for ensuring their use complies with YouTube's Terms of Service, copyright law as it applies to transcript content, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organisation.

***

### SEO Keywords

youtube transcript scraper, youtube transcript api, extract youtube transcript, youtube captions scraper, youtube subtitles downloader, srt from youtube, vtt from youtube, youtube video to text, youtube transcription tool, whisper youtube transcription, transcribe youtube videos without captions, youtube transcript for llm, youtube rag pipeline, bulk youtube transcripts, youtube caption extractor, video to text api, youtube shorts transcript, youtube transcript json, apify youtube transcript, pintostudio alternative, youtube-transcript-scraper alternative

# Actor input Schema

## `startUrls` (type: `array`):

Video URLs in any form — `youtube.com/watch?v=…`, `youtu.be/…` or Shorts links. Paste as many as you like; each becomes one transcript row. To transcribe a whole channel, list its videos with the YouTube Channel Videos scraper first and feed the URLs here.

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

Preferred caption language code (e.g. `en`, `de`, `es`). `default` takes the video's original track. When the exact track is missing, YouTube's auto-translate is used where available.

## `whisperFallback` (type: `boolean`):

When a video has no captions at all, download its audio and transcribe it with Whisper speech-to-text. Billed as a separate premium event per transcribed video — see the pricing tab. Off by default so you never pay it unknowingly. Applies to videos up to 30 minutes long.

## `maxItems` (type: `integer`):

Hard cap on transcript rows for the run — your spend guard. Applies per run, across all input URLs (matters for channel expansion).

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

Parallel video fetches.

## `minConcurrency` (type: `integer`):

Lower bound for the autoscaled pool.

## `maxRequestRetries` (type: `integer`):

Retries per video before it is skipped (skipped videos are never billed).

## `proxy` (type: `object`):

Runs on a paid Apify plan are routed through the actor's built-in premium residential pool automatically — no configuration needed. This setting applies to free-plan runs, which default to Apify's automatic proxy.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "language": "default",
  "whisperFallback": false,
  "maxItems": 100,
  "maxConcurrency": 10,
  "minConcurrency": 1,
  "maxRequestRetries": 3,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "startUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ],
    "proxy": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

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