# YouTube Transcript Scraper: Chapters, Channels & Playlists (`farovin/youtube-transcripts`) Actor

Scrape YouTube transcripts and subtitles from videos, channels, playlists and searches, split into the video chapters for AI. Text, SRT, VTT, Markdown. $0.50 per 1,000, failed videos free.

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

## Pricing

from $0.50 / 1,000 transcript founds

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/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

### What you get

Each video comes back with its transcript **already split into the creator's chapters** (or 5-minute parts if it has none):

```json
{
  "title": "Phone Review: First Generation",
  "sections": [
    { "title": "Intro", "start": 0, "text": "So this is the first..." },
    { "title": "The Hardware", "start": 201, "text": "Let's start with the..." }
  ],
  "text": "So this is the first..."
}
```

### How to start

1. Paste a video, channel (`@name`) or playlist link, or a search term.
2. Click **Start**.
3. Download as JSON, CSV or Excel. Videos without captions are not charged.

***

### Full documentation (optional)

Everything below is reference material. You do not need it to get started.

#### Why use this YouTube transcript scraper?

| Feature | |
|---|---|
| Single videos, Shorts, live replays, any link format | ✅ |
| Whole channels (newest first) | ✅ |
| Playlists | ✅ |
| YouTube search queries | ✅ |
| **Transcript split by creator chapters** | ✅ rare |
| Equal time sections when a video has no chapters | ✅ |
| Choose transcript language, human captions first | ✅ |
| Auto-generated captions as fallback | ✅ |
| Text, `[mm:ss]` timestamps, segments, SRT, VTT, Markdown, in one run | ✅ |
| Only videos from the last N days, skip Shorts | ✅ |
| List available caption languages for free | ✅ |
| Video details: title, channel, duration, views, description, tags, thumbnail | ✅ |
| Failed videos free, pay only for transcripts | ✅ |
| About half the price of the most popular alternatives | ✅ |
| Scheduling, API, webhooks, Google Sheets, n8n, Make, Zapier, MCP | ✅ (Apify platform) |

#### Use cases

##### AI, RAG and chatbots

Feed transcripts into ChatGPT, Claude or your own LLM pipeline. The `sections` field gives you chapter-sized chunks with titles and timestamps, so retrieval and citations point to the right part of the video.

##### Content repurposing

Turn videos into blog posts, newsletters, show notes, social posts and course material. The Markdown format is ready to paste into Notion, Google Docs or a CMS.

##### Research and analysis

Collect transcripts from a channel, a playlist or a search to study topics, sentiment, claims or language across hundreds of videos.

##### SEO and competitor monitoring

See what your competitors say in their videos. Schedule a daily run on their channels with **Only videos from the last N days** to get only what is new.

##### Subtitles and accessibility

Download SRT or VTT files to edit, translate or re-upload subtitles.

##### Datasets and machine learning

Build text datasets with clean, timestamped segments and metadata.

#### What data can it extract?

| Field | Type | Description |
|---|---|---|
| `text` | string | Full transcript as one string |
| `sections` | array | Transcript split by chapter: `title`, `start`, `end`, `text`, `wordCount` |
| `sectionsType` | string | `creator-chapters`, `every-5-min` or `none` |
| `timestampedText` | string | Lines like `[01:23] text` |
| `segments` | array | Caption lines with `start` and `duration` in seconds |
| `srt`, `vtt` | string | Ready-to-use subtitle files |
| `markdown` | string | LLM-ready document with one heading per chapter |
| `language` | string | Language code of the returned transcript |
| `isAutoGenerated` | boolean | `true` for YouTube automatic captions |
| `availableLanguages` | array | All caption languages YouTube offers for the video |
| `title`, `channelName`, `channelId` | string | Video and channel |
| `durationSeconds`, `viewCount` | number | Length and views |
| `description`, `tags`, `thumbnailUrl` | string / array | Video details |
| `publishedText`, `isShort` | string / boolean | Upload age as shown in lists (e.g. "3 weeks ago"), Shorts flag |
| `source`, `sourceInput` | string | Where the video came from: video, channel, playlist or search |
| `wordCount`, `segmentCount` | number | Size of the transcript |
| `status`, `charged`, `errorCode`, `error` | | Result status and whether it was charged |

#### How to get YouTube transcripts

1. Open the Actor and go to the **Input** tab.
2. Add links in **Videos, channels or playlists**, or type **Search queries**.
3. For channels, playlists and searches, set **Max videos per channel, playlist or search**.
4. Pick **Output formats** and keep **Split transcript into chapters** on.
5. Click **Start**, then download the results as JSON, CSV, Excel or HTML.

#### Input examples

