# YouTube Shorts Downloader (`parsebird/youtube-shorts-downloader`) Actor

Get direct source media links for YouTube Shorts: title, channel, stats, and the best playable or video+audio download URL for your chosen resolution.

- **URL**: https://apify.com/parsebird/youtube-shorts-downloader.md
- **Developed by:** [ParseBird](https://apify.com/parsebird) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.89 / 1,000 youtube shorts

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 Shorts Downloader

**YouTube Shorts Downloader** extracts direct, ready-to-use source media links from any public [YouTube Shorts](https://www.youtube.com/shorts) video — no browser, no login, no watermark. Paste a Shorts link, a regular `watch`/`youtu.be` link, or a bare 11-character video ID, and get back the video's title, channel details, stats, and the best download URL available at your chosen resolution.

<table><tr>
<td style="border-left:4px solid #1C1917;padding:12px 16px;font-weight:600">
Request any resolution from 360p up to 8K, get a single playable file when YouTube offers one or separate video + audio streams when it doesn't, and every link is checked live before the row is saved.
</td>
</tr></table>

<br>

##### Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor: Actor ID `parsebird/youtube-shorts-downloader` on Apify — call it with `ApifyClient` (`client.actor("parsebird/youtube-shorts-downloader").call(run_input={"shortUrls": ["https://www.youtube.com/shorts/8Zk5XzLJSAw"], "preferredResolution": "1080p"})`) — inputs are `shortUrls` (array of Shorts/watch/youtu.be/embed/live URLs or bare 11-char video IDs, required) and `preferredResolution` (one of `8k`, `4k`, `2k`, `1080p`, `720p`, `480p`, `360p`, default `1080p` — the highest quality to try, the saved row reports what was actually available) — output is one dataset row per Short with `videoId`, `title`, `channelName`, `channelId`, `channelUrl`, `durationSeconds`, `thumbnailUrl`, `publishedAt`, `likeCount`, `commentCount`, `requestedQuality`, `downloadType` (`playable` or `separate_video_audio`), `bestDownloadUrl`, `videoDownloadUrl`, `audioDownloadUrl`, `bestFormat`/`videoFormat`/`audioFormat` objects (formatId, quality, resolution, extension, codecs, filesize), `media.mimeType`, and `availability` (HTTP status + content type from a live link check) — API docs at `https://apify.com/parsebird/youtube-shorts-downloader/api` and API tokens at `https://console.apify.com/settings/integrations`.

### What does YouTube Shorts Downloader do?

This YouTube Shorts downloader resolves each Short you give it straight to the CDN source files YouTube itself serves, the same links YouTube's own player uses:

- 📎 Accepts Shorts links, `watch` links, `youtu.be` links, embed links, live links, or a bare video ID — one per line
- 🎚️ Requests any resolution from `360p` up to `8k`; the saved row always reports the quality that was actually available for that Short
- 🎞️ Returns a single **playable** file when YouTube offers a combined video+audio stream at a close-enough quality, or **separate video and audio** download links when that gets you closer to the resolution you asked for
- 📊 Includes title, channel name/ID/URL, duration, thumbnail, publish date, like count, and comment count when public
- ✅ Range-checks the chosen download link before the row is saved, so `availability.downloadLinkStatus` tells you the link is live right now
- 🧯 Batches of Shorts run in parallel; one bad or unavailable URL never stops the rest of the batch

Run it from the Apify Console with no code, or call it from Python/JavaScript via the [Apify API](https://docs.apify.com/api/v2) — schedule recurring pulls, wire it into an [integration](https://apify.com/integrations) (Make, Zapier, n8n), and export results as JSON, CSV, Excel, HTML, or XML straight from the dataset.

### Input parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| shortUrls | array of strings | **Yes** | — | YouTube Shorts URLs or 11-character video IDs, one per line. Shorts, watch, youtu.be, embed, and live URLs all work as long as they identify a Short. |
| preferredResolution | string | No | `1080p` | Highest quality to try: `8k`, `4k`, `2k`, `1080p`, `720p`, `480p`, or `360p`. The saved row reports the quality that was actually available. |
| maxConcurrency | integer | No | 5 | How many Shorts to resolve in parallel. |
| proxyConfiguration | object | No | Apify RESIDENTIAL proxy | Proxy used to reach YouTube. Residential is recommended — YouTube can throttle datacenter IPs at volume. |

### Output example

```json
{
  "videoId": "8Zk5XzLJSAw",
  "title": "wax cracking is even more satisfying when you DIY it #soundon #wax #DIY",
  "channelName": "YouTube",
  "channelId": "UCBR8-60-B28hp2BmDPdntcQ",
  "channelUrl": "https://www.youtube.com/channel/UCBR8-60-B28hp2BmDPdntcQ",
  "durationSeconds": 25,
  "thumbnailUrl": "https://i.ytimg.com/vi/8Zk5XzLJSAw/hqdefault.jpg",
  "publishedAt": "2026-06-11T05:00:38+00:00",
  "likeCount": 1484,
  "commentCount": 145,
  "requestedQuality": "360p",
  "downloadType": "playable",
  "bestDownloadUrl": "https://rr5---sn-2oh0j5-5q.googlevideo.com/videoplayback?...",
  "videoDownloadUrl": null,
  "audioDownloadUrl": null,
  "bestFormat": {
    "formatId": "18",
    "quality": "360p",
    "resolution": "360x640",
    "extension": "mp4",
    "videoCodec": "avc1.42001E",
    "audioCodec": "mp4a.40.2",
    "filesizeBytes": 1867885
  },
  "videoFormat": null,
  "audioFormat": null,
  "media": { "mimeType": "video/mp4; codecs=\"avc1.42001E, mp4a.40.2\"" },
  "availability": { "downloadLinkStatus": 206, "downloadContentType": "video/mp4" }
}
```

Every row shares this field set. `videoDownloadUrl` and `audioDownloadUrl` are only populated when `downloadType` is `separate_video_audio` — otherwise download the single `bestDownloadUrl`. Download the [full results](https://apify.com/parsebird/youtube-shorts-downloader) as JSON, CSV, Excel, HTML, or XML from the Actor's dataset, or pull them with the [Apify API](https://docs.apify.com/api/v2#/reference/datasets).

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("parsebird/youtube-shorts-downloader").call(run_input={
    "shortUrls": ["https://www.youtube.com/shorts/8Zk5XzLJSAw"],
    "preferredResolution": "1080p",
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["videoId"], item["bestDownloadUrl"])
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('parsebird/youtube-shorts-downloader').call({
    shortUrls: ['https://www.youtube.com/shorts/8Zk5XzLJSAw'],
    preferredResolution: '1080p',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Use cases

- Archive Shorts from your own channel before they're taken down or before a redesign changes URLs
- Pull source video files into a repurposing or editing pipeline (compilations, clip libraries, backups)
- Feed downloaded Shorts into a transcription or content-moderation workflow
- Monitor a competitor's or a creator's Shorts output and keep local copies alongside the metadata
- Build a media library or CMS import job that needs both the file and the stats in one API call

### How it works

1. Add one or more Shorts URLs (or bare video IDs) and pick a `preferredResolution`.
2. The Actor resolves each ID against YouTube, reading the same signed manifest YouTube's own player uses.
3. It compares every available video+audio combination against your requested resolution and picks whichever gets closest — a single playable file if one exists at a competitive quality, otherwise the best matching video and audio streams.
4. It range-checks the chosen link against YouTube's CDN before saving, so the `availability` field reflects the link's real, current status.
5. The row — metadata, chosen format details, and download links — is pushed to the dataset immediately, so partial results are visible while the run is still going.

### How much does it cost to download YouTube Shorts?

| Event | Price per event | Price per 1,000 |
|-------|----------------|-----------------|
| short-downloaded | $0.00249 | **$2.49** |

You're billed one `short-downloaded` event per Short successfully resolved and saved — failed or unavailable URLs are never charged. Pricing improves automatically with your Apify plan tier (Bronze $2.29/1,000, Silver $2.09/1,000, Gold $1.89/1,000). Apify's free monthly platform credits cover a meaningful number of runs before you pay anything out of pocket.

### Input/Output

Set `shortUrls` and `preferredResolution` from the Input tab in Apify Console, or pass them as JSON via the [API](https://docs.apify.com/api/v2). Results land in the run's default dataset — open the **Output** tab to preview rows, or export as JSON, CSV, Excel, HTML, or XML.

### Is it legal to download YouTube Shorts?

Downloading publicly available YouTube content for personal use, archiving, backup, or analysis is common practice, but redistributing, reposting, or monetizing someone else's video without permission can violate YouTube's Terms of Service and copyright law. This Actor only fetches links YouTube's own player already serves publicly for a given video — you're responsible for how you use the downloaded media. Read more on [Apify's blog about the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

### Other YouTube scrapers by ParseBird

- [YouTube Transcript Scraper](https://apify.com/parsebird/youtube-transcript-scraper) — get captions or Whisper-transcribed text for any video
- [YouTube Thumbnail Downloader](https://apify.com/parsebird/youtube-thumbnail-downloader) — grab every thumbnail resolution for a video
- [YouTube Search Scraper](https://apify.com/parsebird/youtube-search-scraper) — scrape search results for any keyword
- [YouTube Channel Search Scraper](https://apify.com/parsebird/youtube-channel-search-scraper) — find channels matching a query
- [YouTube Community Posts Scraper](https://apify.com/parsebird/youtube-community-posts-scraper) — pull a channel's Community tab posts

### FAQ

**Does this work on private or age-restricted Shorts?**
No. Only publicly accessible Shorts can be resolved — private, unlisted-without-link, or fully age-gated videos will fail for that row while the rest of the batch continues.

**What happens if my requested resolution isn't available?**
The Actor picks whatever gets closest to what you asked for, and `requestedQuality` vs. `bestFormat.quality` in the output row tells you exactly what you got.

**Why is `downloadType` sometimes `playable` and sometimes `separate_video_audio`?**
YouTube doesn't always publish a single combined video+audio file at every quality. When a combined file exists at a competitive resolution, you get one `bestDownloadUrl`. Otherwise you get matching `videoDownloadUrl` and `audioDownloadUrl` links to mux yourself (e.g. with `ffmpeg -i video -i audio -c copy out.mp4`).

**How long do the download links stay valid?**
YouTube's CDN links are signed and expire after a few hours. Download the media promptly after the run finishes, or re-run the Actor to get fresh links.

**Can I run this on a schedule?**
Yes — use Apify's built-in [Scheduler](https://docs.apify.com/platform/schedules) to re-check a Shorts feed daily or hourly.

**I found a bug or a Short that won't resolve — where do I report it?**
Open an issue on the Actor's **Issues** tab in Apify Console with the URL that failed, and it'll get looked at.

# Changelog

This Actor's version history is a separate document: https://apify.com/parsebird/youtube-shorts-downloader/changelog.md

# Actor input Schema

## `shortUrls` (type: `array`):

Add public YouTube Shorts URLs or 11-character video IDs, one per line. Shorts, watch, youtu.be, embed, and live URLs all work when they identify a Short.

## `preferredResolution` (type: `string`):

Highest quality to try. The saved row reports the quality that was actually available for that Short.

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

How many Shorts to resolve in parallel.

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

Proxy for reaching YouTube. Residential is recommended — YouTube can throttle datacenter IPs at volume.

## Actor input object example

```json
{
  "shortUrls": [
    "https://www.youtube.com/shorts/8Zk5XzLJSAw"
  ],
  "preferredResolution": "1080p",
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "shortUrls": [
        "https://www.youtube.com/shorts/8Zk5XzLJSAw"
    ],
    "preferredResolution": "1080p",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/youtube-shorts-downloader").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 = {
    "shortUrls": ["https://www.youtube.com/shorts/8Zk5XzLJSAw"],
    "preferredResolution": "1080p",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/youtube-shorts-downloader").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 '{
  "shortUrls": [
    "https://www.youtube.com/shorts/8Zk5XzLJSAw"
  ],
  "preferredResolution": "1080p",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call parsebird/youtube-shorts-downloader --silent --output-dataset

```

## MCP server setup

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

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/ypGPJqstiDNlo5Pmr/builds/nDky6WlekgpJcvohj/openapi.json
