# YouTube Transcript Scraper: Captions, Subtitles & Text (`northloop-labs/youtube-transcript-scraper`) Actor

Get YouTube transcripts from videos, Shorts, channels, playlists and searches: full text, timestamped segments, SRT/VTT, title, channel, duration and publish date. Videos without captions are transcribed by Whisper. Failed videos are free.

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

## Pricing

from $5.00 / 1,000 transcript from captions

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 with Whisper Fallback

Get the transcript of any public YouTube video, Short, channel, playlist or search. Paste links or keywords and get back for every video:

- the **full transcript** text
- **timestamped segments** (start and end in seconds), plus optional **SRT** and **WebVTT** subtitles
- the **source** of each transcript: YouTube **captions** (human-made or auto-generated) or **Whisper**
- **video metadata**: title, channel name, ID and URL, duration, publish date, views, likes, thumbnail and description

**No captions? No problem.** Most transcript scrapers return nothing when a video has no captions. This one downloads the audio and transcribes it with OpenAI's open-source **Whisper** model (via faster-whisper), running **inside the Actor**. No API key and no other account needed.

### What you can use it for

- **AI and RAG pipelines:** feed clean transcripts with metadata into ChatGPT, Claude, a vector database or your own LLM app.
- **Content research:** read what a whole channel or a search's top videos actually say, without watching hours of video.
- **Summaries, notes and clips:** jump to the exact second something was said using the segments or SRT.
- **Repurposing:** turn videos into blog posts, newsletters, show notes or social posts.
- **SEO and accessibility:** publish text versions and subtitles of your own videos.
- **Market and competitor monitoring:** schedule a daily run on competitor channels and get only the newest videos as text.

### How to scrape YouTube transcripts

