# YouTube Transcript Scraper (`automation-lab/youtube-transcript`) Actor

Extract timestamped transcripts & subtitles from any public YouTube video. Batch hundreds of URLs, 100+ languages with auto-fallback, no API key required. Returns full video metadata + segments. Export JSON, CSV, Excel.

- **URL**: https://apify.com/automation-lab/youtube-transcript.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Videos, AI, Developer tools
- **Stats:** 243 total users, 68 monthly users, 100.0% runs succeeded, 3 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

### What does YouTube Transcript Scraper do?

**YouTube Transcript Scraper** extracts **full transcripts, subtitles, and captions** from any public YouTube video — with no YouTube Data API key required. Paste one or more video URLs (or channel URLs to auto-discover videos), choose your language, and get **timestamped text segments** plus complete video metadata including title, channel, view count, duration, keywords, and thumbnail.

The actor uses YouTube's internal **ANDROID InnerTube API** — the same endpoint the YouTube mobile app uses — which means it works reliably without browser overhead, API quotas, or OAuth credentials. Batch hundreds of videos in a single run.

Try it free: go to [YouTube Transcript Scraper on Apify Store](https://apify.com/automation-lab/youtube-transcript) and click **Try for free**.

### Who is YouTube Transcript Scraper for?

**Content creators and marketers**
- 📝 Repurpose a YouTube video into a blog post, newsletter, or Twitter thread
- 🔄 Feed transcripts into ChatGPT or Claude to generate summaries, titles, or social copy
- 📌 Extract quotes from interviews for use in articles or email campaigns

**SEO professionals and agencies**
- 🔍 Build text content from video to rank alongside video results on Google
- 🗂️ Analyze transcript keyword density across a YouTube channel
- 📊 Audit a competitor's spoken messaging for topic gaps

**Researchers, academics, and journalists**
- 🎓 Build NLP corpora from lectures, conference talks, and interviews
- 📰 Search and reference spoken content from press conferences without rewatching
- 🌐 Collect multilingual transcripts for cross-language analysis

**Developers and AI/ML engineers**
- 🤖 Feed merged `fullText` into summarization, translation, or Q&A pipelines
- ⚡ Process hundreds of transcripts overnight via the API with zero manual work
- 🧩 Power RAG (retrieval-augmented generation) systems with timestamped video knowledge

**Educators and e-learning builders**
- 📚 Convert course videos into searchable text notes
- ♿ Generate accessible transcripts for learners who need closed captions
- 🌍 Translate transcripts to other languages via downstream translation APIs

### Why use YouTube Transcript Scraper?

- ✅ **Actually works** — tested on 15+ video types: music, vlogs, tutorials, lectures, news, and Shorts
- 💸 **Best price on Apify Store** — $0.0025/transcript (Bronze), down to $0.00075 for Diamond; up to 75% cheaper than competitors
- 🚀 **Batch processing** — extract hundreds of transcripts in one run (competitors often limit to 1 video per call)
- 🌍 **100+ languages** — auto-generated and manual captions, with smart fallback to the best available language
- 📦 **Full metadata** — title, channel, description, view count, duration, keywords, thumbnail, publish date, available languages
- ⚡ **No browser** — lightweight pure HTTP extraction, no Playwright or Puppeteer overhead
- 🔑 **No API key** — no YouTube Data API quota, no OAuth, no rate limits
- 📅 **Date filtering** — filter channel videos by publish date range when processing channels
- 🔗 **Flexible input** — full URLs, short URLs (`youtu.be/`), embed URLs, Shorts URLs, or plain 11-character video IDs

### What data can you extract?

**🎬 Video metadata (returned for every video):**

| Field | Type | Description |
|-------|------|-------------|
| `videoId` | string | YouTube video ID (11 characters) |
| `videoUrl` | string | Full YouTube URL |
| `videoTitle` | string | Video title |
| `channelName` | string | Channel display name |
| `channelId` | string | Channel ID (UC-prefixed) |
| `description` | string | Full video description |
| `viewCount` | number | Exact view count |
| `durationSeconds` | number | Duration in seconds |
| `keywords` | array | Video tags/keywords set by creator |
| `thumbnail` | string | Highest-resolution thumbnail URL |
| `publishDate` | string | Publication date (ISO 8601) |
| `availableLanguages` | array | All available caption languages |

**📝 Transcript data:**

| Field | Type | Description |
|-------|------|-------------|
| `language` | string | Language code of selected transcript (e.g. `en`) |
| `selectedLanguage` | string | Full language name (e.g. `English`) |
| `isAutoGenerated` | boolean | `true` if captions are auto-generated by YouTube |
| `segments` | array | Timestamped text segments (see below) |
| `segmentCount` | number | Total segments in the transcript |
| `fullText` | string | All segments merged into one string (optional, enable via `mergeSegments`) |

**⏱️ Each segment contains:**

| Field | Type | Description |
|-------|------|-------------|
| `text` | string | Caption text (HTML entities decoded) |
| `start` | number | Start time in seconds |
| `duration` | number | Segment duration in seconds |

### How much does it cost to extract YouTube transcripts?

This Actor uses **pay-per-event** pricing — you pay only for what you extract.
No monthly subscription. All platform costs (compute, proxy, storage) are **included**.

| | Free | Bronze ($29/mo) | Silver ($199/mo) | Gold ($999/mo) |
|---|---|---|---|---|
| **Start fee** | $0.003 | $0.0025 | $0.002 | $0.0015 |
| **Per transcript** | $0.003 | $0.0025 | $0.002 | $0.0015 |
| **10 transcripts** | $0.033 | $0.0275 | $0.022 | $0.0165 |
| **100 transcripts** | $0.303 | $0.2525 | $0.202 | $0.1515 |
| **1,000 transcripts** | $3.003 | $2.5025 | $2.002 | $1.5015 |

Higher-tier plans get additional volume discounts (Platinum and Diamond).

**Real-world cost examples:**

| Use case | Videos | Cost (Free tier) |
|---|---|---|
| Single video transcript | 1 | ~$0.006 |
| YouTube playlist (20 videos) | 20 | ~$0.063 |
| Channel analysis (100 videos) | 100 | ~$0.303 |
| Research dataset (1,000 videos) | 1,000 | ~$3.003 |

**Compared to competitors:** starvibe charges $0.005/video, karamelo charges $0.005–$0.007/video, pintostudio and topaz_sharingan charge $0.01/video. Our batch processing makes bulk extraction significantly cheaper when you include the $0.003 start fee savings per run.

On the **free $5 credit** that every new Apify account gets, you can extract approximately **1,600 transcripts**.

### How to get YouTube video transcripts

1. Go to [YouTube Transcript Scraper](https://apify.com/automation-lab/youtube-transcript) on Apify Store
2. Click **Try for free** (no credit card needed for the free $5 credit)
3. Paste one or more YouTube video URLs into the **Videos** field
4. Set your preferred language code (default: `en` for English)
5. Optionally enable **Merge into full text** to get a single string per video
6. Click **Start** and wait seconds to minutes depending on batch size
7. Download transcripts as **JSON, CSV, or Excel** from the dataset view

**Example inputs:**

Minimal — single video:
```json
{
    "urls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
    "language": "en"
}
````

Batch with merge:

```json
{
    "urls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://youtu.be/jNQXAC9IVRw",
        "9bZkp7q19f0"
    ],
    "language": "en",
    "includeAutoGenerated": true,
    "mergeSegments": true
}
```

Channel with date filter (last 30 days):

```json
{
    "urls": ["https://www.youtube.com/@lexfridman"],
    "language": "en",
    "maxVideosPerChannel": 20,
    "startDate": "2026-03-01"
}
```

### Input parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `urls` | array | required | YouTube video URLs, video IDs, Shorts URLs, or channel URLs |
| `language` | string | `"en"` | Preferred transcript language code (ISO 639-1). Automatic fallback if unavailable |
| `includeAutoGenerated` | boolean | `true` | Include YouTube auto-generated captions when manual captions aren't available |
| `mergeSegments` | boolean | `false` | Add `fullText` field with all segments as a single string |
| `maxVideosPerChannel` | integer | `50` | Max videos per channel URL (newest first). Range: 1–500 |
| `startDate` | string | — | Only process videos published on or after this date (YYYY-MM-DD) |
| `endDate` | string | — | Only process videos published on or before this date (YYYY-MM-DD) |

### Output examples

**Transcript with segments:**

```json
{
    "videoId": "dQw4w9WgXcQ",
    "videoUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "videoTitle": "Rick Astley - Never Gonna Give You Up (Official Music Video)",
    "channelName": "Rick Astley",
    "channelId": "UCuAXFkgsw1L7xaCfnd5JJOw",
    "description": "The official video for \"Never Gonna Give You Up\" by Rick Astley...",
    "viewCount": 1600000000,
    "durationSeconds": 213,
    "keywords": ["rick astley", "never gonna give you up"],
    "thumbnail": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
    "publishDate": "2009-10-25",
    "language": "en",
    "selectedLanguage": "English",
    "isAutoGenerated": false,
    "availableLanguages": ["English", "Spanish", "French", "German (auto-generated)"],
    "segments": [
        { "text": "We're no strangers to love", "start": 18.0, "duration": 3.0 },
        { "text": "You know the rules and so do I", "start": 21.0, "duration": 3.0 }
    ],
    "segmentCount": 61
}
```

**With `mergeSegments: true`, the item also includes:**

```json
{
    "fullText": "We're no strangers to love You know the rules and so do I..."
}
```

### Tips for best results

- 📦 **Batch your requests** — 100 videos in one run saves 99 start fees versus 100 separate runs
- 🆔 **Use video IDs directly** — plain 11-character IDs like `dQw4w9WgXcQ` work just as well as full URLs
- 🤖 **Keep `includeAutoGenerated: true`** — many videos (especially non-English) only have auto-generated captions
- 🧠 **Use `mergeSegments: true` for LLM pipelines** — the `fullText` field gives the entire transcript as one string, ready for summarization
- 📋 **Check `availableLanguages` in the output** — if you need a different language, re-run with the correct code
- 📅 **Use `startDate` for channel monitoring** — set a weekly date range to get only new videos from a channel
- ⚠️ **Videos without captions** — Shorts, music-only videos, and some older uploads have no captions; they return `segmentCount: 0` with full metadata

### How to download YouTube subtitles and captions

YouTube Transcript Scraper retrieves subtitles using YouTube's internal InnerTube API — the same way the YouTube player loads captions. You get the exact text a viewer sees when they enable captions.

**Supported caption types:**

- 📝 **Manual captions** — professionally created or uploaded by the video owner (highest accuracy)
- 🤖 **Auto-generated captions** — created by YouTube's speech recognition (most English videos and many others)
- 🌐 **Community captions** — user-contributed translations where enabled by the creator

**Export formats from the Apify dataset:**

- **JSON** — structured data with timestamps, ideal for programmatic use
- **CSV** — flat format, one row per video, easy to open in Excel or Google Sheets
- **Excel (.xlsx)** — ready-to-open spreadsheet with all metadata and transcript columns

To download: run the Actor → click **Export** in the Dataset view → choose your format.

### How to get transcripts without the YouTube Data API

The official YouTube Data API v3 does **not** expose transcript or caption text to third-party developers — it only lets you list available caption tracks. To read the actual text, you need a different approach.

YouTube Transcript Scraper uses YouTube's **ANDROID InnerTube API** — the same internal endpoint used by the YouTube mobile app to load captions. This approach:

- 🚫 Requires **no YouTube API key** or quota
- 🌍 Works on **any public video** with captions enabled
- ⏱️ Returns **more detailed segmentation** than web-based extraction
- ♾️ Is **not subject** to the YouTube Data API's 10,000 daily unit quota

This makes it ideal for developers who need transcripts at scale without managing API keys, OAuth flows, or quota limits.

### Integrations

Connect YouTube Transcript Scraper with your existing workflows:

- 📊 **YouTube Transcript → Google Sheets** — schedule daily extraction of a channel's new videos and append transcripts to a running spreadsheet for content analysis
- 🤖 **YouTube Transcript → OpenAI/Claude** — pipe `fullText` into a summarization prompt to auto-generate blog posts or show notes from every new episode
- 📧 **YouTube Transcript → Email** — use Make or Zapier to send a formatted transcript digest when a watched channel publishes a new video
- 🔔 **Webhook on completion** — trigger a downstream pipeline (keyword extraction, translation, indexing) as soon as the run finishes
- 📅 **Scheduled channel monitoring** — run weekly with `startDate` set to last week to continuously capture new transcripts from research channels

Learn more about [Apify integrations](https://docs.apify.com/platform/integrations).

### Using the Apify API

You can start YouTube Transcript Scraper programmatically using the [Apify API](https://docs.apify.com/api/v2).

**Node.js:**

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });

const run = await client.actor('automation-lab/youtube-transcript').call({
    urls: ['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],
    language: 'en',
    mergeSegments: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].fullText);
```

**Python:**

```python
from apify_client import ApifyClient

client = ApifyClient('YOUR_API_TOKEN')

run = client.actor('automation-lab/youtube-transcript').call(run_input={
    'urls': ['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],
    'language': 'en',
    'mergeSegments': True,
})

items = client.dataset(run['defaultDatasetId']).list_items().items
print(items[0]['fullText'])
```

**cURL:**

```bash
curl -X POST "https://api.apify.com/v2/acts/automation-lab~youtube-transcript/runs?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "urls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
    "language": "en",
    "mergeSegments": true
  }'
```

### Use with AI agents via MCP

[YouTube Transcript Scraper](https://apify.com/automation-lab/youtube-transcript) is available as a tool for AI assistants that support the [Model Context Protocol (MCP)](https://docs.apify.com/platform/integrations/mcp).

Add the Apify MCP server to your AI client — this gives you access to all Apify actors, including this one:

#### Setup for Claude Code

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/youtube-transcript"
```

#### Setup for Claude Desktop, Cursor, or VS Code

Add this to your MCP config file:

```json
{
    "mcpServers": {
        "apify": {
            "url": "https://mcp.apify.com?tools=automation-lab/youtube-transcript"
        }
    }
}
```

Your AI assistant will use OAuth to authenticate with your Apify account on first use.

#### Example prompts

Once connected, try asking your AI assistant:

- "Use automation-lab/youtube-transcript to get the full transcript of this video and summarize the key points: https://www.youtube.com/watch?v=dQw4w9WgXcQ"
- "Extract the English transcripts for all videos published this month on the @lexfridman channel and merge them into full text"
- "Get the transcript for this YouTube lecture and extract all timestamps where the speaker mentions machine learning"

Learn more in the [Apify MCP documentation](https://docs.apify.com/platform/integrations/mcp).

### Is it legal to scrape YouTube transcripts?

YouTube Transcript Scraper only accesses publicly available captions and metadata from YouTube videos. It does not bypass any login walls, age restrictions, or access controls. The data collected is the same as what any viewer can access by clicking the CC button on a public YouTube video.

Web scraping of publicly available data is generally considered legal — particularly for non-commercial research and content analysis purposes — but you should review [YouTube's Terms of Service](https://www.youtube.com/static?template=terms) and applicable laws in your jurisdiction. Use the data responsibly and in compliance with privacy regulations like GDPR and CCPA. Read more about the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

### FAQ

**Can I extract transcripts from private or age-restricted videos?**
No. This Actor only works with public YouTube videos. Private, unlisted, or age-restricted videos that require a login will return an error message with the video ID so you can identify which ones failed.

**What happens if a video doesn't have captions?**
The Actor returns the full video metadata with `segmentCount: 0` and an empty `segments` array. No error is thrown. You still get the title, description, view count, publish date, and other fields.

**Which languages are supported?**
All languages available on YouTube — over 100 languages including auto-generated captions. Set `language` to any ISO 639-1 code: `en`, `es`, `de`, `ja`, `ko`, `ar`, `hi`, `pt`, `fr`, `zh`, etc. If your preferred language isn't available, the Actor automatically falls back to the best available option and records it in `selectedLanguage`.

**How many videos can I process in one run?**
There is no hard limit. The Actor processes videos concurrently, so large batches benefit from parallelization. For very large datasets (10,000+ videos), consider splitting into multiple runs scheduled across time.

**What URL formats are supported?**
Full URLs (`youtube.com/watch?v=...`), short URLs (`youtu.be/...`), embed URLs (`youtube.com/embed/...`), Shorts URLs (`youtube.com/shorts/...`), channel URLs (`youtube.com/@handle`, `youtube.com/channel/UC...`, `youtube.com/c/Name`), bare `@handles`, and plain 11-character video IDs.

**Why are there more segments than the competitor's output?**
This Actor uses the ANDROID InnerTube API, which often returns more detailed caption segmentation than web-based extraction. More segments means more precise timestamps for applications that need accurate time references.

**The transcript is in the wrong language. How do I fix it?**
Set `language` to the desired ISO 639-1 code (e.g., `es` for Spanish, `ja` for Japanese). Check `availableLanguages` in the output to see all options for that video. If the target language has only auto-generated captions, make sure `includeAutoGenerated` is `true`.

**I'm getting `segmentCount: 0`. Why?**
Some videos genuinely have no captions — this is common with Shorts, music videos, and older uploads. Check if captions exist on YouTube by opening the video and clicking the CC button. If captions exist on YouTube but the Actor returns 0 segments, verify that `includeAutoGenerated` is `true`, since many videos only have auto-generated captions that are skipped when this option is off.

**How is this different from the YouTube Data API?**
The YouTube Data API v3 does not expose transcript text — it only lists available caption tracks. This Actor bypasses that limitation by using YouTube's internal InnerTube endpoint, which returns the actual caption text with timestamps. No API key or quota required.

### Other YouTube and video scrapers

- [YouTube Scraper](https://apify.com/automation-lab/youtube-scraper) — scrape YouTube videos, channels, playlists, and comments at scale
- [YouTube Shorts Scraper](https://apify.com/automation-lab/youtube-shorts-scraper) — extract Shorts data from any YouTube channel including views, likes, and engagement
- [YouTube Transcript Enhanced](https://apify.com/automation-lab/youtube-transcript-enhanced) — transcripts with SRT/VTT export, paragraph chunking, and keyword search
- [TikTok Scraper](https://apify.com/automation-lab/tiktok-scraper) — scrape TikTok videos, profiles, and hashtags
- [Instagram Scraper](https://apify.com/automation-lab/instagram-scraper) — extract Instagram posts, reels, profiles, and hashtags

# Actor input Schema

## `urls` (type: `array`):

Add YouTube video URLs, video IDs, or channel URLs. Supported formats: full video URLs (<code>youtube.com/watch?v=...</code>), short URLs (<code>youtu.be/...</code>), Shorts URLs, bare video IDs (11 characters), channel URLs (<code>youtube.com/@handle</code>), and bare <code>@handles</code>.

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

Set the preferred transcript language as an ISO 639-1 code (e.g. <code>en</code>, <code>es</code>, <code>de</code>, <code>ja</code>, <code>ko</code>, <code>fr</code>, <code>pt</code>). If the language is unavailable, the actor falls back to the best available option. Check <code>selectedLanguage</code> in the output to see which was used.

## `includeAutoGenerated` (type: `boolean`):

Enable to fall back to YouTube's auto-generated captions when manual captions are not available. Recommended: leave on — many videos only have auto-generated captions.

## `mergeSegments` (type: `boolean`):

Enable to add a <code>fullText</code> field containing all transcript segments merged into a single string. Useful for feeding directly into LLMs, summarizers, or translation APIs.

## `maxVideosPerChannel` (type: `integer`):

Set the maximum number of videos to process when a channel URL is provided. Videos are fetched newest first. Keep low (10–20) for testing before running the full channel.

## `startDate` (type: `string`):

Filter: only process videos published on or after this date. Format: <code>YYYY-MM-DD</code>. Works with both video URLs and channel URLs.

## `endDate` (type: `string`):

Filter: only process videos published on or before this date. Format: <code>YYYY-MM-DD</code>. Combine with <strong>Start date</strong> to extract a specific time window.

## Actor input object example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "language": "en",
  "includeAutoGenerated": true,
  "mergeSegments": false,
  "maxVideosPerChannel": 10
}
```

# Actor output Schema

## `overview` (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 = {
    "urls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ],
    "language": "en",
    "maxVideosPerChannel": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/youtube-transcript").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 = {
    "urls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
    "language": "en",
    "maxVideosPerChannel": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/youtube-transcript").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 '{
  "urls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "language": "en",
  "maxVideosPerChannel": 10
}' |
apify call automation-lab/youtube-transcript --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "YouTube Transcript Scraper",
        "description": "Extract timestamped transcripts & subtitles from any public YouTube video. Batch hundreds of URLs, 100+ languages with auto-fallback, no API key required. Returns full video metadata + segments. Export JSON, CSV, Excel.",
        "version": "0.1",
        "x-build-id": "gbMKItB6ZAcgmUV5k"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/automation-lab~youtube-transcript/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-automation-lab-youtube-transcript",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/automation-lab~youtube-transcript/runs": {
            "post": {
                "operationId": "runs-sync-automation-lab-youtube-transcript",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/automation-lab~youtube-transcript/run-sync": {
            "post": {
                "operationId": "run-sync-automation-lab-youtube-transcript",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "urls"
                ],
                "properties": {
                    "urls": {
                        "title": "🎬 Video or channel URLs",
                        "type": "array",
                        "description": "Add YouTube video URLs, video IDs, or channel URLs. Supported formats: full video URLs (<code>youtube.com/watch?v=...</code>), short URLs (<code>youtu.be/...</code>), Shorts URLs, bare video IDs (11 characters), channel URLs (<code>youtube.com/@handle</code>), and bare <code>@handles</code>.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "language": {
                        "title": "Preferred language",
                        "type": "string",
                        "description": "Set the preferred transcript language as an ISO 639-1 code (e.g. <code>en</code>, <code>es</code>, <code>de</code>, <code>ja</code>, <code>ko</code>, <code>fr</code>, <code>pt</code>). If the language is unavailable, the actor falls back to the best available option. Check <code>selectedLanguage</code> in the output to see which was used.",
                        "default": "en"
                    },
                    "includeAutoGenerated": {
                        "title": "Include auto-generated captions",
                        "type": "boolean",
                        "description": "Enable to fall back to YouTube's auto-generated captions when manual captions are not available. Recommended: leave on — many videos only have auto-generated captions.",
                        "default": true
                    },
                    "mergeSegments": {
                        "title": "Merge transcript into full text",
                        "type": "boolean",
                        "description": "Enable to add a <code>fullText</code> field containing all transcript segments merged into a single string. Useful for feeding directly into LLMs, summarizers, or translation APIs.",
                        "default": false
                    },
                    "maxVideosPerChannel": {
                        "title": "Max videos per channel",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Set the maximum number of videos to process when a channel URL is provided. Videos are fetched newest first. Keep low (10–20) for testing before running the full channel.",
                        "default": 50
                    },
                    "startDate": {
                        "title": "Start date (from)",
                        "type": "string",
                        "description": "Filter: only process videos published on or after this date. Format: <code>YYYY-MM-DD</code>. Works with both video URLs and channel URLs."
                    },
                    "endDate": {
                        "title": "End date (until)",
                        "type": "string",
                        "description": "Filter: only process videos published on or before this date. Format: <code>YYYY-MM-DD</code>. Combine with <strong>Start date</strong> to extract a specific time window."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
