# YouTube Transcript API (`maximedupre/youtube-transcript-api`) Actor

Extract available captions from public YouTube videos using URLs or video IDs. Get full transcript text, timestamped segments, optional word timings and paragraphs, caption details, and SRT, VTT, Markdown, and PDF download links.

- **URL**: https://apify.com/maximedupre/youtube-transcript-api.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Videos, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 video transcripts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

### 🎬 Turn public YouTube videos into searchable text

YouTube Transcript API is for developers, researchers, creators, and teams that need text from public YouTube videos. Give it video URLs or IDs and get the full available transcript, timestamped segments, caption language and source, optional word timings and paragraphs, plus download links for SRT, VTT, Markdown, and PDF files. Use the results in your own search, review, or content workflow.

Use it as a YouTube transcript extractor or YouTube to text API for available captions. It is not a speech-to-text YouTube transcript generator, so it does not create new transcripts when a video has no usable captions.

- Turn a public video URL or ID into plain transcript text with [**YouTube Transcript to Text**](https://apify.com/maximedupre/youtube-transcript-api/examples/youtube-transcript-to-text).
- Read creator-provided or auto-generated captions with [**YouTube Caption Extractor**](https://apify.com/maximedupre/youtube-transcript-api/examples/youtube-caption-extractor).
- Collect available captions from a public video for [**Online Video Transcription**](https://apify.com/maximedupre/youtube-transcript-api/examples/online-video-transcription).
- Convert a public video reference into text with [**YouTube to Text**](https://apify.com/maximedupre/youtube-transcript-api/examples/youtube-to-text).
- Pull a full available transcript and its timings with [**YouTube Transcript Extractor**](https://apify.com/maximedupre/youtube-transcript-api/examples/youtube-transcript-extractor).

#### 📚 Full YouTube transcripts with timing

Each saved dataset row contains the full available transcript text, source video identity, caption language, caption source, timestamped segments, and links to SRT, VTT, Markdown, and PDF files. Some rows also contain word-level timing and paragraph grouping. The `transcriptResults` output link opens the dataset.

#### ▶️ Run a transcript job from URLs or IDs

1. Add one or more public YouTube video URLs or raw video IDs.
2. Set a preferred caption language if you have one.
3. Choose creator-provided captions only, or allow auto-generated captions too.
4. Start the run and open the transcript dataset when it finishes.

The Actor reads the caption source made available for each public video. If the preferred language is not available, another available caption language may be used and the returned language is included in the row. A video without a usable transcript does not stop the rest of the submitted list.

#### ⚙️ Input

Add one or more public video references. The schema has no fixed maximum, so use a list sized for the run and the source limits you expect.

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `videoUrlsOrIds` | array of strings | Required. Adds public YouTube video URLs or raw video IDs. URLs and IDs can be mixed in the same list. |
| `preferredCaptionLanguage` | string | Optional language code such as `en` or `en-US`. If it is unavailable, another available caption language is used and reported. |
| `captionSource` | string enum | Choose `creator` for creator-provided captions only, or `creator_or_auto` to allow auto-generated captions too. |

This example is copied from the public input of a successful current-beta default-input run:

```json
{
  "videoUrlsOrIds": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "preferredCaptionLanguage": "en",
  "captionSource": "creator_or_auto"
}
```

#### 🧾 Output

**Run output**

| Field | Type | What it does |
| --- | --- | --- |
| `transcriptResults` | string URL | Opens the default dataset that contains the transcript rows. |

**Transcript row**

Each saved row has this complete field shape. Optional fields can be absent when the source does not provide them.

| Field | Type | What it does |
| --- | --- | --- |
| `videoId` | string | YouTube video ID for the source video. |
| `title` | string, when available | Title of the YouTube video. |
| `channelName` | string, when available | Name of the YouTube channel. |
| `thumbnailUrl` | URL string, when available | URL for the video thumbnail. |
| `captionLanguage` | string | Language of the captions returned for the video. |
| `captionSource` | string enum | `creator` for creator-provided captions or `autoGenerated` for auto-generated captions. |
| `transcriptText` | string | Complete available transcript as plain text. |
| `segments` | array of objects | Timestamped transcript segments in playback order. |
| `segments[].text` | string | Text spoken in the segment. |
| `segments[].startSeconds` | number | Segment start time from the beginning of the video, in seconds. |
| `segments[].durationSeconds` | number | Segment duration in seconds. |
| `segments[].words` | array of objects, optional | Word-level timing data when it is available. |
| `segments[].words[].text` | string | Text of the word. |
| `segments[].words[].startSeconds` | number | Word start time from the beginning of the video, in seconds. |
| `segments[].words[].durationSeconds` | number | Word duration in seconds. |
| `paragraphs` | array of strings, optional | Paragraph grouping of the transcript text. |
| `downloads` | object | Download URLs for the generated transcript files. |
| `downloads.srtUrl` | URL string | SRT subtitle file URL. |
| `downloads.vttUrl` | URL string | WebVTT subtitle file URL. |
| `downloads.markdownUrl` | URL string | Markdown transcript file URL. |
| `downloads.pdfUrl` | URL string | PDF transcript report URL. |

This complete row is from a successful current-beta run. It shows a creator-provided transcript without optional word timings:

```json
{
  "videoId": "jNQXAC9IVRw",
  "title": "Me at the zoo",
  "channelName": "jawed",
  "thumbnailUrl": "https://i.ytimg.com/vi/jNQXAC9IVRw/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG-AoAC8AGKAgwIABABGFUgWShlMA8=&rs=AOn4CLA9eLBatYv9WbkD4BbZ2Im-biSPTw",
  "captionLanguage": "en",
  "captionSource": "creator",
  "transcriptText": "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": [
    {
      "text": "All right, so here we are, in front of the elephants",
      "startSeconds": 1.2,
      "durationSeconds": 2.16
    },
    {
      "text": "the cool thing about these guys is that they have really...",
      "startSeconds": 5.318,
      "durationSeconds": 2.656
    },
    {
      "text": "really really long trunks",
      "startSeconds": 7.974,
      "durationSeconds": 4.642
    },
    {
      "text": "and that's cool",
      "startSeconds": 12.616,
      "durationSeconds": 1.751
    },
    {
      "text": "(baaaaaaaaaaahhh!!)",
      "startSeconds": 14.421,
      "durationSeconds": 1.312
    },
    {
      "text": "and that's pretty much all there is to say",
      "startSeconds": 16.881,
      "durationSeconds": 2
    }
  ],
  "paragraphs": [
    "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"
  ],
  "downloads": {
    "srtUrl": "https://api.apify.com/v2/key-value-stores/e7Q8cG3AEmd4BrwmP/records/transcript-jNQXAC9IVRw.srt?signature=15FbEZZTiuuI9oqYAWDhm",
    "vttUrl": "https://api.apify.com/v2/key-value-stores/e7Q8cG3AEmd4BrwmP/records/transcript-jNQXAC9IVRw.vtt?signature=LvDxwUJum07BoX4JQtDP",
    "markdownUrl": "https://api.apify.com/v2/key-value-stores/e7Q8cG3AEmd4BrwmP/records/transcript-jNQXAC9IVRw.md?signature=2S3dTG4ppsWeZUaCnPX1",
    "pdfUrl": "https://api.apify.com/v2/key-value-stores/e7Q8cG3AEmd4BrwmP/records/transcript-jNQXAC9IVRw.pdf?signature=1r6ljRrwL9xAh277cpvdD"
  }
}
```

This shortened row is also from a successful current-beta run and shows optional word timings. The string `"..."` marks omitted transcript, segment, word, and paragraph data.

```json
{
  "videoId": "EJED0LNsdPc",
  "title": "How to Use YouTube Transcript Auto Generate Feature !",
  "channelName": "Tekwiq",
  "thumbnailUrl": "https://i.ytimg.com/vi/EJED0LNsdPc/sddefault.jpg",
  "captionLanguage": "en",
  "captionSource": "autoGenerated",
  "transcriptText": "...",
  "segments": [
    {
      "text": "Hey there guys, welcome back to another",
      "startSeconds": 0.08,
      "durationSeconds": 4.239,
      "words": [
        {
          "text": "Hey",
          "startSeconds": 0.08,
          "durationSeconds": 0.32
        },
        {
          "text": "there",
          "startSeconds": 0.4,
          "durationSeconds": 0.319
        },
        "..."
      ]
    },
    "..."
  ],
  "paragraphs": [
    "..."
  ],
  "downloads": {
    "srtUrl": "https://api.apify.com/v2/key-value-stores/ZCdEt7x52xcUFvtDW/records/transcript-EJED0LNsdPc.srt?signature=A2A6MvYr5ROiVrWvyTyB",
    "vttUrl": "https://api.apify.com/v2/key-value-stores/ZCdEt7x52xcUFvtDW/records/transcript-EJED0LNsdPc.vtt?signature=10mQyHnWw8LpgykKzi2pf",
    "markdownUrl": "https://api.apify.com/v2/key-value-stores/ZCdEt7x52xcUFvtDW/records/transcript-EJED0LNsdPc.md?signature=1JEfw4V2wgVPn9PExbx6s",
    "pdfUrl": "https://api.apify.com/v2/key-value-stores/ZCdEt7x52xcUFvtDW/records/transcript-EJED0LNsdPc.pdf?signature=100trB3p4uaRiOwhmbztp"
  }
}
```

#### 💳 Pricing

This Actor uses pay-per-event pricing. The primary event is `youtube-video-transcript`, titled **Video transcript**, and it covers one complete available transcript saved for one public YouTube video. The current tier price is shown in the Pricing tab and can vary by plan. This README does not promise a fixed rate.

#### 🔌 Integrations

Use the Apify Actor and API access to open the `transcriptResults` dataset link and read transcript rows in your own workflow. The output keeps the video ID, caption details, timing, transcript text, and file links together.

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### What happens when the preferred caption language is missing?

The Actor can use another available caption language and reports the language it returned in `captionLanguage`. If you need creator-provided captions only, set `captionSource` to `creator`.

##### Can I choose creator-provided captions only?

Yes. Set `captionSource` to `creator`. Use `creator_or_auto` when auto-generated captions are also acceptable.

##### Does this create a transcript from video audio?

No. It extracts available creator-provided or auto-generated captions. It does not download video or audio and does not create new speech-to-text transcripts when captions are missing.

##### Does it search YouTube transcripts by keyword?

No. Submit the public video URLs or IDs you want to read. The Actor does not discover videos from search terms, channels, or playlists. You can use the returned text in your own YouTube transcript search workflow.

##### What is included in a YouTube transcript download?

Each saved row includes links for SRT, VTT, Markdown, and PDF files. It also includes plain transcript text, timestamped segments, caption language, and caption source.

##### What happens when the same video is submitted more than once?

The first eligible occurrence is saved. Later copies of that same source video are ignored, so one saved row describes the first match rather than collecting every later submitted value.

##### Can I use the transcript in an AI or search workflow?

Yes. The Actor returns structured text and timing through the dataset and API. It does not summarize, translate, create chapters, or generate embeddings, so apply those transformations in your own workflow.

##### What if one video has no usable transcript?

That video does not stop the rest of the submitted list. Results depend on the public captions available for each video and the caption options you choose.

### 📝 Changelog

**v0.0** (19-09-2026)

- Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~youtube-transcript-api/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- Use [YouTube Transcript to PDF](https://apify.com/maximedupre/youtube-to-pdf) when you need a readable PDF copy of a public video transcript.
- Use [YouTube Subtitle Search Scraper](https://apify.com/maximedupre/youtube-subtitle-search-crawler) when you need to find public videos whose captions contain a phrase.
- Use [TikTok Transcript Scraper](https://apify.com/maximedupre/tiktok-transcript-scraper) when the source is a public TikTok video rather than YouTube.
- Compare [YouTube Transcript API](https://apify.com/novi/youtube-transcript-api) when you want another URL-based YouTube transcript option.
- Compare [YouTube Transcript Generator API & Subtitle Downloader](https://apify.com/tugelbay/youtube-transcript) when you need to review another transcript and subtitle workflow.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `videoUrlsOrIds` (type: `array`):

Add one or more public YouTube video URLs or raw video IDs. Mix URLs and IDs in the same list. Shorts URLs work when the source has a transcript.

## `preferredCaptionLanguage` (type: `string`):

Enter an optional language code such as en or en-US. If that language is unavailable, the Actor uses another available caption language and reports the language it returns.

## `captionSource` (type: `string`):

Choose creator-provided captions only, or allow auto-generated captions too.

## Actor input object example

```json
{
  "videoUrlsOrIds": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "dQw4w9WgXcQ"
  ],
  "preferredCaptionLanguage": "en",
  "captionSource": "creator_or_auto"
}
```

# Actor output Schema

## `transcriptResults` (type: `string`):

Open the transcript results in the dataset.

# 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 = {
    "videoUrlsOrIds": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    ],
    "preferredCaptionLanguage": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/youtube-transcript-api").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 = {
    "videoUrlsOrIds": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
    "preferredCaptionLanguage": "en",
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maximedupre/youtube-transcript-api"
        }
    }
}
```

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/6LaGDKsdvIUK60wuA/builds/vo8g4TTPNHZXEc35M/openapi.json