1. Paste video, Shorts, channel or playlist links (or plain video IDs) into **YouTube URLs**, and/or keywords into **Search terms**.
2. Set **Max videos per source** for channels, playlists and searches.
3. Optionally pick a **Transcript language** (empty = the video's own language) and the **Transcript source**.
4. Click **Start**. Each video becomes one row in the dataset; download it as JSON, CSV, Excel or HTML.

### Input

| Field | What it does |
|---|---|
| `urls` | Video, Shorts, `youtu.be`, channel (`@handle`, `/channel/…`) or playlist URLs, or 11-character video IDs. Channels give their newest uploads; add `/shorts` or `/streams` to a channel URL for those tabs. |
| `searchTerms` | Keywords searched on YouTube. The top results are transcribed. |
| `maxVideos` | Max videos per channel, playlist or search term (default 10). |
| `searchSort` | `relevance` (default) or `date` (newest uploads first). |
| `language` | Caption language code such as `en`, `es`, `de`, `pt-BR`. Empty = the video's original language. |
| `transcriptSource` | `captions-then-whisper` (default), `captions-only` (cheapest, never uses Whisper) or `whisper-only` (always transcribe the audio). |
| `preferManualCaptions` | Use uploader-made captions before auto-generated ones (default on). |
| `maxWhisperMinutesPerVideo` | Longer videos are skipped for free instead of sent to Whisper (default 60). |
| `maxTotalWhisperMinutes` | Cap on Whisper minutes per run (default no cap; the run's maximum cost always applies). |
| `whisperLanguage` | Optional spoken-language hint for Whisper. Empty = auto-detect. |
| `includeSegments`, `includeSrt`, `includeVtt` | Output formats (segments on by default). |

#### Input example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=8jPQjjsBbIc",
    "https://www.youtube.com/@TED",
    "https://www.youtube.com/playlist?list=PLFDE868BCF58A3950"
  ],
  "searchTerms": ["how to make sourdough bread"],
  "maxVideos": 5,
  "language": "en",
  "transcriptSource": "captions-then-whisper",
  "includeSrt": true
}
```

#### Output example

```json
{
  "status": "ok",
  "source": "captions",
  "captionType": "manual",
  "language": "en",
  "translated": false,
  "videoId": "8jPQjjsBbIc",
  "url": "https://www.youtube.com/watch?v=8jPQjjsBbIc",
  "title": "How to stay calm when you know you'll be stressed | Daniel Levitin | TED",
  "channelName": "TED",
  "channelId": "UCAuUUnT6oDeKwE6v1NGQxug",
  "channelUrl": "https://www.youtube.com/channel/UCAuUUnT6oDeKwE6v1NGQxug",
  "durationSeconds": 740,
  "publishedAt": "2015-11-23",
  "publishedTimestamp": null,
  "viewCount": 20164750,
  "likeCount": 269629,
  "thumbnailUrl": "https://i.ytimg.com/vi/8jPQjjsBbIc/sddefault.jpg",
  "description": "Visit http://TED.com to get our entire library of TED Talks, transcripts, transl...",
  "text": "A few years ago, I broke into my own house. I had just driven home, it was around midnight...",
  "wordCount": 2232,
  "segments": [
    { "start": 13.24, "end": 15.8, "text": "A few years ago, I broke into my own house." },
    { "start": 16.88, "end": 18.1, "text": "I had just driven home," }
  ],
  "input": "https://www.youtube.com/watch?v=8jPQjjsBbIc",
  "error": null,
  "billedEvent": "transcript",
  "billedCount": 1,
  "scrapedAt": "2026-10-20T01:00:21Z"
}
```

Rows transcribed by Whisper have `"source": "whisper"`, `captionType: null`, plus `whisperModel`, `whisperLanguageProbability` and `transcribedSeconds`. Rows that were not transcribed keep the metadata and explain why in `status` and `error` (`no-captions`, `skipped-too-long`, `skipped-budget`, `skipped-live`, `no-speech`, `error`). A `note` field explains language fallbacks. A run summary is saved as `RUN_SUMMARY` in the key-value store.

### How much does it cost?

Pay per event, no platform usage costs on top:

- **$0.005 per transcript from captions** ($5 per 1,000 videos)
- **$0.015 per Whisper audio minute**, only for videos without captions (or in Whisper-only mode), counted per started minute
- **$0.0025** per run start (one event per GB of memory; the default 2 GB = $0.005)

Examples: 100 videos with captions cost $0.505. A 10-minute video without captions costs $0.15. Use `captions-only` to never pay for Whisper.

**You only pay for transcripts you get.** Videos that are private, removed, members-only, live or upcoming, have no captions (with Whisper off), fail, contain no speech or are skipped by your caps are **never charged**. Charging happens only after a transcript is ready, and the run stops cleanly at the "Maximum cost per run" you set in Apify.

### Captions, translations and Whisper

- **Captions first.** Uploader-made captions are used when they exist, otherwise YouTube's auto-generated captions in the spoken language. On auto-dubbed videos the Actor picks the original-language track, not a dub.
- **Language choice.** If you ask for a language the video has no captions in, the Actor tries YouTube's auto-translation. YouTube often refuses translations to automated clients; then you get the original-language captions with a `note` saying so.
- **Whisper fallback.** Used only when a video has no captions at all, which is most common for music, very new uploads and some Shorts. Whisper **base** runs on CPU: at the default 2 GB it transcribes about 3–4 minutes of audio per minute of run time. Accuracy is good for clear speech in major languages and weaker on music, heavy accents and noise. Whisper writes the spoken language and does not translate. It doesn't label speakers.
- **Best effort.** Whisper needs the video's audio, which YouTube sometimes blocks for automated downloads. The Actor retries on fresh connections; if the audio still can't be downloaded, the row is an `error` and is free.

### Use with AI agents, MCP, Make, Zapier, n8n and the API

#### AI agents and the Apify MCP server

Your AI agent can run this Actor as a tool through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp). In Claude, Cursor, VS Code or any other MCP client, add this server URL to load only this Actor:

```text
https://mcp.apify.com?tools=northloop-labs/youtube-transcript-scraper
```

You sign in to Apify on first connection. Agents that use the default server can also find the Actor with `search-actors` and run it with `call-actor`. Pass `maxTotalChargeUsd` in `callOptions` to cap what one run may cost. The Actor uses pay-per-event pricing, so it also works with Apify's agentic payments.

Example prompt: *"Get the transcripts of the last 5 videos on @mkbhd and summarize what each one says."* MCP calls wait at most 45 seconds; captions-only runs usually finish within that. For Whisper runs the agent gets the run ID first and reads the transcripts with `get-dataset-items` once the run finishes.

#### Make, Zapier and n8n

Apify has official integrations for [Make](https://docs.apify.com/platform/integrations/make), [Zapier](https://docs.apify.com/platform/integrations/zapier) and [n8n](https://docs.apify.com/platform/integrations/n8n). Use "Run Actor", pick `northloop-labs/youtube-transcript-scraper`, paste your input as JSON, and send the dataset items on to Google Sheets, Notion, Slack, a CRM or your LLM step. Inside Apify you can also connect Google Sheets or Slack, or add a [webhook](https://docs.apify.com/platform/integrations/webhooks) that fires when a run finishes.

#### API

Captions-only runs are fast enough for the synchronous endpoint, which returns the dataset items directly:

```bash
curl -X POST "https://api.apify.com/v2/acts/northloop-labs~youtube-transcript-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://www.youtube.com/watch?v=8jPQjjsBbIc"], "transcriptSource": "captions-only"}'
```

Or with the Python client (`pip install apify-client`). The JavaScript client works the same way:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("northloop-labs/youtube-transcript-scraper").call(run_input={"urls": ["https://www.youtube.com/@TED"], "maxVideos": 5})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["source"], item["title"], item["wordCount"])
```