##### One video

```json
{ "videos": ["https://www.youtube.com/watch?v=abcdEFGh123"] }
```

##### Many videos at once

```json
{ "videos": ["https://youtu.be/abcdEFGh123", "https://www.youtube.com/shorts/xyzXYZ12345", "abcdEFGh124"] }
```

##### Pick a language

```json
{ "videos": ["https://www.youtube.com/watch?v=abcdEFGh123"], "languages": ["es", "en"] }
```

##### SRT, VTT and Markdown in the same run

```json
{ "videos": ["https://www.youtube.com/watch?v=abcdEFGh123"], "outputFormats": ["text", "srt", "vtt", "markdown"] }
```

##### Check which languages exist (free)

```json
{ "videos": ["https://www.youtube.com/watch?v=abcdEFGh123"], "languagesOnly": true }
```

##### Transcribe a whole channel

```json
{ "videos": ["https://www.youtube.com/@examplechannel"], "maxVideosPerSource": 200 }
```

##### Only new videos of a channel, without Shorts

```json
{ "videos": ["https://www.youtube.com/@examplechannel"], "publishedWithinDays": 7, "includeShorts": false }
```

##### A playlist

```json
{ "videos": ["https://www.youtube.com/playlist?list=PLxxxxxxxxxxxxxxxx"], "maxVideosPerSource": 100 }
```

##### Top videos for a search

```json
{ "searchQueries": ["how to bake sourdough bread"], "maxVideosPerSource": 25 }
```

##### Only creator chapters, no time sections

```json
{ "videos": ["https://www.youtube.com/watch?v=abcdEFGh123"], "chapters": "chapters-only" }
```

| Field | What it does |
|---|---|
| `videos` | Video links or IDs, channel links (`@handle`, `/channel/`, `/c/`) or playlist links. Watch, youtu.be, Shorts, embed and live links all work. |
| `searchQueries` | Transcripts of the top videos for each search. |
| `maxVideosPerSource` | Videos to take from each channel (newest first), playlist or search. Default 50. |
| `publishedWithinDays` | Only videos uploaded in the last N days (channels, playlists, searches). Approximate, based on the age YouTube shows in lists. |
| `includeShorts` | Turn off to skip Shorts. |
| `languagesOnly` | Only list available caption languages. Free. |
| `chapters` | `chapters-or-sections` (default), `chapters-only` or `off`. |
| `sectionMinutes` | Section length when a video has no chapters. Default 5. |
| `languages` | Preferred languages in order, e.g. `["es", "en"]`. If none is available, English is tried, then the first available transcript. |
| `includeAutoGenerated` | Use automatic captions when there are no human ones. On by default. |
| `outputFormats` | Any of `text`, `timestamped`, `segments`, `srt`, `vtt`, `markdown`. |
| `maxVideos` | Stop after this many videos in total. Caps the cost of any run. |
| `maxConcurrency` | Videos processed in parallel. Default 5. |

#### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel. One item per video:

```json
{
  "status": "ok",
  "charged": true,
  "videoId": "abcdEFGh123",
  "url": "https://www.youtube.com/watch?v=abcdEFGh123",
  "title": "Phone Review: First Generation",
  "channelName": "Example Channel",
  "durationSeconds": 742,
  "publishedText": "2 days ago",
  "language": "en",
  "isAutoGenerated": false,
  "availableLanguages": [{ "code": "en", "name": "English", "autoGenerated": false }],
  "wordCount": 2890,
  "sectionsType": "creator-chapters",
  "sections": [
    { "title": "Intro", "start": 0, "end": 73, "wordCount": 120, "text": "So this is the first..." },
    { "title": "The Hardware", "start": 201, "end": 455, "wordCount": 2107, "text": "Let's start with the..." }
  ],
  "text": "So this is the first...",
  "srt": "1\n00:00:01,200 --> 00:00:03,360\nSo this is the first...\n..."
}
```

##### A video without captions

```json
{ "status": "error", "charged": false, "videoId": "xyzXYZ12345", "errorCode": "NO_TRANSCRIPT", "error": "This video has no captions or transcript." }
```

##### Markdown output

```markdown
## Phone Review: First Generation

Channel: Example Channel | Video: https://www.youtube.com/watch?v=abcdEFGh123 | Language: en

### Intro (00:00)

So this is the first...

### The Hardware (03:21)

Let's start with the...
```

#### How to split a YouTube transcript into chapters

Many creators add chapters to their videos with timestamps in the description (`0:00 Intro`, `1:13 Setup`...). This Actor reads them using YouTube's own rules (first chapter at 0:00, at least three chapters, each at least 10 seconds long) and puts the matching transcript text under each chapter in `sections`.

