# YouTube Transcript Scraper (`lagenuina_agency/youtube-transcript-scraper`) Actor

YouTube transcript API: captions and subtitles of videos, Shorts, playlists and whole channels as clean text, timestamped segments, SRT or VTT. Language picking, video metadata, auto residential fallback. 20% cheaper than the leader; failed videos are free.

- **URL**: https://apify.com/lagenuina_agency/youtube-transcript-scraper.md
- **Developed by:** [Quelli di Carne Genuina](https://apify.com/lagenuina_agency) (community)
- **Categories:** Videos, AI, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 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

## YouTube Transcript Scraper

A fast **YouTube transcript API**: get the **captions / subtitles** of any YouTube video, **Shorts**, **playlist** or **whole channel** as clean text for LLMs, **timestamped segments**, **SRT** or **VTT**. Pick the language, prefer human captions over auto-generated ones, get the video metadata for free. Videos without captions are never charged.

> Independent tool, not affiliated with or endorsed by YouTube or Google LLC. It reads the same public captions you see in the YouTube player.

### What you get

One row per video (real result, shortened):

```json
{
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "video_id": "dQw4w9WgXcQ",
  "language": "English",
  "language_code": "en",
  "is_generated": false,
  "source_type": "Manual",
  "total_seconds": 211.32,
  "duration_human": "3m 31s",
  "snippet_count": 61,
  "word_count": 487,
  "timestamped": [{ "text": "♪ We're no strangers to love ♪", "start": 18.64, "duration": 3.24 }],
  "non_timestamped": "[♪♪♪] ♪ We're no strangers to love ♪ ♪ You know the rules and so do I ♪ ...",
  "title": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)",
  "channel_name": "Rick Astley",
  "channel_id": "UCuAXFkgsw1L7xaCfnd5JJOw",
  "view_count": 1827520389,
  "video_duration_seconds": 213,
  "thumbnail_url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
  "success": true
}
```

**Try it in 1 click:** press *Start* with the prefilled two videos. In our test it finished in about 5 seconds at 512 MB and costs $0.0044 on the Apify Free plan (less on paid plans).

**Price:** $2.20 per 1,000 transcripts on the Free plan, down to $1.60 on Gold and above. Platform usage and proxies included, no start fee, failed videos and videos without captions free.

### Why this YouTube transcript scraper

- **20% cheaper than johnvc/YoutubeTranscripts on every plan** ($2.20 vs $2.75 per 1,000 on Free, $1.60 vs $2.00 on Gold), with the same input field names, so you switch by changing the actor ID.
- **Pay only for transcripts you get**: no captions, wrong language, private or deleted video = an error row that tells you why, not charged.
- **Doesn't get stuck on blocks**: YouTube blocks datacenter IPs for captions; the actor detects it and moves to residential proxy automatically, at no extra cost to you.
- **Whole channels and playlists**: paste a channel or playlist URL and get every transcript (up to 5,000 videos per source), or list the videos for free first.
- **Ready for AI**: `non_timestamped` is one clean string for LLMs and RAG; `timestamped` keeps start and duration of every caption for citations and video chapters; `word_count` helps you budget tokens.

### What you can do with it

- **RAG and LLM datasets**: turn a channel or a playlist of lectures into a searchable text corpus.
- **AI agents that watch YouTube**: let Claude, ChatGPT or Cursor read a video before answering (see MCP below).
- **Content repurposing**: blog posts, newsletters, summaries, social clips with exact timestamps.
- **SEO and market research**: what competitors and creators actually say, keyword by keyword.
- **Subtitles**: download SRT or VTT files of your own or public videos.

### Input

```json
{
  "youtube_url": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "https://youtu.be/jNQXAC9IVRw"],
  "languages": ["en", "es"],
  "transcript_type": "any",
  "output_formats": ["srt"]
}
```

| Field | What it does |
|---|---|
| `youtube_url` | One URL or a list. Videos, Shorts, youtu.be, embed, live, mobile URLs and bare video IDs. Playlist URLs are expanded and transcribed; channel URLs are treated like `channel`. |
| `channel` | @handle, bare handle, channel ID (`UC...`) or channel URL. A `/videos`, `/shorts` or `/streams` URL keeps that tab. |
| `max_videos` | Videos per channel (newest first) or playlist. Default 100, max 5,000. |
| `channel_transcripts` | `true` = transcribe the channel videos; `false` (default) = list them only, free. |
| `playlist_transcripts` | `true` (default) = transcribe playlist videos; `false` = list them only, free. |
| `languages` | Ordered language codes, first available wins. Manual captions beat auto-generated ones in the same language; `es` also matches `es-419`. Default `["en"]`. |
| `transcript_type` | `any` (default), `manual` or `generated`. |
| `translate_to` | Ask YouTube to translate the transcript (best effort, see limits). |
| `output_formats` | Extra fields: `srt`, `vtt`, `text` (one caption per line). |
| `include_metadata` | Title, description, channel, views, duration, thumbnail, tags, was_live. Default on, free. |
| `preserve_formatting` | Keep `<i>` / `<b>` tags in the text. |
| `list_only` | Only list the caption tracks of each video (languages, manual / auto, translation targets). Free. |
| `maxConcurrency`, `proxyConfiguration` | Parallel videos (default 10) and proxy. |

Also accepted for easy migration: `videoUrls`, `urls`, `startUrls` (lists of URLs) and `language` (a single code).

### Output

- **Transcript row** (`success: true`): the fields shown above plus `is_translatable`, `translation_languages`, `description`, `channel_url`, `tags`, `was_live`, `fetched_at`, and `srt` / `vtt` / `text` when requested. Videos from a playlist or channel carry `source`.
- **Error row** (`success: false`, not charged): `error_type` (`TranscriptsDisabled`, `NoTranscriptFound`, `VideoUnavailable`, `AgeRestricted`, `InvalidInput`, `RequestBlocked`...), `error_message`, `is_permanent_error`, and for `NoTranscriptFound` the `available_transcripts` YouTube offers, so you can retry with the right language:

```json
{
  "url": "https://www.youtube.com/watch?v=4WUVkpC8MKs",
  "success": false,
  "error_type": "NoTranscriptFound",
  "error_message": "No captions in en; available_transcripts lists the caption tracks YouTube offers.",
  "available_transcripts": [{ "language": "Russian (auto-generated)", "language_code": "ru", "is_generated": true, "is_translatable": true }],
  "title": "A New Take on an Ancient Sound | Tina Lajevardian | TED"
}
```

- **Listing row** (`result_type: "channel_video"` or `"playlist_video"`, free): `video_id`, `url`, `title`, `video_duration_seconds`, `view_count`, `published`, `thumbnail_url`.

### Pricing

Pay per transcript, platform usage and proxies included. The price depends on your Apify plan:

| Event | Free | Bronze | Silver | Gold, Platinum, Diamond |
|---|---|---|---|---|
| Transcript (one video with captions, any length, metadata included) | $0.0022 | $0.0020 | $0.0018 | $0.0016 |
| Video without captions, failed video, listing row, `list_only` row | free | free | free | free |
| Run start | free | free | free | free |

Examples on the Free plan: 1,000 transcripts = $2.20 ($1.60 on Gold). A 3-hour podcast costs the same as a 30-second Short. Set a maximum total charge to cap spending; the actor stops cleanly when it is reached.

### Migrating from johnvc/YoutubeTranscripts

The input field names are the same, so an existing input usually works after changing the actor ID to `lagenuina_agency/youtube-transcript-scraper`.

| johnvc/YoutubeTranscripts input | This actor | Notes |
|---|---|---|
| `youtube_url` | `youtube_url` | Same; no 100-URL limit per run. Playlist URLs are also expanded. |
| `languages` | `languages` | Same. |
| `translate_to` | `translate_to` | Same, best effort (see limits). |
| `transcript_type` | `transcript_type` | Same values. |
| `output_formats` | `output_formats` | Same: `srt`, `vtt`, `text`. |
| `preserve_formatting` | `preserve_formatting` | Same. |
| `list_only` | `list_only` | Same, free. |
| `include_metadata` | `include_metadata` | Same basic metadata, free. |
| `channel`, `max_videos`, `channel_transcripts` | same names | Same; `max_videos` up to 5,000. |
| `include_extended_metadata` | (not supported) | Like count, upload date, categories are not returned. |
| `max_age_days` | (not needed) | Ignored: every transcript is fetched fresh from YouTube. |
| (not available) | `playlist_transcripts` | Extra: playlists. |

**Output:** the same field names (`url`, `video_id`, `language`, `language_code`, `is_generated`, `is_translatable`, `translation_languages`, `total_seconds`, `duration_human`, `source_type`, `snippet_count`, `timestamped`, `non_timestamped`, `title`, `channel_name`, `channel_id`, `channel_url`, `view_count`, `video_duration_seconds`, `thumbnail_url`, `tags`, `was_live`, `success`, `error_type`, `error_message`, `available_transcripts`). Extra: `word_count`, `source`. Not returned: `like_count`, `upload_date`, `categories`, `availability`, `cached`.

**Price per 1,000 transcripts** (public Apify Store prices, checked on 17 October 2026):

| Apify plan | johnvc/YoutubeTranscripts | This actor |
|---|---|---|
| Free | $2.75 | $2.20 |
| Bronze | $2.50 | $2.00 |
| Silver | $2.25 | $1.80 |
| Gold / Platinum / Diamond | $2.00 | $1.60 |

Both include platform usage and proxies; failed videos are free on both.

### Limits / not supported

- Only videos that have captions (manual or auto-generated) can be transcribed. There is no speech-to-text for videos without captions.
- **Translation is best effort**: YouTube currently refuses most automated translation requests. When that happens you get the original transcript and a `translation_error` field, charged once as a normal transcript.
- Age-restricted, private, members-only and deleted videos return an error row (not charged): they need a signed-in account, which this actor never uses.
- Live streams in progress and premieres not yet aired have no transcript.
- Channel listing reads the Videos tab by default; pass a `/shorts` or `/streams` URL for the other tabs. `published` is YouTube's relative text ("2 months ago").
- No `like_count` / `upload_date` (johnvc's paid extended metadata).

### Use it from AI agents (MCP)

This actor is a ready-made tool for any MCP client (Claude, ChatGPT, Cursor, custom agents) through the Apify MCP server:

```json
{
  "mcpServers": {
    "apify": { "url": "https://mcp.apify.com/?actors=lagenuina_agency/youtube-transcript-scraper" }
  }
}
```

Ask things like *"Get the transcript of https://youtu.be/dQw4w9WgXcQ and summarise it in 5 bullets"* or *"Transcribe the last 20 videos of @TED and tell me which talks mention AI"*.

### Integrations and API

Call it from your code with the official Apify clients (full examples: [github.com/assa83/youtube-transcript-scraper-api](https://github.com/assa83/youtube-transcript-scraper-api)):

```python
## pip install apify-client
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("lagenuina_agency/youtube-transcript-scraper").call(run_input={"youtube_url": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"]})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item.get("non_timestamped", item.get("error_message"))[:200])
```

```js
// npm i apify-client
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('lagenuina_agency/youtube-transcript-scraper').call({ youtube_url: ['https://www.youtube.com/watch?v=dQw4w9WgXcQ'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

No-code: use the Apify app in **n8n**, **Make** or **Zapier** (action "Run Actor", pick `lagenuina_agency/youtube-transcript-scraper`), or the `langchain-apify` / CrewAI `ApifyActorsTool` integrations for AI agents. Results can also be pushed to Google Sheets, Slack, webhooks or any S3 bucket via Apify integrations.

### More tools from Quelli di Carne Genuina

**Ad intelligence**

- [Google Ads Transparency Scraper](https://apify.com/lagenuina_agency/google-ads-transparency-scraper): every ad a brand or domain runs on Google Search, YouTube, Shopping, Maps and Play.
- [Meta Ad Library Scraper](https://apify.com/lagenuina_agency/meta-ad-library-scraper): Facebook and Instagram ads by page, keyword or Ad Library URL, with creatives and landing pages.
- [TikTok Top Ads Scraper](https://apify.com/lagenuina_agency/tiktok-top-ads-scraper): top-performing TikTok ads from the Creative Center with CTR, likes and MP4 video URLs.
- [LinkedIn Ad Library Scraper](https://apify.com/lagenuina_agency/linkedin-ad-library-scraper): B2B ads of any company from the public LinkedIn Ad Library, with targeting and impressions.

**Competitor & SEO research**

- [Similarweb Website Traffic Scraper](https://apify.com/lagenuina_agency/similarweb-scraper): monthly visits, ranks, traffic sources and top countries for any list of domains.
- [Google Trends Scraper](https://apify.com/lagenuina_agency/google-trends-scraper): interest over time, by region, related queries and Trending Now.
- [Google Play Store Scraper](https://apify.com/lagenuina_agency/google-play-scraper): app search, details, top charts and reviews from Google Play, any country.

**Travel prices**

- [Google Hotels Scraper](https://apify.com/lagenuina_agency/google-hotels-scraper): hotel prices and every booking site's rate for any city and dates.
- [Google Flights Scraper](https://apify.com/lagenuina_agency/google-flights-scraper): fares, airlines, stops, price level and price calendar for any route and date.

**Retail prices**

- [Woolworths AU Product Scraper](https://apify.com/lagenuina_agency/woolworths-scraper): Woolworths Australia grocery prices, specials, unit prices and barcodes.
- [Coles AU Product Scraper](https://apify.com/lagenuina_agency/coles-scraper): Coles Australia grocery prices, half-price specials, unit prices and barcodes.

**Content & social data**

- [Medium Scraper](https://apify.com/lagenuina_agency/medium-scraper): Medium articles by tag, author or search, with full text as Markdown.
- [Likee Scraper](https://apify.com/lagenuina_agency/likee-scraper): Likee videos, profiles and creator engagement analytics.

### FAQ

**How do I get the transcript of a YouTube video?** Paste the video URL in `youtube_url` and press Start: you get the full text and the timestamped captions in seconds, as JSON, CSV, Excel or via API.

**Is there an official YouTube transcript API?** The YouTube Data API only downloads captions of videos you own (OAuth required). This actor reads the public captions of any video, no Google account needed.

**youtube-transcript-api (Python) not working, "RequestBlocked" or "IpBlocked"?** YouTube blocks cloud and datacenter IPs. This actor handles blocking with automatic residential proxy fallback, and you call it from Python with `apify-client` instead.

**Does it work for YouTube Shorts and live replays?** Yes: Shorts, `/live/` replays, embeds and youtu.be links all work when the video has captions.

**Can I download a whole channel or playlist transcript?** Yes: put the channel in `channel` with `channel_transcripts: true`, or paste a playlist URL in `youtube_url`. Up to 5,000 videos per source.

**Auto-generated subtitles or manual?** By default manual captions are preferred and auto-generated are used when there is nothing else (`source_type` tells you which). Force one with `transcript_type`.

**Can I get SRT or VTT subtitle files?** Yes: `output_formats: ["srt", "vtt"]` adds them to each row.

**What if a video has no transcript?** You get an error row (not charged) with the reason and, if other languages exist, the list of available transcripts.

**Is scraping YouTube transcripts legal?** The actor reads publicly available captions. You are responsible for how you use them; respect copyright and YouTube's terms.

**Something broke?** Open an issue on the Issues tab: we answer within 24 hours.

# Actor input Schema

## `youtube_url` (type: `string,array`):

One URL as a string, or many as an array. Works with videos, Shorts, youtu.be links, embed / live / mobile URLs and bare 11-character video IDs. Playlist URLs (or IDs such as PL...) are expanded to their videos and transcribed; channel URLs (@handle, /channel/, /c/, /user/) are treated like the 'channel' input. Invalid entries become error rows and never stop the run. Same field name as johnvc/YoutubeTranscripts, so existing inputs work unchanged.

## `channel` (type: `string,array`):

Optional. One channel or many: @handle, bare handle, channel ID (UC...) or any channel URL. A /videos, /shorts or /streams URL keeps that tab. Each channel is listed newest first up to 'Max videos'. Listing rows are free; enable 'Fetch transcripts for channel videos' to transcribe them.

## `max_videos` (type: `integer`):

How many videos to take from each channel (newest first) or playlist. Default 100, max 5000.

## `channel_transcripts` (type: `boolean`):

If true, every listed channel video is also transcribed (charged per successful transcript). If false, channels are only listed (free).

## `playlist_transcripts` (type: `boolean`):

If true (default), every video of a playlist URL is transcribed. If false, the playlist is only listed (free).

## `languages` (type: `array`):

Ordered ISO 639-1 codes; the first language available wins (manual captions beat auto-generated ones in the same language). "es" also matches regional tracks like "es-419". Default \["en"]. If none matches, the row lists available_transcripts so you can retry.

## `translate_to` (type: `string`):

Optional ISO 639-1 code (e.g. "it", "fr"). The chosen transcript is translated by YouTube. If YouTube does not serve the translation, you get the original transcript plus a translation_error field.

## `transcript_type` (type: `string`):

Which caption tracks to consider: any (default), manual (human-made only) or generated (auto-generated only).

## `output_formats` (type: `array`):

Extra fields to add to each transcript: "srt" (SubRip), "vtt" (WebVTT), "text" (one line per caption). The joined text (non_timestamped) and the timestamped segments are always included.

## `include_metadata` (type: `boolean`):

Title, description, channel, view count, duration, thumbnail, tags and was_live, from the same response as the captions: no extra request, no extra charge.

## `preserve_formatting` (type: `boolean`):

Keep YouTube's <i> / <b> tags in caption text. Default false (clean text).

## `list_only` (type: `boolean`):

Do not download captions: return, for each video, the caption tracks YouTube offers (languages, manual / auto-generated, translation targets). Free.

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

Videos processed in parallel.

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

Apify Proxy by default. If YouTube blocks the IP, the run switches to residential proxy automatically, at no extra cost to you.

## Actor input object example

```json
{
  "youtube_url": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ],
  "max_videos": 100,
  "channel_transcripts": false,
  "playlist_transcripts": true,
  "languages": [
    "en"
  ],
  "transcript_type": "any",
  "output_formats": [],
  "include_metadata": true,
  "preserve_formatting": false,
  "list_only": false,
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "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 = {
    "youtube_url": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/watch?v=jNQXAC9IVRw"
    ],
    "languages": [
        "en"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

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