### Data & privacy

- The Actor reads only public YouTube pages, captions and audio for the videos you ask for. It never logs in, uses no cookies of yours and can't access private, unlisted-without-link or members-only content.
- Whisper runs **inside the Actor**. Audio is not sent to any third-party service, and the downloaded file is deleted as soon as it's decoded.
- Results are written **only to your run's default dataset** and key-value store in your Apify account. We keep no copy.
- Transcripts contain whatever was said in the video, which can include personal details. Follow the privacy rules that apply to you (for example, GDPR) when you store or publish them.

### Your rights to the content

Videos and their captions are usually protected by copyright. **You are responsible for having the rights or a legal basis to use the transcripts** (for example, your own videos, research, accessibility, quotation or fair use in your country), and for respecting YouTube's terms. Check before you republish a transcript. This is not legal advice.

### FAQ

#### How much does a YouTube transcript cost?

$0.005 per video with captions, plus a $0.005 start fee per run at the default memory. Videos without captions cost $0.015 per audio minute through Whisper. Failed and skipped videos are free.

#### What happens when a video has no captions?

With the default `captions-then-whisper`, the Actor downloads the audio and transcribes it with Whisper, and the row says `"source": "whisper"`. With `captions-only` the row is `no-captions` and free.

#### Can I get transcripts of a whole channel or playlist?

Yes. Paste the channel or playlist URL and set **Max videos per source**. Channels are read newest first.

#### Can I get transcripts in another language?

Set **Transcript language**. Existing captions in that language are used first. Otherwise the Actor tries YouTube's translation and falls back to the original language with a `note`.

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

Shorts, yes. Live and upcoming streams have no transcript yet and are skipped for free; ended streams work once YouTube has processed them.

#### Is the transcript timestamped?

Yes. `segments` holds start and end times in seconds; turn on SRT or WebVTT for subtitle files.

#### Why did I get the original language instead of my translation?

YouTube often blocks automatic translation for automated clients. The row's `note` field tells you when that happened.

#### Can I monitor a channel for new videos?

Schedule the Actor in Apify (for example, daily) with the channel URL and a small `maxVideos`, and send new rows to Sheets, Slack or a webhook.

### How this Actor was made

This Actor was made with AI. An AI agent wrote and tested the code, this README and the store listing, and a human owns and maintains the Actor.

### More Actors from Northloop Labs

