# YouTube Channel Transcripts - Full Channel Extractor (RAG) (`jamhimself/youtube-channel-transcripts`) Actor

Extracts the transcript of every video in a YouTube channel. Input: @handle, channel URL, or UC id + max videos. Output: one row per video — full text, timestamped RAG chunks with deep links, optional SRT/VTT. No API key. $0.0075/transcript.

- **URL**: https://apify.com/jamhimself/youtube-channel-transcripts.md
- **Developed by:** [Jaime Martinez](https://apify.com/jamhimself) (community)
- **Categories:** Videos, Agents, Social media
- **Stats:** 5 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$7.50 / 1,000 product transcripts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## YouTube Channel Transcripts — Full Channel Transcript Extractor

YouTube channel transcripts for developers and AI pipelines — a full channel transcript extractor: give it a **channel** and get **every video's transcript** back as RAG-ready chunks (or plain text, SRT, VTT) in a single run. No API key, no quotas, no chaining tools together. Point it at a channel, get a knowledge base out.

This does in one step what normally takes two: it **lists the whole channel**, then **fetches every caption track** through a hosted residential-proxy + uptime layer that handles YouTube's PoToken bot-check — the reason many scrapers and free libraries come back empty.

### ⚡ Quick start

Paste this into the Actor's **Input** (JSON view) and hit **Start**:

```json
{
  "channels": ["@mkbhd"],
  "maxVideosPerChannel": 10
}
```

Each result row looks like:

```json
{
  "channelTitle": "Marques Brownlee",
  "videoId": "e3q0T9lcMSU",
  "url": "https://www.youtube.com/watch?v=e3q0T9lcMSU",
  "title": "iPhone 16 Pro Review: The Fine Print!",
  "durationSeconds": 812,
  "language": "en",
  "text": "This is the iPhone 16 Pro, and after two weeks of using it as my main phone...",
  "chunks": [
    {
      "index": 0,
      "text": "This is the iPhone 16 Pro, and after two weeks of using it as my main phone...",
      "startSeconds": 0,
      "endSeconds": 91.4,
      "deepLink": "https://www.youtube.com/watch?v=e3q0T9lcMSU&t=0s"
    }
  ]
}
```

One row per video; switch the dataset to the **RAG chunks** view to see one row per chunk.

Or run it from the API:

```
POST https://api.apify.com/v2/acts/jamhimself~youtube-channel-transcripts/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN
```

### Why this exists

Building RAG over a creator's catalog means: enumerate every video in the channel, then pull each transcript, then chunk it for embeddings. That's a multi-step pipeline most people stitch together by hand. This actor is the whole pipeline — **channel in → chunked transcripts out** — so an AI agent or a LangChain/LlamaIndex job can ingest an entire channel with one call.

### What you get (per video)

- `channelTitle`, `videoId`, `url`, `title`, `publishedText`, `viewCount`, `durationSeconds`
- `text` — the full transcript as clean text
- `chunks` — RAG-ready overlapping chunks, each with `startSeconds`, `endSeconds`, and a clickable `deepLink` into the video at that timestamp
- Optional `segments` (timestamped), `srt`, `vtt`

### Input

| Field | Type | Description |
|---|---|---|
| `channels` | array | **Required.** @handles, channel URLs, or UC… ids. |
| `maxVideosPerChannel` | integer | Newest N videos per channel (default 50). |
| `languages` | array | Preferred caption languages (default `["en"]`). |
| `ragChunking` | boolean | Emit RAG chunks (default **true**). |
| `chunkMaxChars` / `chunkOverlapChars` | integer | Chunk sizing. |

### Use cases

- **RAG / LLM ingestion** — turn a creator's entire catalog into an embeddable knowledge base in one call
- **Agent workflows** — "summarize everything channel X has said about Y"
- **Research & monitoring** — full-text search across a channel's spoken content
- **Dataset building** — transcript corpora per channel

### What you'll pay

**$0.0075 per delivered transcript.** Listing the channel is free; videos with no captions or that fail are skipped and never billed. No subscription, no API key.

| Transcripts delivered | Cost |
|---|---|
| 1 video | $0.0075 |
| 100 videos | $0.75 |
| 1,000 videos | $7.50 |

A 10-video test run costs about $0.075 — under a dime to see the output shape before you ingest a whole channel.

### Use as an MCP tool / with AI agents

This actor is exposed as an MCP tool, so AI agents can call it directly — the agent passes the channel and gets transcripts back as structured data.

MCP endpoint (streamable HTTP):

```
https://mcp.apify.com/?tools=jamhimself/youtube-channel-transcripts
```

Example MCP client config:

```json
{
  "mcpServers": {
    "youtube-channel-transcripts": {
      "url": "https://mcp.apify.com/?tools=jamhimself/youtube-channel-transcripts"
    }
  }
}
```

Any MCP client — Claude, Cursor, or agent frameworks — can call this actor directly as a tool (authenticate with your Apify token).

### Why scrapers return empty transcripts (and why this one doesn't)

YouTube gates caption downloads behind a **PoToken** (proof-of-origin attestation) bot-check. Requests without a valid token — which is what most free transcript libraries and DIY scrapers send — get an empty caption response, not an error. That's why "worked last month" scrapers silently start returning nothing.

This actor mints a **per-video PoToken** and escalates from datacenter to **residential proxies** when YouTube pushes back, retrying each video across proxy tiers before giving up. It is actively maintained against YouTube's changes. Videos that still can't be fetched are listed in the `SKIPPED` record and are never billed.

### Related actors

- **[YouTube Transcript Scraper](https://apify.com/jamhimself/youtube-transcript-extractor)** — transcripts for specific video URLs
- **[YouTube Channel Videos Scraper](https://apify.com/jamhimself/youtube-channel-videos)** — just the video list (no transcripts)
- **[YouTube Comments Scraper](https://apify.com/jamhimself/youtube-comments-scraper)** — audience data

### FAQ

- **Do I need a YouTube API key?** No — no key, no OAuth, no quota.
- **Big channels?** Set `maxVideosPerChannel`; it pages through and transcribes the newest N.
- **No-caption videos?** Skipped for free; you only pay for transcripts actually delivered.
- **Legal?** It accesses publicly available data. You are responsible for complying with YouTube's Terms of Service and applicable law in your use of the output.

***

If this actor saved you time, an honest review helps others find it.

YouTube is a trademark of Google LLC. This actor is not affiliated with or endorsed by YouTube or Google. Built and maintained by Jamhimself LLC.

# Actor input Schema

## `channels` (type: `array`):

YouTube channels — @handles (e.g. @mkbhd), channel URLs, or UC… channel IDs. The actor lists every video and returns each one's transcript.

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

Max videos per channel — transcribe the newest N videos. Prefilled to 10 for a cheap first run; raise it (up to 2000) to cover the full channel.

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

Transcript language codes in order of preference (e.g. \["en", "es"]). Falls back to English, then the first available caption track.

## `preferManual` (type: `boolean`):

Manual captions first — prefer human-uploaded captions over auto-generated (ASR) when both exist.

## `ragChunking` (type: `boolean`):

RAG chunks — split each transcript into overlapping chunks with timestamps + deep links, ready for embedding pipelines (LangChain, LlamaIndex, vector DBs).

## `chunkMaxChars` (type: `integer`):

Chunk size — maximum characters per RAG chunk.

## `chunkOverlapChars` (type: `integer`):

Chunk overlap — approximate character overlap between consecutive chunks.

## `includePlainText` (type: `boolean`):

Plain-text transcript — include the full transcript as one clean text string per video.

## `includeSegments` (type: `boolean`):

Timestamped segments — include the raw {start, duration, text} segment array per video.

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

SRT subtitles — include a SubRip (.srt) subtitle string per video.

## `includeVtt` (type: `boolean`):

VTT subtitles — include a WebVTT (.vtt) subtitle string per video.

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

Concurrency — how many videos to transcribe in parallel (1-10).

## `proxyCountryCode` (type: `string`):

Optional two-letter country code for proxies.

## Actor input object example

```json
{
  "channels": [
    "@mkbhd"
  ],
  "maxVideosPerChannel": 10,
  "languages": [
    "en"
  ],
  "preferManual": true,
  "ragChunking": true,
  "chunkMaxChars": 1500,
  "chunkOverlapChars": 200,
  "includePlainText": true,
  "includeSegments": false,
  "includeSrt": false,
  "includeVtt": false,
  "concurrency": 5
}
```

# Actor output Schema

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

One row per video: transcript text, timestamped segments, and metadata.

## `ragChunks` (type: `string`):

One row per RAG chunk with start/end timestamps and a deep link (enable the ragChunking input).

## `subtitles` (type: `string`):

Ready-to-save SRT/VTT subtitle strings per video (enable the includeSrt / includeVtt inputs).

# 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 = {
    "channels": [
        "@mkbhd"
    ],
    "maxVideosPerChannel": 10,
    "languages": [
        "en"
    ],
    "preferManual": true,
    "ragChunking": true,
    "chunkMaxChars": 1500,
    "chunkOverlapChars": 200,
    "includePlainText": true,
    "concurrency": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("jamhimself/youtube-channel-transcripts").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 = {
    "channels": ["@mkbhd"],
    "maxVideosPerChannel": 10,
    "languages": ["en"],
    "preferManual": True,
    "ragChunking": True,
    "chunkMaxChars": 1500,
    "chunkOverlapChars": 200,
    "includePlainText": True,
    "concurrency": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("jamhimself/youtube-channel-transcripts").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 '{
  "channels": [
    "@mkbhd"
  ],
  "maxVideosPerChannel": 10,
  "languages": [
    "en"
  ],
  "preferManual": true,
  "ragChunking": true,
  "chunkMaxChars": 1500,
  "chunkOverlapChars": 200,
  "includePlainText": true,
  "concurrency": 5
}' |
apify call jamhimself/youtube-channel-transcripts --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/36g8dzPHRTHwAYmmi/builds/aneq2yaU8Li9KbKSW/openapi.json
