# YouTube Transcript Scraper & API: $1 per 1,000 Transcripts (`fit_melon/youtube-transcript-scraper`) Actor

Get YouTube transcripts, subtitles and captions with video info (title, channel, date, views, likes) from videos, channels, playlists or searches. Full text plus timestamped segments in the original language, ready for AI. $1 per 1,000 transcripts; no captions = free.

- **URL**: https://apify.com/fit_melon/youtube-transcript-scraper.md
- **Developed by:** [Melon Data](https://apify.com/fit_melon) (community)
- **Categories:** Videos, AI, Social media
- **Features:** Limited permissions
- **Stats:** 9 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

$1.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

### What is this YouTube Transcript Scraper?

**YouTube Transcript Scraper** that turns YouTube videos into clean text: the full **transcript (subtitles / captions)** of each
video, with **timestamped segments** and the video's public information (title, channel, publish date, views, likes, description).
Paste video links, or a **channel**, a **playlist** or a **search**, and get one result per video, ready for AI, search or analysis.
**$1 per 1,000 transcripts**, all included (proxies and platform usage). Videos without captions are free. No start fee.

It works like a YouTube transcript API, with no YouTube account and no API key. It uses plain HTTP requests (no browser, no video or
audio download): a channel of 500 videos took 3 to 5 minutes in our benchmark, and a single video takes 2 to 15 seconds (measured,
October 2026). The transcript comes in the video's **original language** by default; ask for another language when the video has it.

Use it for RAG and chatbots, video summaries, content repurposing (blog posts, newsletters), SEO and keyword research, media monitoring,
or to build datasets. Run it from Apify Console, through the API, on a schedule, or from Make, n8n and Zapier. Apify's free plan
($5 of monthly credit) covers up to 5,000 transcripts a month.

> 🇫🇷 **Transcription YouTube** : sous-titres et transcriptions de vidéos, chaînes, playlists ou recherches, avec horodatage. 1 $ les 1 000.
> 🇪🇸 **Transcripción de YouTube**: subtítulos y transcripciones de videos, canales, listas o búsquedas, con marcas de tiempo. 1 $ por 1.000.
> 🇩🇪 **YouTube-Transkript**: Untertitel und Transkripte von Videos, Kanälen, Playlists oder Suchen, mit Zeitstempeln. 1 $ pro 1.000.
> 🇧🇷 **Transcrição do YouTube**: legendas e transcrições de vídeos, canais, playlists ou buscas, com marcações de tempo. US$ 1 por 1.000.

### How to get YouTube transcripts (step by step)

1. Paste one or more YouTube links in **Video links** (watch links, youtu.be, Shorts, /live/ or bare video IDs). Or fill in
   **Channels**, **Playlists** or **Search terms**.
2. Optional: choose a **preferred language** (e.g. `en`), the **max videos** per channel, playlist or search, and extra formats
   (SRT, WebVTT, paragraphs).
3. Click **Start**. Results appear in the dataset as they arrive: download them as JSON, CSV, Excel or HTML, or read them through the API.

### What data do you get?

| Data | Fields |
|---|---|
| Full transcript as one clean string (no HTML, no tags) | `transcriptText` |
| Timestamped segments, in seconds | `segments`: `[{start, duration, text}]` (optional) |
| Transcript language and type | `transcriptLanguage`, `isAutoGenerated`, `originalLanguage`, `availableLanguages`, `languageFallback` |
| Video | `videoId`, `url`, `title`, `description`, `durationSeconds`, `viewCount`, `likeCount` (when public), `publishedAt` |
| Channel | `channelName`, `channelId`, `channelUrl` |
| Subtitle files (optional) | `srt`, `vtt`, readable `paragraphs` |
| Status | `status`: `found`, or `no_transcript` with a `reason` (no captions, live stream, private, age-restricted…), `scrapedAt` |

In our October 2026 benchmark, **every video that had captions was delivered**: 498 of the 500 latest videos of a large channel
(the other 2 had no captions), 192 of 200 search results, 40 of 40 long podcast episodes (up to several hours).

### Why this YouTube Transcript Scraper?

| | This actor |
|---|---|
| Price per 1,000 transcripts | **$1**, all included. Videos without captions are free. No start fee |
| Typical price of other YouTube transcript actors on the Store | $2 to $10 per 1,000, video details sometimes extra |
| Video information (title, channel, date, views, likes, description) | ✅ Included |
| Inputs | Video links, channels (`@handle` too), playlists, searches |
| Language | Original language by default (AI-dubbed audio tracks are ignored), or your preferred language |
| AI-ready output | Full text + timestamped segments, SRT, WebVTT, paragraphs |
| Speed (measured) | 100 to 150 videos per minute on a channel, 2 to 15 s for one video |
| Reliability | Automatic retries on other IPs, resume after a restart without double charge |

### Input

| Field | Type | Description |
|---|---|---|
| `videoUrls` | array | Video links or IDs. Channel and playlist links pasted here also work |
| `channelUrls` | array | Channel links (`/@handle`, `/channel/UC…`, `/c/…`, `/user/…`) or `@handles`. Newest videos first |
| `channelContent` | string | Which uploads of each channel: `all` (default), `videos` (long videos only, no Shorts) or `shorts` |
| `publishedAfter` | string | Channels and playlists only: keep the videos published on or after a day, e.g. `2026-11-01`, `7 days`, `2 weeks`, `3 months`. Older videos are left out and never charged |
| `playlistUrls` | array | Playlist links or IDs |
| `searchQueries` | array | Search terms: the first videos of each YouTube search (live streams are skipped) |
| `searchUploadDate` | string | Searches only: `any` (default), `hour`, `today`, `week`, `month` or `year` (videos uploaded in that period) |
| `searchSortBy` | string | Searches only: `relevance` (default) or `views` (most viewed first) |
| `maxVideos` | integer | Max videos per channel, playlist or search (default 50, `0` = all). Video links are always all processed |
| `language` | string | Preferred transcript language, e.g. `en`, `fr`, `pt-BR`. Empty = the video's original language |
| `translateTo` | string | YouTube's automatic translation, when YouTube allows it (see FAQ) |
| `transcriptType` | string | `any` (manual subtitles first, else auto-generated), `manual`, or `auto` |
| `includeTimestamps` | boolean | Add the timestamped `segments` (default on) |
| `outputFormats` | array | Extra formats: `paragraphs`, `srt`, `vtt` |
| `includeMetadata` | boolean | Add the publish date and like count (default on) |
| `searchCountry` | string | Country for search results, e.g. `US`, `FR`, `BR` |

#### Example inputs

Transcripts of a few videos:

```json
{
    "videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "https://youtu.be/jNQXAC9IVRw"]
}
```

The 100 latest videos of a channel, in English when available, with SRT subtitles:

```json
{
    "channelUrls": ["https://www.youtube.com/@TED"],
    "maxVideos": 100,
    "language": "en",
    "outputFormats": ["srt"]
}
```

The 50 latest long videos of a channel, without its Shorts:

```json
{
    "channelUrls": ["https://www.youtube.com/@kurzgesagt"],
    "channelContent": "videos",
    "maxVideos": 50
}
```

Only the new videos of a channel (schedule it every week with `7 days`: the channel listing stops at the first older video;
measured on @TED with `10 days`: one listing page, 7 transcripts in 21 s):

```json
{
    "channelUrls": ["https://www.youtube.com/@TED"],
    "channelContent": "videos",
    "publishedAfter": "7 days",
    "maxVideos": 0
}
```

The first 40 videos of two searches, without timestamps:

```json
{
    "searchQueries": ["how to cook rice", "machine learning tutorial"],
    "maxVideos": 40,
    "includeTimestamps": false
}
```

The new videos of the week about a topic (schedule it to monitor a subject every day with `today`):

```json
{
    "searchQueries": ["electric cars"],
    "searchUploadDate": "week",
    "maxVideos": 30
}
```

**Switching from another actor?** The input names of other popular YouTube transcript actors are also accepted (`youtube_url`,
`videoUrl`, `urls`, `startUrls`, `channel`, `channel_url`, `max_videos`, `maxResults`, `languages`, `translate_to`,
`transcript_type`, `dateFilter`, `sortingOrder`, `oldestPostDate`…). In Make, n8n or Zapier you can usually change only the actor ID.

### Output example

```json
{
    "status": "found",
    "videoId": "tu6tF-lVDJI",
    "url": "https://www.youtube.com/watch?v=tu6tF-lVDJI",
    "title": "Why You Should Share a Recipe with a Stranger | Anuj Gupta | TED",
    "channelName": "TED",
    "channelId": "UCAuUUnT6oDeKwE6v1NGQxug",
    "channelUrl": "https://www.youtube.com/channel/UCAuUUnT6oDeKwE6v1NGQxug",
    "publishedAt": "2026-10-27",
    "durationSeconds": 233,
    "viewCount": 33450,
    "likeCount": 161,
    "description": "Can we eat our way to a stronger democracy? Civic leader Anuj Gupta be…",
    "transcriptLanguage": "en",
    "isAutoGenerated": false,
    "isTranslated": false,
    "originalLanguage": "en",
    "availableLanguages": [
        { "languageCode": "ar", "name": "Arabic", "isAutoGenerated": false },
        { "languageCode": "en", "name": "English", "isAutoGenerated": false },
        { "languageCode": "es", "name": "Spanish", "isAutoGenerated": false }
    ],
    "transcriptText": "Can we eat our way to a stronger democracy? (Laughter) Normally, when we talk about strengthening democracy, we talk voting, town halls…",
    "segments": [
        { "start": 3.875, "duration": 3.379, "text": "Can we eat our way to a stronger democracy?" },
        { "start": 7.671, "duration": 1.626, "text": "(Laughter)" }
    ],
    "input": "https://www.youtube.com/watch?v=tu6tF-lVDJI",
    "scrapedAt": "2026-10-28T08:21:29.118Z"
}
```

A video without captions comes back with `"status": "no_transcript"`, a `reason` (`no_captions`, `live`, `unavailable`,
`private`, `age_restricted`, `content_warning`, `members_only`) and its video information. It is not charged.

### Use it from the API, Make, n8n or Zapier

Get the transcripts of a video in one call (replace `<YOUR_API_TOKEN>`):

```bash
curl -X POST "https://api.apify.com/v2/acts/fit_melon~youtube-transcript-scraper/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"]}'
```

In Make, n8n or Zapier, use the Apify "Run an Actor" module with the actor `fit_melon/youtube-transcript-scraper` and the same input.

### FAQ

**How much does it cost?** $1 per 1,000 transcripts delivered, everything included: proxies and platform usage are on us. Videos without
a transcript (no captions, live, private, age-restricted…) are free. Set a maximum cost per run in the run options and the actor stops
cleanly before reaching it.

**Which language do I get?** By default the video's original language: manual subtitles when they exist, else YouTube's auto-generated
captions. Videos with AI-dubbed audio tracks keep their original language (the dubbed captions are ignored). Set `language` to prefer
another language: you get it when the video has subtitles in that language, otherwise the original language with `languageFallback: true`.
`availableLanguages` lists every track of the video.

**Can it translate transcripts?** `translateTo` asks YouTube for its automatic translation. In October 2026 YouTube refuses most of these
requests: you then get the original transcript with `translationUnavailable: true`, at the normal price. If the video has subtitles written
in the requested language, those are used instead.

**Does it work for Shorts, live streams and long videos?** Shorts: yes, and `channelContent` takes only the Shorts or only the long
videos of a channel. Live streams and upcoming premieres have no transcript until they
end (they are skipped in searches, free otherwise). Long videos: yes, we tested episodes of several hours. Very long transcripts keep the
full text; if a single result would exceed Apify's 9 MB limit, the timed segments are left out first.

**Why do some videos have no transcript?** The uploader turned captions off, YouTube did not generate them (music, no speech, some
languages), or the video is private, members-only, age-restricted or behind a YouTube content warning. This actor never signs in and
never clicks through these checks: such videos come back as `no_transcript`, free of charge.

**Is it legal?** It only collects public data (transcripts and public video information) without logging in, and never downloads video
or audio. You are responsible for how you use the data, including copyright on the transcripts and YouTube's terms.

**Something does not work?** Open an issue in the Issues tab with your run link: we answer quickly.

### Also by this developer

[Google Maps Scraper](https://apify.com/fit_melon/google-maps-scraper-cheap): local business leads with phones, emails, websites and
social profiles. $0.50 per 1,000 places, all included.

# Actor input Schema

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

One per line: watch links, youtu.be links, Shorts, /live/ and /embed/ links, or 11-character video IDs. Channel and playlist links pasted here also work.

## `channelUrls` (type: `array`):

Channel links (/@handle, /channel/UC…, /c/…, /user/…) or @handles. The newest videos first, up to the maximum below (0 = all of them).

## `channelContent` (type: `string`):

Which uploads to take from each channel: all of them, long videos only (no Shorts), or Shorts only. Only applies to channels.

## `publishedAfter` (type: `string`):

Only keep the videos of channels and playlists published on or after this day: a date (2026-11-01) or a period (7 days, 2 weeks, 3 months, 1 year). Ideal for a daily or weekly schedule that collects only a channel's new videos. Older videos are left out and never charged. Leave empty for all videos.

## `playlistUrls` (type: `array`):

Playlist links (…/playlist?list=…) or playlist IDs.

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

One search per line: the first videos of each YouTube search (live streams are skipped).

## `searchUploadDate` (type: `string`):

Only keep search results uploaded in this period, e.g. to collect the new videos about a topic every day. Only applies to searches.

## `searchSortBy` (type: `string`):

Order of the search results: YouTube's relevance, or the most viewed videos first. Only applies to searches.

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

Limit for each channel, playlist and search (video links are always all processed). 0 = no limit.

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

Language code, e.g. en, fr, es, de, pt-BR. Manual subtitles are preferred over auto-generated ones. When the video has no transcript in this language, its original language is returned. Empty = the video's original language.

## `translateTo` (type: `string`):

Language code for YouTube's own automatic translation, e.g. en. YouTube often refuses translations: the original transcript is then returned with translationUnavailable: true (no extra cost). Empty = no translation.

## `transcriptType` (type: `string`):

Any: manual subtitles when they exist, else auto-generated captions. Manual only, or auto-generated only.

## `includeTimestamps` (type: `boolean`):

Adds `segments`: \[{start, duration, text}] in seconds. The full text (`transcriptText`) is always included.

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

Also return the transcript as readable paragraphs, SRT or WebVTT subtitles.

## `includeMetadata` (type: `boolean`):

Title, channel, duration, views and description are always included. This adds the publish date and like count (one more request per video).

## `searchCountry` (type: `string`):

Two-letter country code used for search results, e.g. US, FR, BR.

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

How many videos are fetched at the same time.

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

Included in the price. YouTube is reached through Apify datacenter proxies; residential proxies are only a limited automatic fallback (choosing residential here does not change that). Custom proxy URLs are used as given.

## `autoResidentialFallback` (type: `boolean`):

When YouTube blocks a video on datacenter IPs, retry it once through a residential proxy (included in the price).

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/jNQXAC9IVRw"
  ],
  "channelContent": "all",
  "searchUploadDate": "any",
  "searchSortBy": "relevance",
  "maxVideos": 50,
  "transcriptType": "any",
  "includeTimestamps": true,
  "outputFormats": [],
  "includeMetadata": true,
  "searchCountry": "US",
  "maxConcurrency": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "autoResidentialFallback": true
}
```

# Actor output Schema

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

One item per video: transcript text, timestamped segments and public video information.

# 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://youtu.be/jNQXAC9IVRw"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fit_melon/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://youtu.be/jNQXAC9IVRw",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("fit_melon/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://youtu.be/jNQXAC9IVRw"
  ]
}' |
apify call fit_melon/youtube-transcript-scraper --silent --output-dataset

```

## MCP server setup

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