# YouTube Shorts Scraper (`apihq/youtube-shorts-scraper`) Actor

Export a YouTube channel's Shorts to JSON by URL, @handle, or channel ID. No YouTube Data API key or quota. One record per Short with title, views, and thumbnail. Pay-per-Short: a channel that can't be resolved or has no Shorts returns a success:false row and is not charged.

- **URL**: https://apify.com/apihq/youtube-shorts-scraper.md
- **Developed by:** [apihq](https://apify.com/apihq) (community)
- **Categories:** Videos, Social media, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.40 / 1,000 shorts

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## YouTube Shorts Scraper

Export a public YouTube channel's Shorts as clean JSON, from a channel URL, @handle, or channel ID. No YouTube Data API key, no quota, no browser.

The contract is simple: **a bad channel never fails your run, and you only pay for Shorts delivered.** Misspell a handle, paste a video URL by mistake, or hit a channel that has never posted a Short, and it comes back as a `success: false` row while the rest of the batch keeps going. Pay-per-result at $0.40 per 1,000 shorts. Failed channels cost $0.

### See one run

Input:

```json
{ "channelUrls": ["@MrBeast", "@totally-wrong-handle"], "maxResults": 5 }
````

What comes back:

- 5 `success: true` Short rows from `@MrBeast`, billed
- 1 `success: false` row, `code: CHANNEL_NOT_FOUND`, for the bad handle, not billed
- Run status: **SUCCEEDED**
- Charged: 5 shorts = $0.002

That is the whole contract. Good input returns billed rows, bad input returns free error rows in the same dataset, and the run still succeeds so one typo never costs you a batch.

### Why this Actor

- **A bad channel never breaks the batch.** Every channel that cannot be resolved, or that has no Shorts, returns a `success: false` record with a machine-readable `code` (`CHANNEL_NOT_FOUND`, `NO_SHORTS`, `VALIDATION_FAILED`, `RESOLVE_TIMEOUT`, `CHANNEL_SHORTS_TIMEOUT`, `DEADLINE_EXCEEDED`). Branch on `code` without parsing English.
- **You pay only for Shorts.** Billing fires on an explicit per-Short event, not on dataset writes, so failure rows sit in your dataset for free. There is no per-run start fee, so a run that returns zero Shorts costs zero.
- **No YouTube Data API key, no quota.** The official YouTube Data API needs a Google key and rations a daily quota per call. This reads public data directly, so there is no Google key to provision and no daily Data API quota to ration. (You still run it with your normal Apify account, like any Actor.)

### Best for

Data and AI workflows that turn channels into Shorts datasets: short-form trend tracking, creator and competitor monitoring, content-enrichment pipelines, and collecting Short video IDs to feed transcript or comment jobs. The failure-free billing and machine-readable error rows matter most when the extraction runs unattended inside a larger pipeline, where one bad channel should never take down the batch. It works fine for one-off manual pulls too.

### Input example

A single channel:

```json
{
  "channelUrl": "https://www.youtube.com/@MrBeast",
  "maxResults": 30
}
```

A batch, mixing URL, @handle, and channel ID forms:

```json
{
  "channelUrls": [
    "https://www.youtube.com/@MrBeast",
    "@mkbhd",
    "UCX6OQ3DkcsbYNE6H8uQQuVA"
  ],
  "maxResults": 100
}
```

`channelUrl` and `channelUrls` are merged and de-duplicated. Up to 50 unique channels run per job. Each channel is walked newest-first up to `maxResults` shorts (default 30).

### Output example

One record per Short. The channel's id and name are copied onto every row so each row stands alone:

```json
{
  "success": true,
  "channel_id": "UCX6OQ3DkcsbYNE6H8uQQuVA",
  "channel_title": "MrBeast",
  "video_id": "LgbyEFILLJI",
  "title": "$1 vs $10,000 Cake",
  "url": "https://www.youtube.com/shorts/LgbyEFILLJI",
  "type": "short",
  "view_count": "2M views",
  "thumbnail_url": "https://i.ytimg.com/vi/LgbyEFILLJI/oardefault.jpg",
  "author": "MrBeast"
}
```

A channel that cannot be resolved lands in the same dataset and is not charged:

```json
{
  "success": false,
  "channel_url": "@totally-wrong-handle",
  "code": "CHANNEL_NOT_FOUND",
  "error": "Could not resolve YouTube channel: @totally-wrong-handle",
  "request_id": "req_911f37d2e55644ff9d9e4a3f",
  "status_code": 404
}
```

Split hits from misses on the `success` field. Quote `request_id` in any support issue and we can trace the exact request.

### What you get

Every Short is one record with `success: true`:

| Field | Type | What it is |
|---|---|---|
| `success` | boolean | `true` for a Short (billed), `false` for a channel that could not be listed (not billed). |
| `channel_id` | string | The `UC...` channel ID the Short belongs to. |
| `channel_title` | string | The channel's display name. |
| `video_id` | string | The 11-character YouTube video ID of the Short. |
| `title` | string | Short title. |
| `url` | string | Canonical Short URL, `https://www.youtube.com/shorts/<video_id>`. |
| `type` | string | Content type. Always `short`. |
| `view_count` | string | View count as a display string (for example `2M views`). May be empty. |
| `thumbnail_url` | string | URL of the largest available thumbnail. |
| `author` | string | Channel author name. |

Channels that could not be listed carry `success: false`, `channel_url`, a machine-readable `code`, a human-readable `error`, the service `request_id`, and the HTTP `status_code`. They are not charged.

### Pricing

Pay-per-result. One charge per Short delivered: `$0.0004` each, which is `$0.40 per 1,000 shorts`. The charge fires only after a Short row lands in your dataset.

- 1,000 delivered shorts cost $0.40.
- A run that hits ten dead handles and returns zero shorts costs $0.
- There is no per-run start fee, so an empty run is genuinely free.

Apify subscriber discounts apply automatically: roughly `$0.32 per 1,000` on the Scale plan and `$0.24 per 1,000` on Business. Platform compute is included in the per-Short price. Cap the maximum spend of a single run from Apify's Run Limits panel; the Actor honors the cap and stops cleanly mid-walk when the budget runs out.

### What this Actor does not do

Honest scope, so you know before you run it:

- **It reads the channel's Shorts tab, not regular videos.** That keeps output focused on Shorts and avoids mixing formats. For long-form uploads, use the [YouTube Channel Scraper](https://apify.com/apihq/youtube-channel-scraper).
- **It returns what the Shorts tab exposes: title, view count, and thumbnail.** The Shorts tab does not carry a duration or a publish date, so those fields are not in the output. Likes, comments, and descriptions require opening each Short and are out of scope here.
- **It returns Shorts newest first.** There is no sort by popularity or oldest.
- **Public channels only.** Private and unavailable channels return `success:false`.

### How to use this Actor

1. Open the Actor in the Apify Console.
2. Set `channelUrl` (single), `channelUrls` (a list), or both. Each accepts a full channel URL, an `@handle`, or a `UC...` channel ID. Up to 50 unique channels run per job.
3. Set `maxResults` to cap how many Shorts to return per channel, newest first. Default is 30.
4. Click Start. Each Short is one `success: true` record. Channels that cannot be listed produce one `success: false` record and do not stop the run. Only Shorts are charged.

The Actor is also callable from the Apify API and every official integration (Make, Zapier, n8n, Slack, webhooks). The API tab in the Console has ready-to-paste JavaScript, Python, and curl snippets.

### Reliability

**A bad channel never fails the batch.** A misspelled handle, a video URL pasted by mistake, or a channel with no Shorts becomes a `success: false` record with a specific `code`. The run keeps going and finishes successfully.

**You never pay for a failure.** Billing fires on an explicit per-Short charge event, not on dataset writes, so `success: false` records are free. There is no per-run start fee either.

**Hard 30-second deadline per page request.** Each page of a channel is fetched under a 30-second deadline. If YouTube or the proxy network stalls, that channel returns a `504` with `code: DEADLINE_EXCEEDED` as a `success: false` record instead of hanging your run.

### FAQ

**Do I need a YouTube Data API key?**

No. The Actor reads YouTube's public data directly and does not consume Google API quota.

**What channel formats are accepted?**

A full channel URL (`https://www.youtube.com/@MrBeast` or `.../channel/UC...`), an `@handle`, or a bare `UC...` channel ID. A video URL or unrecognizable input comes back as a `success: false` record with `code: VALIDATION_FAILED`, not a rejected run.

**How many Shorts do I get per channel?**

Up to `maxResults`, newest first. The Actor walks the channel's Shorts tab page by page until it reaches `maxResults` or the channel runs out. Set `maxResults` higher to go deeper.

**Why is there no duration or publish date?**

The YouTube Shorts tab does not expose them. It gives the title, view count, and thumbnail per Short, and that is what this Actor returns. Pulling a duration or exact date would mean opening every Short individually, which is a different, slower, more expensive job.

**Does this include regular videos?**

No. This Actor lists a channel's Shorts. For long-form uploads, use the [YouTube Channel Scraper](https://apify.com/apihq/youtube-channel-scraper).

**Can I get transcripts too?**

Not from this Actor. Use it to collect a channel's Short video IDs, then run the [YouTube Transcript Scraper](https://apify.com/apihq/youtube-transcript-scraper) on those IDs to pull captions.

**Can I use this Actor from my own code?**

Yes. Use the Apify API or one of the official SDKs (Node.js: `apify-client`, Python: `apify-client`). The Console shows ready-to-paste code samples on the API tab.

**How does billing know a channel failed?**

Billing fires on an explicit per-Short charge event, not on dataset writes. The Actor only fires it when a Short is delivered, so `success: false` records sit in your dataset for free. You get every result in one place and still branch on `success` and `code`, with a `request_id` for support correlation.

### Found a bug or want a feature?

Open an issue on this Actor's Issues tab and include the `request_id` from any error record you saw. We respond within one business day.

# Actor input Schema

## `channelUrl` (type: `string`):

A single YouTube channel. Accepts a full channel URL (https://www.youtube.com/@MrBeast or /channel/UC...), an @handle, or a UC... channel ID. A channel that can't be resolved comes back as a success:false record (code CHANNEL\_NOT\_FOUND), not a rejected run.

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

List of channel URLs, @handles, or channel IDs. Merged with channelUrl and de-duplicated; up to 50 unique channels are processed per run. A channel that can't be resolved or has no Shorts comes back as a success:false record, so one bad channel never blocks the batch.

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

Maximum number of Shorts to return per channel (newest first). The Actor walks the channel's Shorts tab in pages until it reaches this many shorts or the channel is exhausted.

## Actor input object example

```json
{
  "channelUrl": "https://www.youtube.com/@MrBeast",
  "maxResults": 30
}
```

# Actor output Schema

## `shorts` (type: `string`):

One record per Short. success:true carries the Short and channel fields; success:false carries the error code and message for a channel that failed.

# 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 = {
    "channelUrl": "https://www.youtube.com/@MrBeast",
    "maxResults": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("apihq/youtube-shorts-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "channelUrl": "https://www.youtube.com/@MrBeast",
    "maxResults": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("apihq/youtube-shorts-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "channelUrl": "https://www.youtube.com/@MrBeast",
  "maxResults": 30
}' |
apify call apihq/youtube-shorts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=apihq/youtube-shorts-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "YouTube Shorts Scraper",
        "description": "Export a YouTube channel's Shorts to JSON by URL, @handle, or channel ID. No YouTube Data API key or quota. One record per Short with title, views, and thumbnail. Pay-per-Short: a channel that can't be resolved or has no Shorts returns a success:false row and is not charged.",
        "version": "0.1",
        "x-build-id": "bCzuUc1aptrUdhngh"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/apihq~youtube-shorts-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-apihq-youtube-shorts-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/apihq~youtube-shorts-scraper/runs": {
            "post": {
                "operationId": "runs-sync-apihq-youtube-shorts-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/apihq~youtube-shorts-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-apihq-youtube-shorts-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "channelUrl": {
                        "title": "Channel URL, @handle, or ID",
                        "type": "string",
                        "description": "A single YouTube channel. Accepts a full channel URL (https://www.youtube.com/@MrBeast or /channel/UC...), an @handle, or a UC... channel ID. A channel that can't be resolved comes back as a success:false record (code CHANNEL_NOT_FOUND), not a rejected run."
                    },
                    "channelUrls": {
                        "title": "Multiple channels",
                        "type": "array",
                        "description": "List of channel URLs, @handles, or channel IDs. Merged with channelUrl and de-duplicated; up to 50 unique channels are processed per run. A channel that can't be resolved or has no Shorts comes back as a success:false record, so one bad channel never blocks the batch.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxResults": {
                        "title": "Max shorts per channel",
                        "type": "integer",
                        "description": "Maximum number of Shorts to return per channel (newest first). The Actor walks the channel's Shorts tab in pages until it reaches this many shorts or the channel is exhausted."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
