# YouTube Transcript Scraper | Captions & Full Text | $0.8 / 1K (`hridayrungta/youtube-transcript-scraper`) Actor

Get YouTube video transcripts and captions with timestamps plus one joined full-text field. Paste video, channel or playlist URLs. Auto-caption fallback and language choice. No login, no browser. $0.0008 per transcript.

- **URL**: https://apify.com/hridayrungta/youtube-transcript-scraper.md
- **Developed by:** [Hriday Rungta](https://apify.com/hridayrungta) (community)
- **Categories:** Videos, AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 transcript scrapeds

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 & Full Text | $0.8 / 1K

Get the transcript of any YouTube video as timestamped segments **and** one joined full-text field, ready for LLMs, RAG, summaries, search and content repurposing. Paste video URLs, or a whole channel or playlist, and get one row per video. No login, no API key, no browser.

You are only charged for videos where a transcript is actually returned. Videos without captions, private or deleted videos are returned as a status row and are never charged.

### What data do you get from a YouTube transcript scraper?

For every video:

- **Full transcript text** in one field (`text`), plus an optional `segments` array with `start`, `duration` and `text` per caption line
- **Language** of the transcript, its name, and whether it is **auto-generated** or human-made
- **Video details**: title, channel name and id, length in seconds
- **Word count** and segment count
- Optionally **every caption language** the video offers (`availableLanguages`)
- A `status` per video: `ok`, `no-captions`, `language-not-available`, `unavailable` or `blocked`

### How to scrape YouTube transcripts (tutorial)

1. Add one or more **Video, channel or playlist URLs** (one per line). Watch links, `youtu.be` links, Shorts and live links, bare 11-character video ids, `@handle` channels and playlist links all work.
2. Pick your **Preferred languages** (default `en`). Human-made captions are tried first, then auto-generated ones.
3. Set **Max videos in total** so you always know your worst-case bill.
4. Click **Start**. Download the dataset as JSON, CSV, Excel or via API.

### Input

| Field | What it does |
|---|---|
| Video, channel or playlist URLs | Videos give their transcript. Channels and playlists are expanded to their latest videos. |
| Max videos per channel / playlist | How many of the latest videos to take from each channel or playlist (default 10). |
| Max videos in total | Hard cap on videos processed in the run (default 100). |
| Preferred languages | Language codes in order of preference, e.g. `en`, `es`, `pt-BR`. |
| Fall back to any available language | If no preferred language exists, return the original-language captions instead of nothing (default on). |
| Prefer human-made captions | Take uploaded captions over auto-generated ones when both exist (default on). |
| Include timestamped segments | Adds the `segments` array. Turn off for a lighter dataset. |
| Put timestamps inside the full text | Makes `text` one line per cue, like `[01:23] ...`. |
| List all available caption languages | Adds `availableLanguages` to each row. |
| Remove back-to-back duplicate lines | Drops a line identical to the one right before it. |

### Output example

```json
{
  "videoId": "jNQXAC9IVRw",
  "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
  "status": "ok",
  "title": "Me at the zoo",
  "channelId": "UC4QobU6STFB0P71PMvOGN5A",
  "channelTitle": "jawed",
  "lengthSeconds": 19,
  "language": "en",
  "languageName": "English",
  "isAutoGenerated": false,
  "matchedRequestedLanguage": true,
  "segmentCount": 6,
  "wordCount": 39,
  "text": "All right, so here we are, in front of the elephants the cool thing about these guys is that they have really... really really long trunks and that's cool (baaaaaaaaaaahhh!!) and that's pretty much all there is to say",
  "segments": [
    { "start": 1.2, "duration": 2.16, "text": "All right, so here we are, in front of the elephants" },
    { "start": 5.318, "duration": 2.656, "text": "the cool thing about these guys is that they have really..." }
  ],
  "scrapedAt": "2026-10-14T04:59:00.257Z"
}
```

A video with no captions comes back like this (not charged):

```json
{ "videoId": "jWdxXdp8sZI", "status": "no-captions", "message": "This video has no captions / transcript available.", "title": "...", "text": null }
```

### Pricing

Pay per event, no subscription:

- **$0.0015** once per run (start fee)
- **$0.0008 per transcript** returned, which is **$0.80 per 1,000 transcripts**

| Run | Cost |
|---|---|
| 1 video | $0.0023 |
| 100 videos | about $0.082 |
| 1,000 videos | about $0.80 |
| 10,000 videos | about $8.00 |

You are charged for the transcript only when a transcript is returned. Videos without captions, unavailable videos and videos YouTube would not serve are free. The platform's own usage (compute) is included in these prices for paying users.

### Use cases

- Feed transcripts into LLMs and RAG pipelines, chatbots and search indexes
- Summarize, quote or repurpose videos into blog posts, newsletters and social posts
- Research and monitor what a channel talks about, in text form
- Build datasets for NLP, topic and keyword analysis

### FAQ

**Does it work for auto-generated captions?** Yes. If a video only has auto-generated captions you get those, and `isAutoGenerated` is `true`.

**Does it transcribe audio with AI?** No. It returns the captions YouTube already has for the video, human-made or auto-generated. Videos with no captions at all return `no-captions` and are free.

**Can it translate transcripts?** No. YouTube's own caption translation could not be reached reliably over plain HTTP, so this Actor returns the languages a video natively has. Use "List all available caption languages" to see what a video offers.

**Can I scrape a whole channel or playlist?** Yes. Add the channel or playlist URL and set "Max videos per channel / playlist". The latest videos are taken in the order YouTube lists them.

**Does it work for long videos and live-stream replays?** Yes, long videos work (a 4-hour course returned about 2,900 segments in one row). Live streams that are still running have no final transcript.

**Why did a video come back as `blocked`?** YouTube sometimes refuses a request from a given IP. The Actor retries up to 20 times on fresh IPs. If it still fails, the video is not charged: run it again later.

**Known limits.** Private, deleted and age-restricted videos return `unavailable`. Some videos have captions turned off by the uploader. Channel and playlist expansion reads the first pages YouTube serves for that channel or playlist.

### Is it legal to scrape YouTube transcripts?

This Actor reads publicly available captions of public videos and uses no login. You are responsible for how you use the data: respect copyright and YouTube's Terms of Service, and do not republish transcripts of videos you have no rights to. Do not use it to collect personal data in ways that break privacy law such as GDPR.

### More scrapers from this developer

| Scraper | What it does |
|---|---|
| [YouTube Scraper](https://apify.com/hridayrungta/youtube-scraper) | Video details, channel videos, search results and comments |
| [YouTube Shorts Scraper](https://apify.com/hridayrungta/youtube-shorts-scraper) | Channel Shorts with views, likes and dates |
| [YouTube Comments Scraper](https://apify.com/hridayrungta/youtube-comments-scraper) | Top-level comments for any video |
| [YouTube Channel Scraper](https://apify.com/hridayrungta/youtube-channel-scraper) | Channel profile data and stats |
| [Reddit Scraper](https://apify.com/hridayrungta/reddit-scraper) | Posts and comments from Reddit |

# Actor input Schema

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

One per line. A video URL (youtube.com/watch?v=..., youtu.be/..., /shorts/..., /live/...) or a bare 11-character video id returns that video's transcript. A channel (@handle, channel URL or UC... id) or playlist URL is expanded to its latest videos (see "Max videos per channel / playlist").

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

How many of the latest videos to take from each channel or playlist URL you add. Ignored for single video URLs.

## `maxItems` (type: `integer`):

Hard cap on how many videos this run processes, across every URL, so you always know your worst-case bill. You are only charged for videos where a transcript is returned.

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

Language codes in order of preference, e.g. en, es, de, pt-BR. For each language the human-made captions are tried first, then YouTube's auto-generated ones. Default: en.

## `fallbackToAnyLanguage` (type: `boolean`):

If none of your preferred languages exists for a video, return the video's original-language captions instead of nothing. The row's "language" and "matchedRequestedLanguage" fields say what you got. Turn off to skip such videos (they are not charged).

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

When a language has both an uploaded (human) caption track and an auto-generated one, take the human one. Turn off to prefer auto-generated.

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

Adds a "segments" array (start, duration, text per caption line) to each row. Turn off to get only the joined "text" field and a lighter dataset.

## `timestampsInText` (type: `boolean`):

Makes the "text" field one line per caption cue, each prefixed like \[01:23]. Off (default) gives one continuous block of text, best for LLMs and search.

## `includeAvailableLanguages` (type: `boolean`):

Adds an "availableLanguages" array (code, name, isAutoGenerated) listing every caption track the video has.

## `dedupeRepeatedLines` (type: `boolean`):

Drops a caption line when it is exactly identical to the line right before it (common in auto-generated captions). Never edits real text.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ],
  "maxVideosPerSource": 10,
  "maxItems": 10,
  "languages": [
    "en"
  ],
  "fallbackToAnyLanguage": true,
  "preferManualCaptions": true,
  "includeSegments": true,
  "timestampsInText": false,
  "includeAvailableLanguages": false,
  "dedupeRepeatedLines": true
}
```

# Actor output Schema

## `results` (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 = {
    "videoUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/watch?v=jNQXAC9IVRw"
    ],
    "maxItems": 10,
    "languages": [
        "en"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("hridayrungta/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 = {
    "videoUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    ],
    "maxItems": 10,
    "languages": ["en"],
}

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

```

## MCP server setup

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