# Best YouTube Transcripts Scraper (`data_minds/best-youtube-transcripts-scraper`) Actor

Get the transcript of any YouTube video, Short, playlist or channel with no login or API key. Timestamped captions, plain text, SRT, chapters, language choice, plus video and channel details. Bulk input, auto proxy fallback. Export JSON, CSV or Excel.

- **URL**: https://apify.com/data_minds/best-youtube-transcripts-scraper.md
- **Developed by:** [Data Minds](https://apify.com/data_minds) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.50 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Transcripts Scraper — captions, SRT, chapters and video details

YouTube Transcripts Scraper takes YouTube video, Shorts, playlist and channel links and returns one row per video with the **transcript in the language you choose**, timestamped segments, plain text, an optional SRT subtitle file, chapters with their transcript text, and video and channel details. No YouTube account, cookies or API key are needed. Every response is structured JSON — ready to pass directly to an LLM, index into a vector store, or feed a RAG pipeline. Videos that have no transcript are never dropped: they get a row with a clear `status` and reason, so you always know what happened.

#### Why choose YouTube Transcripts Scraper?

- Paste a single link or thousands — bulk input of video, Shorts, youtu.be, playlist and channel links in one run.
- Channel links can end in `/videos`, `/shorts` or `/streams` to pick that tab.
- Pick the transcript language (or several in priority order). Creator captions win over auto-generated ones.
- Rows appear in the output table while the run is still going, one table per section.
- Starts without a proxy and moves to a stronger proxy only when YouTube rejects requests.

#### Key features

- **YouTube transcript scraper** for videos, Shorts, playlists and whole channels
- **Five captions formats**: caption lines, lines with start and end seconds, XML with or without timestamps, or one single text
- **Timed segments** with start and end in milliseconds and a readable start time
- **SRT subtitles** as ready-to-use text (optional)
- **Chapters** with the transcript text inside each chapter
- **Video details**: title, channel, views, likes, publish date, category, keywords, hashtags, description, thumbnail
- **Honest status per row**: `ok`, `no_transcript`, `live`, `upcoming`, `login_required`, `unavailable`, `rate_limited`, `error`

#### Input

Example input:

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://www.youtube.com/@Fireship/videos"
  ],
  "maxVideos": 50,
  "language": "auto",
  "outputFormat": "captions",
  "includeDetails": true,
  "includeSrt": false,
  "maxRetries": 3,
  "proxyConfiguration": { "useApifyProxy": false }
}
```

| Field | What it does |
|---|---|
| 📺 `urls` (required) | YouTube video, Shorts, youtu.be, playlist or channel links, or 11-character video ids. Bulk input is supported. |
| 📊 `maxVideos` | Maximum videos read per channel or playlist link (`0` = all). Direct video links are always read. |
| 🌍 `language` | `auto` for the original language, or a code such as `en`, or several in priority order such as `en, de`. If the language is missing, YouTube's own translation is tried; if that is refused you get the original track and a `warning`. |
| 🧾 `outputFormat` | Shape of the `captions` field: `captions`, `textWithTimestamps`, `xmlWithoutTimestamps`, `xmlWithTimestamps` or `singleStringText`. |
| ✨ `includeDetails` | Adds likes, publish date, category, Short / unlisted flags and chapters. One extra request per video. |
| 🎬 `includeSrt` | Adds `transcript_srt`, a subtitle file as text. |
| 🔁 `maxRetries` | Retries for a blocked or failed request (1–12, default 3). |
| 🌐 `proxyConfiguration` | Optional. Default is no proxy; on rejection the run moves to a datacenter proxy, then a residential proxy, and keeps using it. |

#### Output

Each video is saved the moment it is read. The main table holds the full row; the same data is also split into separate tables: transcripts, timed segments, video details, chapters and errors.

Example row (shortened, from a real run):

```json
{
  "id": "jNQXAC9IVRw",
  "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
  "title": "Me at the zoo",
  "channel_name": "jawed",
  "channel_id": "UC4QobU6STFB0P71PMvOGN5A",
  "duration_seconds": 19,
  "view_count": 445835540,
  "transcript_language": "en",
  "transcript_language_name": "English",
  "transcript_type": "manual",
  "word_count": 39,
  "transcript_only_text": "All right, so here we are, in front of the elephants\nthe cool thing about these guys is that they have really...",
  "transcript": [
    { "text": "All right, so here we are, in front of the elephants", "startMs": "1200", "endMs": "3360", "startTimeText": "0:01" }
  ],
  "captions": ["All right, so here we are, in front of the elephants"],
  "status": "ok",
  "error": null,
  "source_url": "https://youtu.be/jNQXAC9IVRw"
}
```

| Field | Notes |
|---|---|
| `id`, `url`, `title`, `channel_name`, `channel_id`, `channel_url` | Video and channel identity |
| `duration_seconds`, `view_count` | Always present when the video can be read |
| `like_count`, `published_at`, `category`, `is_short`, `is_unlisted`, `chapters` | With `includeDetails` |
| `is_livestream`, `keywords`, `hashtags`, `description`, `thumbnail_url` | Video content |
| `transcript_language`, `transcript_language_name`, `transcript_type` | Which transcript you got: `manual`, `auto` or `translated` |
| `available_languages` | Every caption language YouTube offers for the video |
| `word_count`, `transcript_only_text`, `transcript` | Word count, plain text, and timed segments |
| `captions` | The transcript in the `outputFormat` you picked |
| `transcript_srt` | With `includeSrt` |
| `status`, `error`, `warning`, `source_url`, `scraped_at` | `source_url` is the input link that produced the row |

Age-restricted videos return their details but YouTube hides their captions from logged-out visitors. Live streams have no transcript while live.

#### 🚀 How to use (Apify Console)

1. Log in at [console.apify.com](https://console.apify.com) and open **Actors**.
2. Find **Best YouTube Transcripts Scraper** and open it.
3. Paste your YouTube links, pick the language and format.
4. Click **Start**.
5. Watch the log: every saved video is reported as it finishes.
6. Open the **Output** tab when the run completes — separate tables for transcripts, segments, videos, chapters and errors.
7. Export to JSON, CSV or Excel.

#### 🤖 Use via API / MCP

Start a run with the Apify API by sending the same JSON as the example input above to the Actor's `runs` endpoint, with your token in the `Authorization: Bearer` header. AI agents can call this Actor through the Apify MCP server: `claude mcp add --transport http apify "https://mcp.apify.com"`, then use its search, details and call tools to find and run it.

#### Best use cases

- Feed video transcripts into an LLM, a vector store or a RAG pipeline
- Build a searchable text archive of a channel or playlist
- Create subtitles (SRT) for accessibility or translation work
- Research topics, quotes and mentions across many videos
- Summarise long videos by chapter

#### Frequently asked questions

**Does it need a YouTube account or API key?** No. It reads public data that any visitor can see.

**What if a video has no captions?** The video still gets a row with `status: no_transcript` and the reason, and it appears in the errors table.

**Can I get a transcript in another language?** Yes. Set `language`. Existing creator or auto captions in that language are used first; otherwise YouTube's translation is tried. If it is refused, the original language is returned and `warning` explains it.

**Why did some rows come back `rate_limited`?** YouTube rejected the connection. The run already retries and moves to stronger proxies on its own; if it still fails, try again later or start with a residential proxy.

**Can I scrape a whole channel?** Yes. Paste the channel link and set `maxVideos` (`0` = all uploads).

**Does it work on Shorts and playlists?** Yes, both are accepted.

**What if YouTube changes?** The scraper refreshes what it depends on at the start of every run, so small changes on YouTube's side do not break it.

#### Support and feedback

Found a bug or need another field? Open an issue from the Actor's **Issues** tab in Apify Console.

#### Legal

Only publicly available data is collected. You are responsible for using it in line with YouTube's terms, copyright and privacy laws such as GDPR.

# Actor input Schema

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

One or many YouTube video, Shorts or youtu.be links, playlist links or channel links (@handle, /channel/..., optionally ending in /videos, /shorts or /streams). Bulk input is supported. Free plan: up to 10 transcripts per run.

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

Stop listing after this many videos for each channel or playlist link (0 = all). Direct video links are always read. Free plan: up to 10 transcripts per run.

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

auto = the video's original language. Or a language code such as en, or several in priority order such as en, de. Creator captions win over auto-generated ones; if the language is missing YouTube's own translation is tried, otherwise the original is returned and the row says so.

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

Shape of the captions field. Timed segments, plain text and SRT are always available in their own fields.

## `includeDetails` (type: `boolean`):

Add likes, publish date, category, Short / unlisted flags and chapters with their transcript text. One extra request per video.

## `includeSrt` (type: `boolean`):

Add a ready-to-use SRT subtitle file as text for every video.

## `maxRetries` (type: `integer`):

How many times a blocked or failed request is retried before it is given up. Raise it if many videos fail.

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

Default is no proxy. If YouTube rejects the requests, the run switches to a datacenter proxy and then a residential proxy, and keeps using it for the rest of the run.

## Actor input object example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://www.youtube.com/@MrBeast"
  ],
  "maxVideos": 10,
  "language": "auto",
  "outputFormat": "captions",
  "includeDetails": true,
  "includeSrt": false,
  "maxRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Every video with its transcript and details.

## `transcripts` (type: `string`):

Transcript text, language and output format per video.

## `segments` (type: `string`):

One row per timed transcript segment.

## `videos` (type: `string`):

Channel, stats, keywords and description per video.

## `chapters` (type: `string`):

Chapters with the transcript text inside each one.

## `errors` (type: `string`):

Inputs and videos that did not produce a transcript.

## `summary` (type: `string`):

Counts for this run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/@MrBeast"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("data_minds/best-youtube-transcripts-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 = {
    "urls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/@MrBeast",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("data_minds/best-youtube-transcripts-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 '{
  "urls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://www.youtube.com/@MrBeast"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call data_minds/best-youtube-transcripts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,data_minds/best-youtube-transcripts-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/kfBeI4hUWd9quD274/builds/GVYkdQnLTln6g0HoU/openapi.json