When a video has no chapters, the transcript is split into equal sections of `sectionMinutes` minutes, so every video comes in chunks of a predictable size. Set `chapters` to `chapters-only` if you only want real creator chapters.

#### How to get transcripts of a whole YouTube channel

Paste the channel link (`https://www.youtube.com/@name`, `/channel/UC...` or `/c/name`) and set `maxVideosPerSource`. Videos are taken newest first. Add `publishedWithinDays` to get only recent uploads and `includeShorts: false` to skip Shorts. Schedule the run daily or weekly to keep a channel archive up to date.

#### How to build a searchable transcript dataset for RAG

1. Run the Actor on your channels, playlists or searches with `outputFormats: ["text"]` and chapters on.
2. Use each item in `sections` as one document: `title` + `text`, with the video `url` and `start` time as metadata.
3. Embed the sections in your vector database. Answers can then link to the exact moment in the video: `url + "&t=" + start`.

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

| What | Price |
|---|---|
| Transcript delivered | **$0.50 per 1,000** ($0.0005 each) |
| Run start | $0.05 per 1,000 runs ($0.00005 per run), covers server start-up |
| Video without a transcript, private, deleted, invalid link | **Free** |
| Listing a channel, playlist or search | **Free** |
| Listing available languages (`languagesOnly`) | **Free** |

| Run | Cost |
|---|---|
| 100 videos in one run | about $0.05 |
| 1,000 videos | about $0.50 |
| 10,000 videos | about $5.00 |

Apify's free $5 monthly credit covers about 10,000 transcripts a month. Set **Max videos** to cap the cost of any run.

#### Use with AI agents: Claude, ChatGPT, Cursor (MCP)

Every Apify Actor can be used by AI agents through the [Apify MCP server](https://mcp.apify.com).

1. Get your Apify API token in [Settings > API & Integrations](https://console.apify.com/settings/integrations).
2. Add the Apify MCP server to your client (Claude Desktop, Claude Code, Cursor, VS Code or ChatGPT) and enable the Actor `farovin/youtube-transcripts`.
3. Ask your agent, for example: *"Get the transcripts of the last 10 videos of @examplechannel split by chapters, and summarize each chapter in two sentences."*

#### Use in n8n, Make, Zapier and Google Sheets

Use the **Apify** node or app, choose **Run Actor**, select `farovin/youtube-transcripts` and pass the JSON input. Send `text`, `markdown` or `sections` to your LLM, Google Docs, Notion, Airtable or database. You can also export every run to Google Sheets, or trigger a webhook when a run finishes.

#### Use from code

##### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("farovin/youtube-transcripts").call(run_input={
    "videos": ["https://www.youtube.com/@examplechannel"],
    "maxVideosPerSource": 10,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], len(item.get("sections", [])))
```

##### JavaScript

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('farovin/youtube-transcripts').call({
    videos: ['https://www.youtube.com/watch?v=abcdEFGh123'],
    outputFormats: ['text', 'srt'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].text);
```

#### Tips

- **Lower cost per video**: put many videos in one run instead of one run per video (the start fee is paid once per run).
- **Spreadsheet-friendly**: choose only `text` for clean CSV and Excel exports; nested fields like `sections` are easier in JSON.
- **Faster runs**: raise `maxConcurrency` for large batches.
- **Monitoring**: schedule a daily run with `publishedWithinDays: 1` to get only new videos.

#### Limitations

- It returns captions that YouTube already has (human or automatic). It does not transcribe audio of videos without captions.
- Caption translation is not offered: YouTube currently rate-limits it, and we do not ship features we cannot run reliably.
- `publishedWithinDays` is approximate: it uses the upload age YouTube shows in lists ("3 weeks ago").
- Likes, comment counts and exact upload dates are not included, to keep the price low.
- Private, deleted, members-only, age-restricted and region-blocked videos cannot be read.

#### Troubleshooting

| Symptom | Likely cause | What to do |
|---|---|---|
| `NO_TRANSCRIPT` | The video has no captions, or only automatic ones and `includeAutoGenerated` is off | Check captions are visible on YouTube; turn on `includeAutoGenerated`. Not charged. |
| `UNAVAILABLE`, `PRIVATE`, `AGE_RESTRICTED` | The video is deleted, private or needs sign-in | Nothing to fix. Not charged. |
| `INVALID_INPUT` | The link is not a YouTube video, channel or playlist | Use a standard watch, youtu.be, Shorts, `@handle` or playlist link. Not charged. |
| Wrong language | The requested language is not available | Check `availableLanguages`, or run with `languagesOnly: true` first. |
| Channel or playlist returns few or no videos | Private playlist, no public videos, or filters too strict | Open the link while signed out; relax `publishedWithinDays` or `includeShorts`. |
| `BLOCKED` | YouTube refused the request after several retries | Run that video again. Not charged. If it repeats, open an issue. |

