# YouTube Transcript Scraper: Captions, Subtitles & Timestamps (`vncntlabs/youtube-transcript-scraper`) Actor

Get YouTube transcripts as text plus timestamped segments from video links, keyword searches or a channel's latest videos. Caption language, title and channel on every row. Videos without captions are never charged. Pay per transcript.

- **URL**: https://apify.com/vncntlabs/youtube-transcript-scraper.md
- **Developed by:** [VNCNT Labs](https://apify.com/vncntlabs) (community)
- **Categories:** Videos, Social media, AI
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 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/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 Transcript Scraper: Captions, Subtitles & Timestamps

Get the transcript of any YouTube video as plain text plus timestamped segments. Paste video links or IDs, give a
search keyword, or give a channel (@handle or link) and get transcripts of its latest videos. Each video gets one row
with its caption language, title and channel. Videos without captions get a clear status row and are **never charged**.

### What you get

- **Full transcript text**, ready for summaries, AI prompts, SEO, research or subtitles work
- **Timestamped segments**: every caption line with `start`, `duration` and `end` in seconds
- Optional **\[mm:ss] transcript** text with a timestamp on every line
- Caption **language**, video **title**, **channel** name and link
- From keyword searches: search **rank**, views, video length and a Shorts flag
- A **status** on every row: `ok`, `no_captions`, `not_found`, `unavailable`, `error` or `invalid_input`

### Input

| Field | What it does |
| --- | --- |
| `videos` | YouTube links (watch, youtu.be, Shorts, embed, live) or 11-character video IDs |
| `keywords` | Search YouTube and transcribe the top results (up to 20 keywords) |
| `maxVideosPerKeyword` | Results per keyword (1-200, default 10) |
| `excludeShorts` | Skip Shorts in search and channel results |
| `channels` | YouTube channels: @handle, channel link or UC... ID (up to 10). Transcribes their latest videos |
| `maxVideosPerChannel` | Videos per channel (1-200, default 20) |
| `channelSort` | `newest` (default) or `relevance` |
| `language` | Caption track language code (e.g. `en`, `es`, `de`). Empty = the video's own language |
| `country` | Country for searches (name or 2-letter code) |
| `includeSegments` | Timestamped segments (default on) |
| `includeTimestampedText` | One text field with `[mm:ss]` before each line |
| `fastMode` | Priority queue for big batches with tight timeouts |
| `maxVideos` | Hard cap on videos per run (default 100, max 1,000) |

```json
{ "videos": ["https://www.youtube.com/watch?v=jNQXAC9IVRw", "dQw4w9WgXcQ"], "language": "en" }
```

```json
{ "keywords": ["how to make sourdough bread"], "maxVideosPerKeyword": 10, "excludeShorts": true }
```

```json
{ "channels": ["@veritasium"], "maxVideosPerChannel": 20, "excludeShorts": true }
```

### Output (one row per video)

```json
{
  "type": "transcript", "status": "ok", "videoId": "jNQXAC9IVRw",
  "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw", "title": "Me at the zoo",
  "channelName": "jawed", "channelUrl": "https://www.youtube.com/@jawed", "language": "en",
  "segmentsCount": 6, "transcriptDurationSeconds": 18.88, "wordCount": 39,
  "transcript": "All right, so here we are, in front of the elephants ...",
  "segments": [{ "start": 1.2, "duration": 2.16, "end": 3.36, "text": "All right, so here we are, in front of the elephants" }],
  "charged": true
}
```

A video without captions:

```json
{ "type": "transcript", "status": "no_captions", "videoId": "aqz-KE-bpKQ", "title": "Big Buck Bunny 60fps 4K - Official Blender Foundation Short Film",
  "error": "This video has no captions (creator or automatic).", "charged": false }
```

Keyword searches also add a `keyword` row (`videosFound`, `videosQueued`), and channels a `channel` row (`channelId`,
`videosFound`, `videosQueued`, `shortsSkipped`). Transcripts from a channel also carry `channelInput` and `publishedAt`. The run summary is in the `OUTPUT` record.

### Pricing

- **$0.005 per transcript delivered** (event `transcript`). No start fee.
- **Fast mode: $0.008 per transcript** (event `transcript-fast`), charged instead of the standard price, never both.
- **Not charged:** videos without captions, missing or private videos, provider errors, invalid inputs, keyword and channel rows.
- Set a maximum charge per run and the Actor stops there. Apify free plan: up to 10 transcripts per run.

### Use from AI agents (MCP)

AI assistants such as Claude, ChatGPT and Cursor can run this Actor through [Apify's MCP server](https://docs.apify.com/platform/integrations/mcp) (`https://mcp.apify.com`). The agent can look up the Actor, read its input schema, run it and read the results. Runs use your own Apify account and are charged at the prices on this page.

- **Actor name:** `vncntlabs/youtube-transcript-scraper`
- **Server URL with only this tool:** `https://mcp.apify.com?tools=vncntlabs/youtube-transcript-scraper`. The default `https://mcp.apify.com` also works.
- **Claude** (desktop app or claude.ai): Settings > Connectors > Add custom connector, paste the server URL, then sign in to Apify.
- **ChatGPT:** turn on Developer mode, then Settings > Apps & Connectors > Create, paste the server URL and choose OAuth.
- **Cursor:** add the server to `mcp.json`:

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

Example prompt: *"Use the Apify Actor vncntlabs/youtube-transcript-scraper to get the transcript of https://www.youtube.com/watch?v=dQw4w9WgXcQ and summarise it in five bullet points with timestamps."*

To cap the cost of an agent's run, it can pass `maxTotalChargeUsd` in the run options.

### FAQ

**Which captions?** Creator-uploaded captions or YouTube's automatic captions, as YouTube serves them.
**Can I pick the language?** Yes, with `language`. If the video has no track in that language you get a free `no_captions` row.
**How fast?** In our tests 90 videos took about 1.5 minutes and 3 videos about 15 seconds. Fast mode uses a priority queue for big batches with tight timeouts.
**Long videos?** Yes. We tested videos up to 13 hours (163,000 words) in one row.
**Does channel mode get every video a channel ever posted?** It gets the channel's videos that YouTube search lists,
newest first (tested: 116 of a big tech channel's videos in one search). Each channel gets a summary row with how many
videos were found; if that is fewer than you asked for, the row says so. `publishedAt` is approximate, because YouTube
shows dates like "3 weeks ago".

Public YouTube captions delivered through a licensed SERP data API. Transcript texts belong to their creators.
Not affiliated with or endorsed by YouTube or Google. Questions: hello@vncntlabs.com

# Actor input Schema

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

Watch, youtu.be, Shorts, embed or live links, or bare 11-character video IDs. One transcript row per video.

## `keywords` (type: `array`):

Get transcripts of the top YouTube search results for each keyword (up to 20 keywords).

## `maxVideosPerKeyword` (type: `integer`):

How many top search results to transcribe for each keyword.

## `excludeShorts` (type: `boolean`):

Leave YouTube Shorts out of keyword and channel results (they often have little speech).

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

YouTube channels as @handle, channel link (youtube.com/@name or /channel/UC...) or UC... channel ID (up to 10). Videos are found through YouTube search for the channel, newest first, so very large or very old back catalogs may not be complete. One row per channel shows how many videos were found.

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

How many of each channel's videos to transcribe.

## `channelSort` (type: `string`):

Which of the channel's videos to take first.

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

Language code of the caption track you want, e.g. en, es, de, pt. Leave empty for the video's own language. If the video has no captions in that language you get a no_captions row (not charged).

## `country` (type: `string`):

Country for keyword searches (and the YouTube region captions are read from). Name or 2-letter code, e.g. United States, GB, Germany.

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

Add every caption line with start, duration and end (seconds).

## `includeTimestampedText` (type: `boolean`):

Add one text field with a \[mm:ss] timestamp before every line, ready for notes or AI prompts.

## `fastMode` (type: `boolean`):

Use the provider's priority queue. Standard is usually done within 1-2 minutes per 100 videos; fast mode helps big batches with tight timeouts. Fast-mode transcripts are charged as 'Transcript (fast mode)' instead of 'Transcript'.

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

Hard cap on videos processed per run (links and search results together). You are only charged for transcripts delivered.

## Actor input object example

```json
{
  "videos": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    "https://youtu.be/dQw4w9WgXcQ"
  ],
  "keywords": [
    "how to make sourdough bread"
  ],
  "maxVideosPerKeyword": 10,
  "excludeShorts": false,
  "channels": [
    "@veritasium"
  ],
  "maxVideosPerChannel": 20,
  "channelSort": "newest",
  "country": "United States",
  "includeSegments": true,
  "includeTimestampedText": false,
  "fastMode": false,
  "maxVideos": 100
}
```

# Actor output Schema

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

No description

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

No description

## `summary` (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 = {
    "videos": [
        "https://www.youtube.com/watch?v=jNQXAC9IVRw",
        "https://youtu.be/dQw4w9WgXcQ"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("vncntlabs/youtube-transcript-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 = { "videos": [
        "https://www.youtube.com/watch?v=jNQXAC9IVRw",
        "https://youtu.be/dQw4w9WgXcQ",
    ] }

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vncntlabs/youtube-transcript-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/ygKMWbVcNXktcZv5g/builds/gzoiceJmVqSOqFcHB/openapi.json