- [Podcast Transcriber for RSS & Apple Podcasts](https://apify.com/northloop-labs/podcast-transcriber): Whisper transcripts of podcast episodes from RSS feeds and Apple Podcasts.
- [Google Trends Scraper: Keywords, Regions & Related Queries](https://apify.com/northloop-labs/google-trends-scraper): bulk Google Trends with comparisons and rising-query alerts.
- [Google Ads Transparency Center Scraper](https://apify.com/northloop-labs/google-ads-transparency-library): a company's ads from the Google Ads Transparency Center.
- [Luma, Eventbrite & Meetup Events Scraper](https://apify.com/northloop-labs/tech-events-finder): tech, AI and startup events from Luma, Eventbrite and Meetup.
- [Greenhouse, Lever, Ashby & Workable Jobs Scraper](https://apify.com/northloop-labs/company-jobs-finder): open jobs from company career pages.
- [EU TED & UK Find a Tender Scraper](https://apify.com/northloop-labs/public-tenders-monitor): UK and EU public tenders with daily alerts.

### Feedback

Need speaker labels, a larger Whisper model, comments or another feature? Open an issue in the **Issues** tab. We read every one.

# Actor input Schema

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

Video, Shorts, channel (@handle, /channel/…) or playlist URLs, or plain 11-character video IDs. Channels list their newest videos first (add /shorts or /streams to the channel URL for those tabs).

## `searchTerms` (type: `array`):

Keywords to search on YouTube. The top results (up to Max videos per source) are transcribed.

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

Maximum videos taken from each channel, playlist or search term. Single video URLs always count as one.

## `searchSort` (type: `string`):

Order of search results: relevance (YouTube's default) or newest uploads first.

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

Language code for the captions, e.g. en, es, de, pt-BR. Leave empty for the video's original language. If that language has no captions, YouTube's auto-translation is tried, then the original language is returned (see the note field).

## `transcriptSource` (type: `string`):

captions-then-whisper: use YouTube captions and transcribe the audio with Whisper only when a video has no captions. captions-only: never use Whisper (cheapest). whisper-only: always transcribe the audio, even when captions exist.

## `preferManualCaptions` (type: `boolean`):

Use uploader-made captions before YouTube's auto-generated ones when both exist.

## `maxWhisperMinutesPerVideo` (type: `integer`):

Videos longer than this are skipped (free row) instead of transcribed with Whisper. 0 = no limit.

## `maxTotalWhisperMinutes` (type: `integer`):

Stop using Whisper after this many audio minutes in one run. 0 = no limit (the run's maximum cost still applies).

## `whisperLanguage` (type: `string`):

Optional language code of the speech for Whisper (e.g. en, es). Leave empty to auto-detect. Whisper writes the spoken language; it does not translate.

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

Add a segments array: \[{start, end, text}] in seconds.

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

Add the transcript as an SRT subtitle string.

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

Add the transcript as a WebVTT subtitle string.

## Actor input object example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=8jPQjjsBbIc",
    "https://www.youtube.com/@TED",
    "https://www.youtube.com/playlist?list=PLFDE868BCF58A3950"
  ],
  "searchTerms": [
    "how to make sourdough bread"
  ],
  "maxVideos": 10,
  "searchSort": "relevance",
  "language": "",
  "transcriptSource": "captions-then-whisper",
  "preferManualCaptions": true,
  "maxWhisperMinutesPerVideo": 60,
  "maxTotalWhisperMinutes": 0,
  "whisperLanguage": "",
  "includeSegments": true,
  "includeSrt": false,
  "includeVtt": false
}
```

# Actor output Schema

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

No description

## `runSummary` (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 = {
    "urls": [
        "https://www.youtube.com/watch?v=8jPQjjsBbIc",
        "https://www.youtube.com/watch?v=jNQXAC9IVRw"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("northloop-labs/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 = { "urls": [
        "https://www.youtube.com/watch?v=8jPQjjsBbIc",
        "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    ] }

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,northloop-labs/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/FThPCaAzjpnsxGWc2/builds/abGmCqLFnpx5ezOzQ/openapi.json
