# YouTube Transcript Scraper — Bulk & LLM-Ready (`fkdg_digital/youtube-transcript-bulk`) Actor

Extract YouTube transcripts in bulk from videos, playlists or entire channels. Output as JSON, text, SRT, VTT or LLM-ready chunks with timestamps.

- **URL**: https://apify.com/fkdg\_digital/youtube-transcript-bulk.md
- **Developed by:** [Franclim Diogo](https://apify.com/fkdg_digital) (community)
- **Categories:** AI, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.002 / run start

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 — Bulk & LLM-Ready

Extract **YouTube transcripts at scale** — a single video, a playlist, or an **entire channel** in one run — and get them back in the format your pipeline actually wants: JSON segments, plain text, SRT, VTT, or **LLM-ready chunks with timestamps**.

No API key. No YouTube login. Feed entire channels to your AI pipeline in one run.

### Why this Actor

Most transcript scrapers take one video URL at a time and hand you a wall of text. This one is built for the two things people actually do with transcripts in 2026:

1. **Bulk ingestion** — point it at `@channel` and pull the latest 10, 50 or 500 videos in a single run.
2. **Feeding LLMs** — the `chunked` output splits transcripts into token-sized blocks that **never cut a caption mid-sentence**, each carrying its own start/end timestamp. Drop them straight into a vector store and your citations still point at the right moment in the video.

Plus: it's **cheaper per transcript** than the popular alternatives, and you're only charged for transcripts actually extracted — failures are free.

### Input

| Field | Description |
|---|---|
| `videoUrls` | Individual videos: watch URLs, `youtu.be` links, Shorts, embeds, or raw 11-char IDs |
| `channelUrl` | A whole channel or playlist: `@handle`, `/channel/UC...`, `/user/...`, playlist URL |
| `videosPerChannel` | How many recent videos to pull (default 10, up to 500) |
| `languages` | Priority list, e.g. `["en", "pt"]`. Manual captions preferred, auto-generated as fallback |
| `outputFormat` | `chunked` · `json` · `text` · `srt` · `vtt` |
| `chunkTokens` | Target chunk size (default 500) |
| `chunkOverlapSegments` | Repeat N segments across chunk boundaries to preserve context |
| `requestDelaySeconds` | Pacing between videos (default 1s — YouTube rate-limits bursts) |
| `proxyConfiguration` | Optional Apify Proxy if you hit rate limits |

### Output

One row per video: `title`, `channel`, `channel_id`, `duration_seconds`, `upload_date`, `view_count`, `language`, `is_auto_generated`, `word_count`, `segment_count`, plus the transcript itself (`segments`, `transcript`, or `chunks` depending on format).

Chunked rows look like this:

```json
{
  "chunk_index": 0,
  "start": 12.34,
  "end": 78.9,
  "timestamp": "00:00:12",
  "estimated_tokens": 487,
  "text": "..."
}
```

Failed videos still appear as rows with `success: false` and an `error` — nothing is silently dropped.

### Use cases

- **RAG pipelines** — index whole channels for semantic search with timestamp-accurate citations
- **Content research** — analyse a competitor's or an expert's entire back catalogue
- **Subtitles** — bulk SRT/VTT export for editing or re-upload
- **Summarisation at scale** — feed chunked transcripts to any LLM without preprocessing

### Honest notes

- **Not every video has captions.** Videos with captions disabled return `success: false` with a clear reason — you aren't charged for them.
- **Auto-generated captions have errors.** Every row tells you via `is_auto_generated` whether the text was human-written or machine-transcribed. Don't treat ASR output as a verbatim quote.
- **Use a proxy for reliable runs.** YouTube blocks cloud datacenter IPs with "Sign in to confirm you're not a bot". Measured success on Apify: **100% with residential proxy**, ~50% with datacenter, ~25% with none. Residential is the default recommendation — and because failed attempts still burn compute, it also works out *cheaper per delivered transcript*.
- **YouTube rate-limits bursts.** Videos are fetched concurrently with staggered starts and exponential backoff on HTTP 429, and the Actor rotates through several YouTube player clients when one is blocked or returns no captions.
- **Token counts are estimates** (~4 characters per token). Close enough for chunk sizing; use your model's tokenizer if you need exact counts.
- Transcripts are YouTube's public caption data. Respect the copyright of the underlying content.

### Pricing

Pay-per-event: a tiny run fee plus a per-transcript fee **charged only on success**. Videos without captions cost you nothing.

# Actor input Schema

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

Individual videos to transcribe. Accepts watch URLs, youtu.be links, Shorts, embeds or raw 11-character IDs.

## `channelUrl` (type: `string`):

Transcribe a whole channel or playlist. Accepts @handle, /channel/UC..., /user/... or a playlist URL.

## `videosPerChannel` (type: `integer`):

How many of the most recent videos to pull from the channel/playlist.

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

Language codes in priority order (e.g. en, pt, es). Manual captions are preferred; auto-generated are used as fallback.

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

chunked = LLM-ready blocks with timestamps (best for RAG/AI pipelines). json = raw timed segments. text/srt/vtt = ready-to-use files.

## `chunkTokens` (type: `integer`):

Target size per chunk in the chunked format. Chunks never split a caption segment, so actual size varies slightly.

## `chunkOverlapSegments` (type: `integer`):

Repeat this many caption segments at the start of each chunk to preserve context across boundaries. 0 = no overlap.

## `requestDelaySeconds` (type: `integer`):

YouTube rate-limits rapid transcript requests (HTTP 429). Keep at 1s or higher for bulk runs.

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

STRONGLY RECOMMENDED. YouTube blocks datacenter IPs with a bot check — measured success is 100% with RESIDENTIAL proxy vs ~50% datacenter and ~25% without proxy.

## `concurrency` (type: `integer`):

How many videos to fetch in parallel. Higher = faster and cheaper per transcript, but more likely to hit YouTube rate limits without a proxy.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "videosPerChannel": 10,
  "languages": [
    "en"
  ],
  "outputFormat": "chunked",
  "chunkTokens": 500,
  "chunkOverlapSegments": 0,
  "requestDelaySeconds": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "concurrency": 5
}
```

# Actor output Schema

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

Video metadata plus transcript as JSON segments, plain text, SRT, VTT or LLM-ready chunks.

## `report` (type: `string`):

Videos requested, transcripts extracted, success rate, errors and parameters.

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "videoUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fkdg_digital/youtube-transcript-bulk").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"] }

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

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/OAtFaoyezg5oLwu1J/builds/NWJnu0eeCdby2NqUe/openapi.json
