# YouTube Download API: Video and Audio (MP4, MP3, M4A) (`johnvc/youtube-download-api`) Actor

Download YouTube videos and audio by API. MP4 from 144p to 4K with sound, or M4A, MP3 and Opus audio. One row per link with a stable file link, size, checksum and duration. Pay per minute delivered; failed and skipped videos are free.

- **URL**: https://apify.com/johnvc/youtube-download-api.md
- **Developed by:** [John](https://apify.com/johnvc) (community)
- **Categories:** Videos, Social media
- **Stats:** 6 total users, 5 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.01 / 1,000 audio minutes

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

## YouTube Download API: download YouTube video and audio files by API

The YouTube Download API turns a list of [YouTube](https://www.youtube.com) links into real files: MP4 video from 144p to 4K with sound always included, or audio as M4A, MP3 or Opus. Every link gets one row with a stable file link, file size, SHA-256 checksum, duration and channel details. Files land in the run's storage, or straight in your own Amazon S3, Google Cloud Storage or Azure bucket. You pay per minute of media actually delivered. Private, removed, blocked or skipped videos cost nothing, and no cookies or login are needed for public videos. Built for archiving your own channel, feeding transcription and AI pipelines, research datasets and MCP agents.

### ⚡ What you get back

- **A real file, stored for you.** Each download lands in the run's key-value store with a direct link you can fetch from code, a browser or the next step of a workflow. Never a temporary player link that expires in a few hours.
- **Or straight into your own bucket.** Point the API at Amazon S3 (or any S3-compatible storage such as Cloudflare R2, Backblaze B2 or Wasabi), Google Cloud Storage or Azure Blob Storage, and files are uploaded there directly, with no copy left behind.
- **Video with sound, every time.** Video and audio streams are combined into one file before delivery, so there are no silent MP4s.
- **Audio in the format you need.** M4A and Opus are delivered without re-encoding; MP3 is converted for you. Standard quality is compact and clear for speech; high quality is the best stream YouTube offers.
- **The smallest file at the quality you asked for.** By default the most efficient codec is chosen (AV1 or VP9 when YouTube offers them), which is often half the size of H.264. Ask for H.264 when you need a file that plays on every device and editor.
- **One row per link, always.** A file row, a metadata row, or a free error row that says exactly why: `VIDEO_PRIVATE`, `VIDEO_UNAVAILABLE`, `AGE_RESTRICTED`, `OVER_MAX_MINUTES` and so on.
- **Integrity fields.** `fileSizeBytes` and `sha256` on every file row, so you can verify and deduplicate downstream.
- **Free metadata.** `metadataOnly` returns title, channel, duration, the qualities on offer and estimated file sizes without downloading anything.

### 🎯 Use cases

- **Archive your own channel.** Keep an offline copy of every upload at the quality you choose, with checksums.
- **Audio for transcription and AI pipelines.** Pull compact audio for speech-to-text, summarization, search indexes and RAG. Pair it with the [YouTube Transcripts API](https://apify.com/johnvc/YoutubeTranscripts?fpr=9n7kx3) when captions already exist.
- **Lectures, talks and webinars for offline study.** Download long-form educational video at 360p or 480p to keep files small.
- **Research and media monitoring.** Collect the videos behind a news story, a campaign or a topic for analysis, with a metadata row per video.
- **Accessibility.** Produce audio-only versions, or files that can be re-captioned, slowed down or translated.
- **Video datasets for machine learning.** Batch downloads with predictable naming (`<videoId>_<quality>.<ext>`), size limits and checksums.
- **Agents that need the media itself.** Any MCP client can call this API as a tool and get a file link back.

You are responsible for having the rights to the content you download. Use this API for your own content, for content you have permission to use, and for uses the law allows where you live.

### 🔧 Input

| Field | Type | What it does |
| --- | --- | --- |
| `videoUrls` | array, required | YouTube links or 11-character video IDs. Watch links, `youtu.be` links, Shorts, embed and live-replay links all work. Up to 200 per run. |
| `format` | string | `audio` (default) or `video`. |
| `quality` | string | Maximum video quality: `144p`, `240p`, `360p`, `480p`, `720p` (default), `1080p`, `1440p`, `2160p`. If the video is not offered that high, the best available quality below it is delivered and billed at its own rate. |
| `audioFormat` | string | `m4a` (default), `mp3` or `opus`. |
| `audioQuality` | string | `standard` (default, compact, clear for speech) or `high` (best available). |
| `videoCodec` | string | `smallest` (default, most efficient codec) or `h264` (plays everywhere, up to 1080p). |
| `metadataOnly` | boolean | Return details, available qualities and estimated sizes only. Free. |
| `maxMinutes` | integer | Skip videos longer than this, at no charge, before anything is downloaded. |
| `maxMegabytes` | integer | Skip files estimated to be larger than this, at no charge. |
| `maxAgeDays` | integer | Reuse cached metadata up to this many days old (default 7, 0 to always check YouTube). Media files are always downloaded fresh. |
| `storageProvider` | string | Where files go: `apify` (default, the run's key-value store), `s3`, `gcs` or `azure`. |
| `storageBucket` | string | Bucket name, for `s3` and `gcs`. |
| `storagePrefix` | string | Optional folder inside the bucket or container, for example `youtube/2026/`. |
| `storageRegion` | string | Bucket region for `s3` (default `us-east-1`; `auto` for Cloudflare R2). |
| `storageEndpoint` | string | https endpoint for S3-compatible storage other than Amazon. |
| `storageAccessKeyId` | string, secret | Access key ID (`s3`), or HMAC access ID (`gcs`). |
| `storageSecretAccessKey` | string, secret | Secret access key (`s3`), or HMAC secret (`gcs`). |
| `storageSasUrl` | string, secret | Container URL with a write SAS token, for `azure`. |
| `cookies` | string, secret | Optional. Cookies from your own signed-in session, only for age-restricted or members-only videos you have access to. |

#### Audio for transcription

```json
{
  "videoUrls": ["https://www.youtube.com/watch?v=aqz-KE-bpKQ"],
  "format": "audio",
  "audioFormat": "m4a"
}
```

#### 720p video that plays everywhere

```json
{
  "videoUrls": ["https://youtu.be/aqz-KE-bpKQ"],
  "format": "video",
  "quality": "720p",
  "videoCodec": "h264"
}
```

#### Check a list before you spend

```json
{
  "videoUrls": ["aqz-KE-bpKQ", "jNQXAC9IVRw"],
  "metadataOnly": true
}
```

#### A batch with guard rails

```json
{
  "videoUrls": ["https://www.youtube.com/watch?v=aqz-KE-bpKQ", "https://www.youtube.com/shorts/jNQXAC9IVRw"],
  "format": "video",
  "quality": "1080p",
  "maxMinutes": 60,
  "maxMegabytes": 500
}
```

#### Straight into your own S3 bucket

```json
{
  "videoUrls": ["https://www.youtube.com/watch?v=aqz-KE-bpKQ"],
  "format": "video",
  "quality": "720p",
  "storageProvider": "s3",
  "storageBucket": "my-video-archive",
  "storageRegion": "us-east-1",
  "storagePrefix": "youtube/",
  "storageAccessKeyId": "YOUR_ACCESS_KEY_ID",
  "storageSecretAccessKey": "YOUR_SECRET_ACCESS_KEY"
}
```

### 🗄️ Send files to your own storage

By default every file is kept in the run's key-value store and the row's `fileUrl` links to it. Set `storageProvider` and the API uploads each finished file directly to your storage instead. Nothing is kept in the key-value store, and the row tells you where the object is (`fileUrl`, `storageUri`).

| Destination | `storageProvider` | What to supply |
| --- | --- | --- |
| [Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html) | `s3` | `storageBucket`, `storageRegion`, `storageAccessKeyId`, `storageSecretAccessKey` |
| Cloudflare R2 | `s3` | the same, plus `storageEndpoint` (`https://<account>.r2.cloudflarestorage.com`) and `storageRegion: "auto"` |
| Backblaze B2, Wasabi, DigitalOcean Spaces, MinIO | `s3` | the same, plus the provider's S3 `storageEndpoint` and its region |
| [Google Cloud Storage](https://cloud.google.com/storage/docs/interoperability) | `gcs` | `storageBucket` and an HMAC key pair from Cloud Storage settings, Interoperability tab, as `storageAccessKeyId` and `storageSecretAccessKey` |
| [Azure Blob Storage](https://learn.microsoft.com/azure/storage/common/storage-sas-overview) | `azure` | `storageSasUrl`: the container URL with a SAS token that allows create and write |

How it works:

- **Checked before anything is downloaded.** The run writes and removes a tiny test object first. If the bucket, region or key is wrong you get one free `STORAGE_UNAVAILABLE` row and the run stops, before any media is fetched or charged.
- **Least privilege is enough.** The key only needs permission to put objects (and, optionally, delete the test object) in that bucket or prefix. It never needs to list or read.
- **Your credentials stay secret.** They are stored as secret input fields, used only to sign the upload, and never written to the log or the dataset. For Azure, the SAS token is stripped from every address in the output.
- **File names.** `<storagePrefix><videoId>_<quality>.<ext>`, for example `youtube/aqz-KE-bpKQ_720p.mp4`. Running the same video again overwrites the same object.
- **If an upload fails part-way through a run**, that file is kept in the run's key-value store instead and the row's `note` says so, so a finished download is never lost. The upload attempt is still billed.
- **Size limit.** One file can be up to 5 GB when sent to your own storage.
- **Access to the object** follows your bucket's own permissions; `fileUrl` is the object's address, not a signed link.

Google Drive, Dropbox and OneDrive are not direct destinations. Use a workflow step (n8n, Make or Zapier) to copy each `fileUrl` there.

### 📤 Example output

A delivered file:

```json
{
  "resultType": "file",
  "videoId": "aqz-KE-bpKQ",
  "url": "https://www.youtube.com/watch?v=aqz-KE-bpKQ",
  "input": "https://youtu.be/aqz-KE-bpKQ",
  "title": "Big Buck Bunny 60fps 4K - Official Blender Foundation Short Film",
  "channelName": "Blender",
  "channelId": "UCSMOQeBJ2RAnuFungnQOxLg",
  "channelUrl": "https://www.youtube.com/channel/UCSMOQeBJ2RAnuFungnQOxLg",
  "durationSeconds": 635,
  "uploadDate": "2014-11-10",
  "viewCount": 23402793,
  "format": "video",
  "quality": "720p",
  "requestedQuality": "720p",
  "container": "mp4",
  "videoCodec": "h264",
  "audioCodec": "aac",
  "width": 1280,
  "height": 720,
  "fps": 60,
  "audioBitrateKbps": 129,
  "fileKey": "aqz-KE-bpKQ_720p.mp4",
  "fileUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/aqz-KE-bpKQ_720p.mp4",
  "fileSizeBytes": 161192091,
  "sha256": "<64 hex characters>",
  "chargedEvent": "video-minute-hd",
  "chargedMinutes": 11,
  "storage": "apify",
  "fetchedAt": "2026-09-30T18:04:11Z"
}
```

A video that could not be delivered (never charged):

```json
{
  "resultType": "error",
  "videoId": "xxxxxxxxxxx",
  "url": "https://www.youtube.com/watch?v=xxxxxxxxxxx",
  "input": "https://www.youtube.com/watch?v=xxxxxxxxxxx",
  "error": "VIDEO_UNAVAILABLE",
  "errorMessage": "This video is unavailable",
  "fetchedAt": "2026-09-30T18:04:12Z"
}
```

`resultType` is `file`, `metadata`, `skipped` or `error`. Only `file` rows are charged.

### 💰 Pricing

Pay per event, with no monthly rental and no minimum. The current rate for each event is on the Pricing tab of the Store page, with lower rates on higher Apify plans.

| Event | Charged when |
| --- | --- |
| `audio-minute` | Per minute of audio delivered |
| `video-minute-sd` | Per minute of video delivered at 480p or lower |
| `video-minute-hd` | Per minute of video delivered at 720p |
| `video-minute-fhd` | Per minute of video delivered at 1080p |
| `video-minute-uhd` | Per minute of video delivered at 1440p or 4K |
| `external-storage-megabyte` | Per megabyte of each upload attempted to your own S3, Google Cloud or Azure storage, whether or not your storage accepts it. Not charged for files kept in the run's key-value store by default |

How billing works:

- Minutes are the video's duration rounded up to a whole minute, per file. A 9 minute 20 second video is 10 minutes.
- You are billed for the quality delivered, not the quality requested. Ask for 1080p, get the 720p that is the best on offer, pay the 720p rate.
- The charge happens only after the file is stored and its checksum is computed. Private, removed, age-restricted, blocked and skipped videos are free rows.
- `metadataOnly` rows are free.
- Apify's standard Actor start and dataset item events apply to every run at the platform's lowest rate; they are listed on the Pricing tab.
- No surcharge for difficult videos: the per-minute rate is the whole price of a file kept in the run's storage.
- Delivery to your own storage adds the `external-storage-megabyte` event, on the size of the file, rounded up to a whole megabyte. It is charged for every upload attempted, including one your storage rejects or drops, so check your bucket, key and quota before a large run. The free test write at the start of each run catches most misconfiguration before anything is billed.
- The run stops cleanly at your maximum cost per run, and every link not reached gets a free `NOT_PROCESSED` row.

Example: 20 lecture videos of 45 minutes each as audio is 900 `audio-minute` events.

### 🚀 How to get started

1. Open the Actor: [View on Apify Store](https://apify.com/johnvc/youtube-download-api?fpr=9n7kx3).
2. Paste one or more YouTube links into **YouTube video links**.
3. Choose **Audio only** or **Video with sound**, and a quality.
4. Click **Start**. When the run finishes, open the dataset: each file row has a `fileUrl`.
5. Download the files from those links, or read them from the run's key-value store by `fileKey`.

From code, with the [Apify API client](https://docs.apify.com/api/client/python):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("johnvc/youtube-download-api").call(run_input={
    "videoUrls": ["https://www.youtube.com/watch?v=aqz-KE-bpKQ"],
    "format": "audio",
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["resultType"] == "file":
        print(row["title"], row["fileUrl"], row["sha256"])
    else:
        print(row["input"], row.get("error"), row.get("errorMessage"))
```

Files stay available for as long as the run's storage is retained on your Apify plan. For long-term storage, copy them out or run the Actor from a [saved task](https://docs.apify.com/platform/actors/running/tasks) and move files in the next step of your workflow.

Tips for large files: run memory sets the disk a run has (disk is twice the memory), so raise the memory for 1080p and 4K downloads of long videos, and set the run timeout to match the length of your list.

### 🔌 Use this API from Claude (MCP)

Add the Apify MCP server to your client and this Actor becomes a tool your assistant can call:

```
https://mcp.apify.com/?tools=actors,docs,johnvc/youtube-download-api
```

Works with [Claude Code](https://claude.ai/referral/uIlpa7nPLg) (free trial), [Claude Cowork](https://claude.ai/referral/uIlpa7nPLg) (free trial), Cursor, VS Code, ChatGPT and any other MCP client. Then ask in plain language: "Download the audio of this talk as M4A and give me the file link" or "Which of these ten videos are longer than an hour? Check without downloading."

Setup walkthrough video:

https://www.youtube.com/watch?v=jREWahDGhJM

Full details in the [Apify MCP documentation](https://docs.apify.com/platform/integrations/mcp).

### 💸 Pay per run with crypto (x402)

The YouTube Download API supports agentic payments via the [x402 protocol](https://docs.apify.com/platform/integrations/x402).
AI agents and MCP clients can pay for runs in USDC (on Base) with no Apify account or API token needed:
point your agent at the [Apify MCP server](https://mcp.apify.com/?tools=actors,docs,johnvc/youtube-download-api) and it can
discover, pay for, and run this Actor autonomously. Read the
[Apify x402 announcement](https://apify.com/change-log/pay-for-apify-actors-with-x402?fpr=9n7kx3) for details.

### 🔌 Integrations

- **Schedules.** Save a task with your channel's newest links and run it on a [schedule](https://docs.apify.com/platform/schedules) to keep an archive current.
- **Webhooks.** Add a [webhook](https://docs.apify.com/platform/integrations/webhooks) on run success to hand the file links to your own service the moment they are ready.
- **n8n, Make and Zapier.** Run the Actor from the [Apify integrations](https://docs.apify.com/platform/integrations) for each tool, read the dataset, then pass each `fileUrl` to a storage, transcription or messaging step.
- **Cloud storage.** Set `storageProvider` to deliver straight to Amazon S3, Cloudflare R2, Google Cloud Storage or Azure Blob Storage. For Google Drive or Dropbox, copy each `fileUrl` in the next step of your workflow; `sha256` lets you skip files you already have.
- **A data chain.** Find videos with a search or listing API, read captions with the transcripts API, and download the media here. See Related Tools below.

### 🔗 Related Tools

Building a video or audio pipeline? These tools from the same catalog chain directly into this one:

- [YouTube Transcripts API](https://apify.com/johnvc/YoutubeTranscripts?fpr=9n7kx3): captions, subtitles and transcripts for the same video links, and a channel listing mode that produces the links to download.
- [YouTube Shorts API](https://apify.com/johnvc/youtube-shorts-api?fpr=9n7kx3): list a channel's Shorts with views, likes and dates, then download the ones that matter.
- [Google Short Videos API](https://apify.com/johnvc/google-short-videos-api?fpr=9n7kx3): find the Shorts that Google surfaces for a keyword and pass the YouTube links here.
- [Google News API](https://apify.com/johnvc/GoogleNewsAPI?fpr=9n7kx3): track a story, then collect the video coverage behind it.
- [All Alpha OSINT Actors on Apify](https://apify.com/johnvc?fpr=9n7kx3): the full portfolio.

Alternatives such as [YouTube Video Downloader](https://apify.com/epctex/youtube-video-downloader?fpr=9n7kx3) deliver video only and bill for the full length of a video up front. This API delivers both audio and video, and charges only after a file has been stored.

### 🤖 Ask an AI assistant about this API

Open a ready-to-send prompt about the YouTube Download API in the AI of your choice:

- 💬 [ChatGPT](https://chatgpt.com/?q=How%20do%20I%20use%20the%20YouTube%20Download%20API%20by%20johnvc%20on%20Apify%20%28https://apify.com/johnvc/youtube-download-api?fpr=9n7kx3%29?%20Show%20me%20input%20examples%2C%20output%20fields%2C%20common%20use%20cases%2C%20and%20how%20to%20integrate%20it%20into%20a%20workflow.)
- 🧠 [Claude](https://claude.ai/new?q=How%20do%20I%20use%20the%20YouTube%20Download%20API%20by%20johnvc%20on%20Apify%20%28https://apify.com/johnvc/youtube-download-api?fpr=9n7kx3%29?%20Show%20me%20input%20examples%2C%20output%20fields%2C%20common%20use%20cases%2C%20and%20how%20to%20integrate%20it%20into%20a%20workflow.)
- 🔍 [Perplexity](https://www.perplexity.ai/search?q=How%20do%20I%20use%20the%20YouTube%20Download%20API%20by%20johnvc%20on%20Apify%20%28https://apify.com/johnvc/youtube-download-api?fpr=9n7kx3%29?%20Show%20me%20input%20examples%2C%20output%20fields%2C%20common%20use%20cases%2C%20and%20how%20to%20integrate%20it%20into%20a%20workflow.)
- 🅒 [Copilot](https://copilot.microsoft.com/?q=How%20do%20I%20use%20the%20YouTube%20Download%20API%20by%20johnvc%20on%20Apify%20%28https://apify.com/johnvc/youtube-download-api?fpr=9n7kx3%29?%20Show%20me%20input%20examples%2C%20output%20fields%2C%20common%20use%20cases%2C%20and%20how%20to%20integrate%20it%20into%20a%20workflow.)

### ❓ FAQ

#### How do I download a YouTube video with an API?

Send the video link in `videoUrls` with `format` set to `video` and a `quality`. The run stores the file and returns a row with `fileUrl`, which you fetch like any other file. The same call works from the Apify Console, the REST API, the Python or JavaScript client, and any MCP client.

#### How do I download only the audio from a YouTube video?

Set `format` to `audio` and pick `audioFormat`: `m4a`, `mp3` or `opus`. M4A and Opus come straight from YouTube's own audio streams with no re-encoding. MP3 is converted once after download.

#### Which video qualities are supported?

144p, 240p, 360p, 480p, 720p, 1080p, 1440p and 2160p (4K). `quality` is a ceiling: if a video tops out below it, you get the best quality on offer and pay that quality's rate. Run with `metadataOnly` first to see `availableQualities` for each video.

#### Will the video file have sound?

Yes. Above 360p YouTube serves picture and sound as separate streams. This API always fetches both and combines them into one file, without re-encoding either stream.

#### What is the difference between the `smallest` and `h264` codec options?

`smallest` picks the most efficient stream at your quality, usually AV1 or VP9, which gives a much smaller file and works in modern browsers, VLC, ffmpeg and most AI pipelines. `h264` picks H.264, the format every phone, TV and video editor plays, and is available up to 1080p. Above 1080p YouTube does not offer H.264, so the most efficient codec is delivered and the row's `note` says so.

#### Am I charged for videos that fail?

No. A charge happens only after a file is stored. Private, removed, age-restricted, region-locked, blocked and skipped videos produce a free row with an `error` code and a plain explanation.

#### How do I avoid downloading a video that is hours long by accident?

Set `maxMinutes` or `maxMegabytes`. Both are checked before any media is downloaded, and a video over the limit becomes a free `skipped` row. You can also run `metadataOnly` first to see `durationSeconds` and `estimatedSizeBytes` for your whole list at no cost.

#### How long do the file links work?

For files in the run's storage: as long as that storage is retained, which depends on your Apify plan. For files sent to your own bucket: as long as you keep them. The link points at a record in the run's key-value store, not at a temporary player address, so it does not expire after a few hours. Copy files out if you need them longer.

#### Can I save YouTube downloads directly to Amazon S3?

Yes. Set `storageProvider` to `s3` with your bucket, region and an access key that can put objects. Each file is uploaded straight to the bucket and the row carries its `storageUri` (`s3://bucket/key`). The same setting works for Cloudflare R2, Backblaze B2, Wasabi and other S3-compatible storage with `storageEndpoint`.

#### Can I save files to Google Cloud Storage or Azure?

Yes. For Google Cloud Storage set `storageProvider` to `gcs` and supply an HMAC key pair from the Interoperability tab of Cloud Storage settings. For Azure Blob Storage set it to `azure` and supply a container SAS URL with write permission.

#### Can I save files to Google Drive?

Not directly. Deliver to the run's storage (the default) and copy each `fileUrl` to Drive with a workflow step in n8n, Make or Zapier.

#### Is it safe to put my storage keys in the input?

The key fields are secret inputs: Apify encrypts them, they are used only to sign the upload request, and they never appear in the log or the dataset. Use a key limited to writing objects in one bucket or prefix, and rotate it like any other credential.

#### Can I download Shorts?

Yes. A Shorts link is a normal video link to this API. To list a channel's Shorts first, use the [YouTube Shorts API](https://apify.com/johnvc/youtube-shorts-api?fpr=9n7kx3).

#### Can I download a whole playlist or channel?

Pass the individual video links. To build the list for a channel, use the channel listing mode of the [YouTube Transcripts API](https://apify.com/johnvc/YoutubeTranscripts?fpr=9n7kx3) and feed its links into `videoUrls`.

#### Can I download age-restricted or members-only videos?

Only with access. Paste cookies from your own signed-in session into `cookies` (stored as a secret). Without cookies those videos return a free `AGE_RESTRICTED` or `MEMBERS_ONLY` row.

#### Can I download a live stream?

Not while it is live: the row is `LIVE_NOT_SUPPORTED`. Once the stream has ended and YouTube has published the replay, the same link downloads normally.

#### How do I get a transcript instead of the audio?

If the video has captions, the [YouTube Transcripts API](https://apify.com/johnvc/YoutubeTranscripts?fpr=9n7kx3) returns them directly and is the fastest route. If it has none, download the audio here and run it through your own speech-to-text.

#### Can I use the YouTube Download API through an MCP server?

Yes. Add `https://mcp.apify.com/?tools=actors,docs,johnvc/youtube-download-api` to your MCP client and the Actor becomes a callable tool. See the MCP section above.

#### Is there a free tier?

Free Apify plans can try the API within a monthly allowance. Metadata-only runs are free on every plan.

#### Is it legal to download YouTube videos?

It depends on the content and on what you do with it. Downloading your own uploads, content under an open licence, or content you have permission to use is fine. YouTube's terms restrict downloading other content without permission, and copyright law applies to what you do with any file. You are responsible for the rights to what you download; this API is a tool for lawful uses such as archiving your own channel, research, accessibility and analysis.

#### What happens if YouTube blocks a request?

The API retries on a different path automatically. If a video still cannot be fetched, you get a free `YOUTUBE_BLOCKED` row and can retry later; nothing is charged for it.

### 🌐 About Alpha OSINT

This Actor is part of [Alpha OSINT](https://www.alphaosint.com), toolset of financial and operations data sources and APIs.
See the [YouTube Download API source page](https://www.alphaosint.com/sources/youtube-download-api/) for related tools and use cases.
For support or requests for this actor, please start a ticket [directly on our support page](https://apify.com/johnvc/youtube-download-api/issues/open?fpr=9n7kx3).

Last Updated: 2026.09.30

# Actor input Schema

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

YouTube video links or 11-character video IDs to download. Accepts watch links (youtube.com/watch?v=...), short links (youtu.be/...), Shorts links (youtube.com/shorts/...), embed and live-replay links. Up to 200 per run. Example: \["https://www.youtube.com/watch?v=jNQXAC9IVRw"].

## `format` (type: `string`):

Choose 'audio' for an audio-only file (smallest and cheapest, ideal for transcription and AI pipelines) or 'video' for a video file with sound included. Default: audio.

## `quality` (type: `string`):

Maximum video resolution, used when format is 'video'. If the video is not offered at this quality, the highest available quality below it is delivered and billed at its own rate. Default: 720p.

## `audioFormat` (type: `string`):

File type for audio downloads, used when format is 'audio'. M4A and Opus are delivered without re-encoding; MP3 is converted. Default: m4a.

## `audioQuality` (type: `string`):

'standard' delivers a compact stream that is clear for speech, podcasts, lectures and transcription. 'high' delivers the best audio stream YouTube offers. Default: standard.

## `videoCodec` (type: `string`):

'smallest' delivers the most efficient stream at the chosen quality (AV1 or VP9 when offered), which gives the smallest file. 'h264' delivers H.264 where YouTube offers it (up to 1080p), which plays on every device and editor. Default: smallest.

## `metadataOnly` (type: `boolean`):

Return title, channel, duration, available qualities and estimated file sizes without downloading anything. Free. Use it to check a list before spending. Default: false.

## `maxMinutes` (type: `integer`):

Videos longer than this many minutes are skipped at no charge, before anything is downloaded. Leave empty for no limit. Example: 60.

## `maxMegabytes` (type: `integer`):

Files estimated to be larger than this many megabytes are skipped at no charge, before anything is downloaded. Leave empty for no limit. Example: 500.

## `maxAgeDays` (type: `integer`):

Metadata-only answers and length checks may be served from a cache when the same video was checked within this many days. Media files are always downloaded fresh. Set 0 to always check YouTube. Default: 7.

## `storageProvider` (type: `string`):

Where the downloaded files are delivered. 'apify' (default) keeps them in this run's key-value store. Choose 's3' for Amazon S3 or any S3-compatible storage (Cloudflare R2, Backblaze B2, Wasabi, DigitalOcean Spaces, MinIO), 'gcs' for Google Cloud Storage, or 'azure' for Azure Blob Storage. Files sent to your own storage are not kept in the key-value store.

## `storageBucket` (type: `string`):

For 's3' and 'gcs': the bucket name only, with no slashes. Example: my-video-archive.

## `storagePrefix` (type: `string`):

Optional folder inside the bucket or container. Example: youtube/2026/ stores files as youtube/2026/<videoId>\_<quality>.<ext>.

## `storageRegion` (type: `string`):

For 's3': the bucket's region, for example us-east-1 or eu-west-1. Use 'auto' for Cloudflare R2. Not needed for 'gcs' or 'azure'. Default: us-east-1.

## `storageEndpoint` (type: `string`):

For S3-compatible storage other than Amazon: the https endpoint, for example https://<account>.r2.cloudflarestorage.com for Cloudflare R2 or https://s3.us-west-004.backblazeb2.com for Backblaze B2. Leave empty for Amazon S3 and for Google Cloud Storage.

## `storageAccessKeyId` (type: `string`):

For 's3': an access key ID with permission to write objects to the bucket. For 'gcs': an HMAC access ID from Cloud Storage settings, Interoperability tab. Stored as a secret.

## `storageSecretAccessKey` (type: `string`):

For 's3': the secret access key. For 'gcs': the HMAC secret that belongs to the access ID. Stored as a secret.

## `storageSasUrl` (type: `string`):

For 'azure': the container URL including a SAS token with write permission, in the form https://<account>.blob.core.windows.net/<container>?sv=...\&sig=... Stored as a secret.

## `cookies` (type: `string`):

Optional. Cookies from your own signed-in YouTube session in Netscape cookies.txt format, needed only for age-restricted or members-only videos you have access to. Stored as a secret. Your session, your responsibility: leave empty for normal public videos.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ],
  "format": "audio",
  "quality": "720p",
  "audioFormat": "m4a",
  "audioQuality": "standard",
  "videoCodec": "smallest",
  "metadataOnly": false,
  "maxAgeDays": 7,
  "storageProvider": "apify"
}
```

# Actor output Schema

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

All file, metadata and error rows from this run as JSON. Each file row carries the link to its media file.

## `resultsCsv` (type: `string`):

The same rows as CSV for spreadsheets.

## `files` (type: `string`):

The downloaded audio and video files, listed by key in the run's key-value store.

# 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=jNQXAC9IVRw"
    ],
    "format": "audio"
};

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

# Run the Actor and wait for it to finish
run = client.actor("johnvc/youtube-download-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 '{
  "videoUrls": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ],
  "format": "audio"
}' |
apify call johnvc/youtube-download-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,johnvc/youtube-download-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/ROmcK1i9P5fksADtG/builds/0Z0lsmBJLjPkhTSVe/openapi.json
