# YouTube Transcript Scraper: Subtitles, Channels & Whisper (`humble-echidna/youtube-transcripts`) Actor

Get YouTube transcripts and subtitles from videos, Shorts, channels, playlists and keyword searches: text, timestamped segments, SRT and VTT, plus views, tags and chapters. No captions? Whisper transcribes the audio. Pick languages and a date window. Failed videos are free.

- **URL**: https://apify.com/humble-echidna/youtube-transcripts.md
- **Developed by:** [Michael Costa](https://apify.com/humble-echidna) (community)
- **Categories:** Videos, AI, Social media
- **Stats:** 6 total users, 5 monthly users, 88.9% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.50 / 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 does YouTube Transcript Scraper do?

**YouTube Transcript Scraper** gets the **transcript of any YouTube video**, Short, **channel, playlist or keyword
search**, as plain text, **timestamped segments, SRT or VTT**, with the video's title, views, tags, description and
chapters. Videos with **no captions at all** are transcribed from their audio with the Whisper speech model. No
login, no API key.

[Input fields](https://apify.com/humble-echidna/youtube-transcripts/input-schema) ·
[API](https://apify.com/humble-echidna/youtube-transcripts/api) ·
[Use it from Claude, ChatGPT or Cursor (MCP)](#can-i-use-youtube-transcript-scraper-from-an-ai-agent-mcp)

**Jump to:** [Fields](#what-data-does-youtube-transcript-scraper-return) · [Price](#how-much-does-it-cost-to-get-youtube-transcripts) · [How to use](#how-to-get-youtube-transcripts) ·
[No captions](#what-happens-to-videos-without-captions) · [What you get here](#what-you-get-here-that-other-transcript-actors-dont) · [Switching](#switching-from-another-youtube-transcript-actor) · [Input](#input) · [Output](#output) ·
[AI agents (MCP)](#can-i-use-youtube-transcript-scraper-from-an-ai-agent-mcp) · [Limits](#limits) · [FAQ](#faq)

**Try it in one click:** the input comes pre-filled with "Me at the zoo", the first video ever uploaded to YouTube
(19 seconds, with uploaded English subtitles). That's 1 transcript, about $0.0046 ($4.50 per 1,000, plus $0.00005 for
the run start). **Then replace it with your own videos, channels, playlists or search keywords.**

### What data does YouTube Transcript Scraper return?

One item per video:

| Field | Example | Notes |
|---|---|---|
| `id`, `url`, `title` | `jNQXAC9IVRw`, `https://www.youtube.com/watch?v=jNQXAC9IVRw`, `Me at the zoo` | The video id is stable: use it to deduplicate |
| `input`, `inputType`, `inputTitle` | `sourdough starter`, `search` | Which link or search the video came from: `video`, `channel`, `playlist` or `search` |
| `text` | `All right, so here we are, in front of the elephants...` | The whole transcript, a new paragraph after each pause of 2 s or more |
| `segments` | `[{"start": 1.2, "end": 3.36, "text": "All right, so here..."}]` | Timed in seconds from the start of the video |
| `srt`, `vtt` | `1\n00:00:01,200 --> 00:00:03,360\n...` | Subtitle files, when you turn them on |
| `transcriptSource` | `manual` | `manual` (the uploader's subtitles), `auto` (YouTube's automatic captions) or `whisper` (transcribed from the audio by this actor) |
| `transcriptLanguage` | `en` | With `languageFallback: true` when the language you asked for wasn't there |
| `captionLanguages` | `{"manual": ["de", "en"], "auto": []}` | Every caption language the video offers |
| `channel`, `channelId`, `channelHandle`, `channelFollowers` | `jawed`, `UC4QobU6STFB0P71PMvOGN5A`, `@jawed` | |
| `uploadDate`, `publishedAt`, `durationSeconds`, `viewCount`, `likeCount`, `commentCount` | `2005-04-24`, `2005-04-24T03:31:52Z`, `19`, `444097321` | As YouTube shows them when the run reads the video; likes are `null` when hidden |
| `tags`, `categories`, `description`, `thumbnail`, `chapters` | `["Film & Animation"]`, `[{"start": 0, "end": 5, "title": "Intro"}]` | Chapters with start and end in seconds |
| `whisperMinutes`, `notes` | `0`, `[]` | Audio minutes charged (Whisper only), and anything worth knowing, in plain words |

The full list, with every field's meaning, is under [Output](#output).

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

You pay per transcript: **$4.50 per 1,000 transcripts**, plus $0.00005 each time a run starts. Video details are
included at no extra cost.

Videos with **no captions** are transcribed from their audio with Whisper, only when you leave **Transcribe videos
without captions** on, charged per started audio minute on top of the transcript:

| Whisper model | Per audio minute | A 10-minute video without captions |
|---|---|---|
| Base (default) | $0.012 | $0.12 + $0.0045 |
| Small (more accurate) | $0.024 | $0.24 + $0.0045 |

- **A channel's last 100 videos**, all with captions: 100 × $0.0045 = **$0.45**.
- **The top 20 results of a keyword search**: 20 × $0.0045 = **$0.09**.
- **Caps:** **Max results per run** and **Max Whisper minutes per video** in the input, and **Maximum cost per run**
  in the run options. The run checks the budget before it reads each video and before it transcribes audio, so it
  stops cleanly and never does work it can't charge for. A video that only partly fits gets its first minutes, and
  its `notes` say so.

**Never charged:** videos that are private, removed, members-only or age-restricted, live streams in progress,
videos without captions when Whisper is off, audio Whisper finds no speech in, videos outside your date window, and
anything that fails. A video that gives no transcript isn't written to the dataset at all, so there is no error row to
pay for either; the run's log and `RUN_STATS` record say why each one was left out.

### How to get YouTube transcripts

1. Open YouTube Transcript Scraper and click **Try for free** (or **Start** if you're signed in).
2. Paste video, channel or playlist links into **YouTube links**, one per line, or type keywords into **Search
   keywords** (or both).
3. Optional: a **Transcript language** (e.g. `es`, or `es, en` for Spanish, else English), **Max videos per channel,
   playlist or search**, a **date window** for channels, playlists and searches, and the output formats you want
   (plain text, timestamped segments, SRT, VTT).
4. Click **Start**, then open the **Output** tab and export as JSON, CSV or Excel.

### What happens to videos without captions?

Most YouTube videos have captions: the uploader's own subtitles, or YouTube's automatic captions of the spoken
language. This actor reads those first, in that order. Some videos have neither (very new uploads, music, many
non-English channels, some Shorts). Caption-only scrapers return nothing for them.

With **Transcribe videos without captions** on (the default), this actor downloads the video's smallest audio
stream and transcribes it with Whisper (faster-whisper, run on Apify, nothing sent to a third party), in the
language YouTube labels the video with, or the one Whisper hears. The item says `"transcriptSource": "whisper"`,
which model ran and how many minutes were charged. A transcript from Whisper is a machine transcript: very good on
clear speech, weaker on music, heavy accents and crosstalk; pick the **Small** model for those. Whisper gets a
time budget per video (about 30 s per audio minute at 4 GB of memory, twice that at the default 2 GB): speech it
can't follow, often a language it doesn't know, would otherwise take many times longer. A transcript cut there
says so in `notes`, and only the minutes it covers are charged.

### What you get here that other transcript actors don't

- **A transcript even when the video has no captions.** Whisper transcribes the audio, charged per minute only for
  those videos. Caption-only tools return an error or an empty field for them.
- **Videos, Shorts, channels, playlists and keyword searches in one run**, mixed freely, each video read once even
  when two inputs name it.
- **Every format in the same item**: plain text, timed segments, SRT and WebVTT, with no second run for another format.
- **Full video details at no extra cost**: channel, follower count, exact publish time, duration, views, likes,
  comment count, tags, categories, description, thumbnail and chapters, plus every caption language the video offers.
- **A date window for channels, playlists and searches** that skips videos outside it before they're read, so they
  cost nothing, and stops reading a channel once its videos are older than the window.
- **Nothing to pay for videos that fail**: no error rows in your dataset, and the reason for each one in the log.
- **Language list in order of preference**, with a clear flag when a video had none of them.

### Switching from another YouTube transcript actor?

Paste the same video links. What usually maps over:

| You had | Here |
|---|---|
| One video per run | Any number of videos, channels and playlists in **YouTube links** |
| A channel or playlist actor feeding a transcript actor | Paste the channel or playlist link directly; set **Max videos per channel, playlist or search** |
| Search keywords | **Search keywords**, one search per line, or paste a YouTube search results link |
| A channel URL with a start and end date | The channel link plus **Published on or after** / **Published on or before** (a date, or a span such as `30 days`) |
| Language list / preferred language | **Transcript language**: one code, or several in order (`es, en`); when none is there you get the video's own language, flagged with `languageFallback` |
| Output format switch (text, timestamps, SRT, VTT) | Turn on any mix of `text`, `segments`, `srt`, `vtt`; they come in the same item |
| "Transcript not available" rows | Not written and not charged; the run log and `RUN_STATS` list each video and why |

### Input

| Field | What it does |
|---|---|
| **YouTube links** (`urls`) | Videos (watch, youtu.be, Shorts, live, embed links or bare ids), channels (`@handle`, `/channel/UC...`, a `/videos`, `/shorts` or `/streams` tab), playlists and search result links, one per line. |
| Search keywords (`searchQueries`) | One YouTube search per line; its top results in YouTube's order. |
| Max videos per channel, playlist or search (`maxVideosPerSource`) | Channels newest first; default 10, up to 5,000. |
| Transcript language(s) (`language`) | A code such as `en`, `es`, `pt-BR`, or several in order (`es, en`). Empty: the video's own language. |
| Published on or after / on or before (`publishedAfter`, `publishedBefore`) | A date window for videos from channels, playlists and searches: `2026-01-31` or a span back from today such as `30 days`. Video links you paste are always read. |
| Transcribe videos without captions (`whisperFallback`) | On by default; charged per audio minute. |
| Whisper model (`whisperModel`) | `base` (default) or `small`. |
| Max Whisper minutes per video (`maxWhisperMinutesPerVideo`) | Default 60, up to 300. |
| Plain text, Timestamped segments, SRT, WebVTT (`includeText`, `includeSegments`, `includeSrt`, `includeVtt`) | Which formats each item carries. Text and segments are on by default. |
| Video details (`includeMetadata`) | Channel, date, views, likes, tags, description, chapters. On by default. |
| Max results per run (`maxResults`) | Cap the number of transcripts. |
| Proxy (`proxyConfiguration`) | Apify Proxy by default. |

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    "https://www.youtube.com/@jawed",
    "https://www.youtube.com/playlist?list=PLxxxxxxxx"
  ],
  "searchQueries": ["sourdough starter"],
  "maxVideosPerSource": 20,
  "publishedAfter": "90 days",
  "language": "en, es",
  "includeSrt": true
}
```

### Output

One item per video with a transcript. Real output of the default input on Apify (2026-10-14; text and segments shortened, some details left out). Fields YouTube doesn't publish for a video are `null`.

```json
{
  "id": "jNQXAC9IVRw",
  "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
  "title": "Me at the zoo",
  "input": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
  "inputType": "video",
  "inputTitle": null,
  "transcriptSource": "manual",
  "transcriptLanguage": "en",
  "requestedLanguage": null,
  "languageFallback": false,
  "captionLanguages": {"manual": ["de", "en"], "auto": []},
  "whisperModel": null,
  "whisperMinutes": 0,
  "wordCount": 39,
  "segmentCount": 6,
  "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 ...",
  "segments": [{"start": 1.2, "end": 3.36, "text": "All right, so here we are, in front of the elephants"}],
  "srt": null,
  "vtt": null,
  "notes": [],
  "scrapedAt": "2026-10-14T22:45:32.983015Z",
  "channel": "jawed",
  "channelId": "UC4QobU6STFB0P71PMvOGN5A",
  "channelHandle": "@jawed",
  "viewCount": 444097321,
  "likeCount": 20077772,
  "tags": ["me at the zoo", "jawed karim", "first youtube video"],
  "uploadDate": "2005-04-24",
  "publishedAt": "2005-04-24T03:31:52Z",
  "durationSeconds": 19,
  "chapters": [{"start": 0, "end": 5, "title": "Intro"}]
}
```

The run's `RUN_STATS` record lists every input line and every video, with why a video had no transcript
(`noCaptions`, `private`, `unavailable`, `ageRestricted`, `membersOnly`, `live`, `blocked` ...), and which videos
were skipped for falling outside your date window.

### Run it on a schedule, or from your own code

1. Save your input as a [task](https://docs.apify.com/platform/actors/running/tasks) (**Save as a new task**, top right
   of the actor page) and add it to a [schedule](https://docs.apify.com/platform/schedules) (Console → Schedules →
   **Create new**), for example to pull a channel's newest videos every morning.
2. Collect results: download the dataset as JSON, CSV or Excel; fetch the latest run's results from the
   [API](https://apify.com/humble-echidna/youtube-transcripts/api)
   (`GET https://api.apify.com/v2/actor-tasks/<task id>/runs/last/dataset/items?status=SUCCEEDED&format=json`, with
   your API token); let a [webhook](https://docs.apify.com/platform/integrations/webhooks) tell your system when a
   run succeeds; or connect it to Make, Zapier or n8n through
   [Apify's integrations](https://docs.apify.com/platform/integrations).

#### Can I use YouTube Transcript Scraper from an AI agent (MCP)?

Yes, through [Apify's MCP server](https://docs.apify.com/platform/integrations/mcp), from Claude, ChatGPT, Cursor or
any other MCP client. Add this to your client's MCP configuration (or let the agent find it with the server's actor
search); your client signs you in to Apify:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=humble-echidna/youtube-transcripts"
    }
  }
}
```

To use an [Apify API token](https://console.apify.com/settings/integrations) instead of signing in, add
`"headers": {"Authorization": "Bearer <APIFY_TOKEN>"}` next to `url`. An agent passes
`{"urls": ["<video link>"], "includeSegments": false}` for just the text, or a channel link with
`"maxVideosPerSource": 5`.

### Who it's for

People who turn videos into text: AI and RAG builders feeding transcripts to a model, marketers and researchers
summarizing a channel's output, editors who need SRT/VTT subtitles, and course and podcast teams repurposing talks.

### Why this one?

- **Videos without captions still get a transcript.** Whisper transcribes the audio when YouTube has no captions,
  charged per minute only then; caption-only scrapers return nothing for those videos.
- **Channels, playlists and keyword searches in the same run as single videos**, each video read once.
- **Every format in one item:** plain text, timestamped segments, SRT and WebVTT, plus the video's details at no
  extra cost.
- **The real spoken track, never a machine translation:** uploaded subtitles first, then YouTube's automatic
  captions of the spoken language. A missing language is flagged, not silently swapped.
- **Reliable.** One failing video never affects the others; a bot check or rate limit is retried twice from a new
  IP address. Failed videos are free, and the log says why each one failed.

### Limits

- **Logged out only.** Private, members-only and age-restricted videos need a signed-in account, which this actor
  never uses; they're listed as failed and not charged.
- **Live streams** in progress have no transcript yet; run it again once the stream has ended.
- **Very long transcripts** (about 15 hours and up with every format on) don't fit one dataset item with every
  format: WebVTT, then SRT, then the segments are left out, the text is always kept, and `notes` says so.
- **Whisper** transcribes at most 300 minutes per video (60 by default), one video at a time, so a run of many
  long videos without captions takes a while; videos with captions take seconds each.
- **No translation.** YouTube refuses its machine-translated caption tracks to logged-out readers, so you get the
  video's own language (flagged) when none of the ones you asked for is there.
- **No comments.** Searches return YouTube's own relevance order; YouTube no longer honours a sort by upload date
  there, so use the date window to narrow a search.
- **The date window** reads a list's rough dates ("3 weeks ago") first, then the exact day: a playlist or search is
  read up to 10 times as far as the videos you asked for to find ones inside it.

### FAQ

#### Is it legal to scrape YouTube transcripts?

This actor reads only what any logged-out visitor sees on youtube.com: public videos, their captions and details.
It never signs in and uses no accounts (only the anonymous visitor id YouTube gives every logged-out visitor),
and collects no personal data beyond the public channel name and
handle shown with every video. Be aware that **YouTube's robots.txt disallows automated access** to the caption and
player addresses this needs, and **YouTube's Terms of Service forbid accessing the service by automated means**
without YouTube's permission. Whether and how you use transcripts (and the videos' content, which belongs to their
creators) is your responsibility. If you are a rights holder and want something removed or not read, open an issue
and we'll act on it promptly.

#### Why did a video return no transcript?

The run log and the `RUN_STATS` record name each video and the reason: no captions (and Whisper off), private,
removed, members-only, age-restricted, a live stream in progress, or a bot check YouTube kept asking for after two
retries from new IP addresses. Nothing is charged for those. Please open an issue with the link if a public video
with captions fails.

#### Which caption track do I get?

The uploader's own subtitles in your language first, then YouTube's automatic captions of the spoken language. With
no language set, the video's own language. `transcriptSource` and `transcriptLanguage` say which one you got, and
`captionLanguages` lists everything the video offers.

#### How accurate is the Whisper transcript?

Whisper's base model makes about 4 words in 100 wrong on clear read speech (measured on LibriSpeech test-clean,
2026-09-26) and more on noisy audio; the small model about 3 in 100. Captions written by the uploader are usually
better, which is why they always come first.

#### How is this different from YouTube's own transcript button or the YouTube Data API?

YouTube's "Show transcript" panel works one video at a time in a browser. The YouTube Data API only lets a video's
owner download its captions. This actor works for any public video, in bulk, from channels, playlists and searches,
with timestamps and subtitle files, and transcribes videos that have no captions at all.

### Related actors

| Actor | Use it when |
|---|---|
| [Audio & Video Transcriber](https://apify.com/humble-echidna/audio-transcriber) | Your audio or video files and podcast feeds (not YouTube), to text, SRT and VTT with Whisper |
| [AI for Every Row](https://apify.com/humble-echidna/ai-rows) | Summarize or classify every transcript with an LLM |
| [Dataset Transform](https://apify.com/humble-echidna/dataset-transform) | Reshape, filter or deduplicate the results into a clean CSV |

### Feedback and support

Found a bug, or need a field that isn't here? Open an issue on the **Issues** tab with the input you used.

### Versions

Current version: **0.2**. See the Changelog tab for what changed in each version.

# Changelog

This Actor's version history is a separate document: https://apify.com/humble-echidna/youtube-transcripts/changelog.md

# Actor input Schema

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

Videos, channels, playlists or search result pages, one per line. Videos: watch, youtu.be, Shorts, live or embed links, or a bare 11-character id (jNQXAC9IVRw). Channels: https://www.youtube.com/@handle (its Videos tab), a /videos, /shorts or /streams tab, or /channel/UC... links. Playlists: https://www.youtube.com/playlist?list=... Searches: https://www.youtube.com/results?search_query=... Leave empty if you only use Search keywords.

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

Search YouTube for these keywords, one search per line (e.g. 'sourdough starter'), and get the transcripts of the top results in YouTube's own order, up to 'Max videos per channel, playlist or search' each. Optional; works alongside YouTube links.

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

How many videos to read from each channel, playlist or search, e.g. 10. From 1 to 5000; default 10. Channels give their newest first, searches YouTube's top results. Single video links aren't affected.

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

The caption language you want, as a code such as en, es, de, pt-BR or ja; or several in order of preference, separated by commas (es, en: Spanish, else English). Leave empty (the default) for the video's own language. The uploader's subtitles are used first, then YouTube's automatic captions of the spoken language. When a video has none of these languages, you get its own language instead, marked with languageFallback: true (never a machine translation).

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

Only videos from channels, playlists and searches published on or after this day: a date (YYYY-MM-DD) or a span back from today such as '30 days' or '2 weeks'. Videos outside the window are skipped before they're read and never charged. Video links you paste are always read. Leave empty for no start.

## `publishedBefore` (type: `string`):

Only videos from channels, playlists and searches published on or before this day: a date (YYYY-MM-DD) or a span back from today such as '1 year'. Leave empty for no end.

## `whisperFallback` (type: `boolean`):

When a video has no captions at all, download its audio and transcribe it with the Whisper speech model, charged per audio minute on top of the transcript (see Pricing). On by default. Turn it off to skip those videos instead (they're listed in the log and cost nothing).

## `whisperModel` (type: `string`):

The speech model for videos without captions: `base` (default) suits clear speech in English and other major languages; `small` makes fewer mistakes on accents, background noise and non-English speech and is priced higher per minute.

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

Transcribe at most this many minutes of each video without captions, e.g. 60 (the default). From 1 to 300. A longer video gets its first part, and the item's notes say so. Videos with captions are never cut.

## `includeText` (type: `boolean`):

Add the whole transcript as one text (`text`), with a new paragraph after each pause of 2 seconds or more. On by default.

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

Add the transcript as timed segments (`segments`: start and end in seconds, and the text). On by default.

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

Add the transcript as an SRT subtitle file (`srt`), ready to save as a .srt file. Off by default.

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

Add the transcript as WebVTT captions (`vtt`), ready to save as a .vtt file. Off by default.

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

Add the video's details: channel, upload date, duration, views, likes, comment count, tags, categories, description, thumbnail and chapters. On by default, at no extra cost. Turn off for smaller items.

## `maxResults` (type: `integer`):

Stop after this many transcripts in total, e.g. 20. Minimum 1; leave empty (the default) for no limit. The run also stops cleanly at the maximum cost per run you set in the run options, whichever comes first. Videos without a transcript don't count.

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

Which IP addresses YouTube sees. The default, Apify's residential proxy, is what this actor is tested with: YouTube answered datacenter addresses with a bot check on every try (2026-10-14). Its traffic is included in the price. A bot check or rate limit is retried twice from a new address.

## Actor input object example

```json
{
  "urls": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ],
  "maxVideosPerSource": 10,
  "whisperFallback": true,
  "whisperModel": "base",
  "maxWhisperMinutesPerVideo": 60,
  "includeText": true,
  "includeSegments": true,
  "includeSrt": false,
  "includeVtt": false,
  "includeMetadata": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

No description

## `runStats` (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=jNQXAC9IVRw"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

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

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

```

## MCP server setup

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