#### Responsible use

Use this Actor only for lawful purposes and for content you are allowed to process. Transcripts belong to their creators and may contain copyrighted material, personal data or errors from automatic captions. Keep attribution to the original video, verify important quotes, and comply with YouTube's terms and the laws that apply to you.

> Our Actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our Actors, when used for ethical purposes by Apify users, are safe. However, you should be aware that your results could contain personal data. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

#### FAQ

##### Do I need a YouTube API key?

No. The Actor works without any key, login or cookies.

##### Is there a free tier?

Yes. Apify gives every account $5 of free usage per month, which covers about 10,000 transcripts.

##### Can it split a transcript into chapters?

Yes, this is its main extra: creator chapters when the video has them, equal time sections otherwise.

##### Does it work with YouTube Shorts and live streams?

Yes for Shorts. Finished live streams work when YouTube has captions for them.

##### Can I choose the transcript language?

Yes, with `languages`. Human captions are preferred over automatic ones.

##### Can I get several formats in one run?

Yes. Pick any combination of text, timestamps, segments, SRT, VTT and Markdown.

##### Can it transcribe videos that have no captions?

No. It returns captions YouTube already has. Most videos have automatic captions.

##### Can it translate transcripts?

Not at the moment. YouTube currently rate-limits caption translation.

##### Am I charged for videos without a transcript?

No. You only pay for delivered transcripts. Every item shows `charged: true` or `false`.

##### How many videos can I process?

There is no fixed limit. Use `maxVideos` to cap a run, and `maxVideosPerSource` for channels, playlists and searches.

##### Can I run it on a schedule or via API?

Yes. Use Apify schedules, the API, webhooks, or n8n, Make and Zapier.

##### How do I report a problem?

Open an issue in the **Issues** tab with the video link. We read every issue and usually reply within a day.

##### Did it help you?

If this Actor saved you time, a short review on Apify Store helps other people find it. Thank you!

# Actor input Schema

## `videos` (type: `array`):

YouTube video links or IDs, channel links (@handle, /channel/, /c/) or playlist links. Channels and playlists are expanded into their videos.

## `searchQueries` (type: `array`):

Get transcripts of the top videos YouTube returns for each search, e.g. "how to bake bread".

## `maxVideosPerSource` (type: `integer`):

How many videos to take from each channel (newest first), playlist or search query.

## `publishedWithinDays` (type: `integer`):

For channels, playlists and searches: skip videos older than this. Uses the upload age YouTube shows in the list (e.g. "3 weeks ago"), so it is approximate. Skipped videos cost nothing.

## `includeShorts` (type: `boolean`):

Turn off to skip YouTube Shorts when reading channels, playlists and searches.

## `languagesOnly` (type: `boolean`):

Do not download transcripts; just list which caption languages each video has. Free.

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

Adds a "sections" list with title, start, end and the text of each part. Ready for AI summaries, search and RAG.

## `sectionMinutes` (type: `integer`):

Length of each time section when a video has no creator chapters.

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

Language codes in order of preference, e.g. 'en', 'es', 'el'. If none is available, English is tried, then the first available transcript.

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

Use YouTube's automatic captions when no human-made transcript exists. Most videos only have auto-generated captions.

## `outputFormats` (type: `array`):

text = full transcript as one string. timestamped = lines with \[mm:ss]. segments = list with start and duration. srt / vtt = subtitle files. markdown = LLM-ready document with one heading per chapter.

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

Stop after this many videos. Also caps the cost of a run.

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

How many videos to process at the same time.

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

Leave as is. Residential proxy is required because YouTube blocks cloud servers, and its cost is already included in the price.

## Actor input object example

```json
{
  "videos": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "maxVideosPerSource": 50,
  "includeShorts": true,
  "languagesOnly": false,
  "chapters": "chapters-or-sections",
  "sectionMinutes": 5,
  "languages": [
    "en"
  ],
  "includeAutoGenerated": true,
  "outputFormats": [
    "text",
    "segments"
  ],
  "maxVideos": 1000,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

All results of the run as JSON. Add ?format=csv or ?format=xlsx for other formats.

# 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 = {
    "videos": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ],
    "languages": [
        "en"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

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

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,farovin/youtube-transcripts"
        }
    }
}
```

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/3C6pNFPGeoODhg08j/builds/6vVr9G7mb6sLMZXZ8/openapi.json
