# YouTube Shorts \[Only $0.45💰] Scraper (`memo23/youtube-shorts-scraper`) Actor

$0.45💰 Unlock YouTube Shorts analytics! Extract views, likes, and engagement data from any channel. Get complete channel stats: 919M+ views tracking, subscriber counts, join dates, locations. Bulk scrape with sorting options. Perfect for content creators, marketers, and researchers analyzing trends

- **URL**: https://apify.com/memo23/youtube-shorts-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Social media, Videos, Lead generation
- **Stats:** 64 total users, 16 monthly users, 98.4% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.45 / 1,000 results

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 web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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 - Extract Shorts, Channel Data & Engagement Metrics

Unlock the power of YouTube Shorts analytics with our comprehensive Shorts Scraper. Extract detailed metadata, engagement metrics, and complete channel information from any YouTube Shorts channel or individual short video.

### Overview

This actor allows you to scrape detailed information about YouTube Shorts, including title, view count, likes, duration, thumbnail URLs, and comprehensive channel metadata. **Extract all shorts from any channel with complete engagement data and channel statistics.** It provides valuable insights for content creators, marketers, and researchers looking to analyze Shorts performance, channel growth, and audience engagement.

### Features

- **Complete Shorts Information:** Extract comprehensive metadata about each short video including title, views, likes, duration, and upload date.
- **Channel Analytics:** Get detailed channel information including total subscribers, total views, total videos, join date, and location.
- **Engagement Metrics:** Capture view counts, like counts, and engagement statistics for every short.
- **Channel Branding Assets:** Extract channel avatar URLs, banner images, and profile information.
- **Bulk Scraping:** Scrape all shorts from a channel or specify a maximum number of items.
- **Sorting Options:** Sort shorts by NEWEST, POPULAR, or OLDEST to get exactly the content you need.
- **Hashtag Extraction:** Automatically extract all hashtags from short descriptions.
- **Transcripts (TXT / SRT / VTT):** Optional `includeTranscript` adds plain text, timed segments, and ready-to-save SubRip + WebVTT subtitle files for every Short.
- **Real Comment Counts:** `commentsCount` is read from the Shorts page for every video.
- **Music / Sound Credits:** Song title, artist, and album for Shorts that use licensed audio (`music` field).
- **Computed Engagement Metrics:** `engagementRate` (likes/views), `viewsPerDay`, and `daysSincePublished` on every row — viral-score analysis without extra math.
- **Region & Language Targeting:** Optional `regionCode` (gl) and `contentLanguage` (hl) to localize listings and metadata.
- **Error Reporting:** Failed sources (missing channel, empty hashtag, blocked page…) push structured error items to the dataset instead of failing silently — integration-friendly (Make, Zapier, n8n).
- **Customizable:** Flexible configuration options including max items, sorting, and concurrency settings.
- **Proxy Support:** Built-in proxy configuration to enhance scraping reliability and avoid blocks.
- **Scrape 40+ critical data points from any YouTube Short, including:**

#### 🎯 Core Metrics

- View counts per short
- Like counts (real-time engagement data)
- Engagement rate, views per day, days since published (computed)
- Music/sound credits (song, artist, album)
- Video duration and upload date
- Short type and format information

#### 📊 Channel Analytics

- Total subscriber count
- Total channel views (all-time)
- Total videos published
- Channel join date and location
- Channel verification status

#### 📜 Content Details

- **Complete Short Metadata**
  - Title and translated title support
  - Thumbnail URLs (high quality)
  - Hashtag extraction
  - Description and links
- **Channel Information:**
  - Channel description
  - Channel username and ID
  - Avatar and banner URLs
  - Age restriction status

#### 🛠 Technical Features

- Automatic resolution of:
  - Channel URLs (handle, @username, or channel ID)
  - Individual short URLs
  - Bulk channel shorts extraction

### How to Use

1. **Set Up:** Ensure you have an Apify account and access to the Apify platform.
2. **Configure Input:** Set the YouTube channel URL(s) or individual short URL(s) you want to scrape (see Input Configuration section).
3. **Adjust Parameters:** (Optional) Configure maxItems, sorting order (NEWEST/POPULAR/OLDEST), concurrency, and proxy settings.
4. **Run the Scraper:** Execute the scraper on the Apify platform.
5. **Data Collection:** The scraper will output detailed data about each short including views, likes, and complete channel metadata.

### Input Configuration

Here's an example of how to set up the input for the YouTube Shorts Scraper:

```json
{
    "startUrls": [
        "rainbowicecream9780",
        "https://www.youtube.com/@channelname/shorts"
    ],
    "searchQueries": ["web scraping", "apify tutorial"],
    "hashtags": ["shorts", "coding"],
    "shortUrls": [
        "https://www.youtube.com/shorts/HKs9NvVRi5s"
    ],
    "maxItems": 50,
    "maxResultsShorts": 100,
    "sortChannelShortsBy": "NEWEST",
    "oldestPostDate": "2026-01-01",
    "regionCode": "US",
    "contentLanguage": "en",
    "maxConcurrency": 10,
    "minConcurrency": 1,
    "maxRequestRetries": 10,
    "includeTranscript": false,
    "downloadVideo": false,
    "language": "default",
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US"
    }
}
```

#### Input Fields Explanation

You need **at least one** source: `startUrls`, `searchQueries`, `hashtags`, and/or `shortUrls` (or deprecated `channels` merged into `startUrls`).

##### Data sources

| Field | Type | Description |
|--------|------|-------------|
| `startUrls` | `string[]` | All **channel** scraping in one list: handles (`"name"` or `"@name"`), full Shorts tab URLs (`https://www.youtube.com/@handle/shorts`, `m.youtube.com`, `/channel/UC…/shorts`, `/c/…/shorts`), or scheme-less `youtube.com/…`. Optional if you use search, hashtags, or direct Short URLs. |
| `searchQueries` | `string[]` | Keywords for **YouTube Shorts search** (each query is run separately; same detail pipeline as channels). |
| `hashtags` | `string[]` | Hashtag hub pages: enter `apify` or `#apify` per row → `/hashtag/{tag}/shorts`. |
| `shortUrls` | `string[]` | **Direct Shorts** only: `youtube.com/shorts/VIDEO_ID`, `watch?v=`, `youtu.be/…`. Each unique video id is scraped once; counts toward `maxItems`. |
| `channels` | `string[]` | **Deprecated.** Not shown in the Apify Console input form; still accepted via API and merged into `startUrls`. Use `startUrls` only. |

##### Limits and filtering

| Field | Type | Description |
|--------|------|-------------|
| `maxItems` | `number` | Global cap: maximum total Shorts to scrape (default `30` if omitted; free users are capped at `30`). |
| `maxResultsShorts` | `number` | Per-source cap: max Shorts per **channel**, per **search query**, or per **hashtag** (in addition to `maxItems`). |
| `sortChannelShortsBy` | `string` | Channel Shorts tab order: `"NEWEST"` (default), `"POPULAR"`, or `"OLDEST"` (uses YouTube sort chips for Popular/Oldest). |
| `oldestPostDate` | `string` | Only keep Shorts published on or after this threshold. **Absolute:** `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM[:SS]Z` (UTC, inclusive). **Relative:** e.g. `30 minutes`, `2 hours`, `7 days`, `2 weeks`, `3 months`, `1 year`. Empty = disabled. |

##### Localization

| Field | Type | Description |
|--------|------|-------------|
| `regionCode` | `string` | ISO 3166-1 alpha-2 country for YouTube `gl` (e.g. `US`, `DE`, `JP`). Applied to listing pages and InnerTube requests. Empty = proxy IP default. |
| `contentLanguage` | `string` | Interface language for YouTube `hl` (e.g. `en`, `de`, `pt-BR`). Affects localized metadata text. Empty = default. |

##### Crawler and reliability

| Field | Type | Default (input schema) | Description |
|--------|------|-------------------------|-------------|
| `maxConcurrency` | `number` | `10` | Max pages processed in parallel. |
| `minConcurrency` | `number` | `1` | Min concurrent pages. |
| `maxRequestRetries` | `number` | `10` | Retries per failed request before giving up. |

If you pass a **minimal** JSON body without `maxRequestRetries`, the actor code currently falls back to **`3`**; the Apify Console usually prefills **`10`** from the schema.

##### Proxy

| Field | Type | Description |
|--------|------|-------------|
| `proxy` | `object` | Standard Apify proxy settings: e.g. `useApifyProxy`, `apifyProxyGroups` (e.g. `RESIDENTIAL`), `apifyProxyCountry`, or custom `proxyUrls`. See [Apify proxy docs](https://docs.apify.com/platform/proxy). |

#### Transcripts

| Field | Type | Default | Description |
|--------|------|---------|-------------|
| `includeTranscript` | `boolean` | `false` | Fetch the transcript for each Short and add a `subtitles` object to the output: plain text, timed segments, plus ready-to-save **SRT** and **WebVTT** strings. |
| `language` | `string` | `"default"` | Preferred transcript language code (e.g. `en`, `de`, `es`). Falls back to English / YouTube's default track when unavailable. |

##### Extra fields (API / JSON input only)

These are **not** in the current Apify `input_schema.json` but are read by the actor when present in JSON (local runs or API):

| Field | Type | Default | Description |
|--------|------|---------|-------------|
| `downloadVideo` | `boolean` | `false` | Download video to Key-Value Store (heavier run). |

### Output Structure

The output data includes detailed information about each YouTube Short along with comprehensive channel metadata. Here's a complete sample of the structure:

```json
[
    {
        "title": "ASRM Satisfying sounds #asmr #music #funny #animation #shortvideo #shorts #satisfying",
        "translatedTitle": null,
        "type": "shorts",
        "id": "HKs9NvVRi5s",
        "url": "https://www.youtube.com/shorts/HKs9NvVRi5s",
        "thumbnailUrl": "https://i.ytimg.com/vi/HKs9NvVRi5s/hq2.jpg?sqp=-oaymwFACKgBEF5IWvKriqkDMwgBFQAAiEIYANgBAeIBCggYEAIYBjgBQAHwAQH4AbYIgAKAD4oCDAgAEAEYciBDKDkwDw==&rs=AOn4CLBaOHct_7Ob2lwOZzME6tCzLeyl5g",
        "viewCount": 173323,
        "date": "2025-08-04T03:00:33-07:00",
        "likes": 1251,
        "location": null,
        "channelName": "Coco Creator Rainbow",
        "channelUrl": "https://www.youtube.com/channel/UC3N1VbltR6aREupzvJ8y-sw",
        "channelUsername": "rainbowicecream9780",
        "collaborators": null,
        "channelId": "UC3N1VbltR6aREupzvJ8y-sw",
        "channelDescription": "Thank you so much! I appreciate you all watching the videos.\n",
        "channelJoinedDate": "Aug 9, 2021",
        "channelDescriptionLinks": [],
        "channelLocation": "United States",
        "channelAvatarUrl": "https://yt3.googleusercontent.com/nVSr8lanf5UPU4Mc6oWOmKWqQ8VoFceHcQsM5sW63ZPp4r1S6M6pHr4stNOMGyknf1ig1Wjh3A=s160-c-k-c0x00ffffff-no-rj",
        "channelBannerUrl": "https://yt3.googleusercontent.com/Wg27ZtirmK5sH4Bx7atk4CugZubFCTwsXZsKdITtWPT6aTiikJgl26heFNxnM16UJi0-qnlUxQ=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
        "channelTotalVideos": 230,
        "channelTotalViews": 919280766,
        "numberOfSubscribers": 1380000,
        "isChannelVerified": false,
        "inputChannelUrl": "https://www.youtube.com/@rainbowicecream9780/shorts",
        "isAgeRestricted": false,
        "aboutChannelInfo": {
            "channelName": "Coco Creator Rainbow",
            "channelId": "UC3N1VbltR6aREupzvJ8y-sw",
            "channelUrl": "https://www.youtube.com/channel/UC3N1VbltR6aREupzvJ8y-sw",
            "channelUsername": "rainbowicecream9780",
            "numberOfSubscribers": 1380000,
            "channelTotalViews": 919280766,
            "channelTotalVideos": 230,
            "channelAvatarUrl": "https://yt3.googleusercontent.com/nVSr8lanf5UPU4Mc6oWOmKWqQ8VoFceHcQsM5sW63ZPp4r1S6M6pHr4stNOMGyknf1ig1Wjh3A=s160-c-k-c0x00ffffff-no-rj",
            "channelBannerUrl": "https://yt3.googleusercontent.com/Wg27ZtirmK5sH4Bx7atk4CugZubFCTwsXZsKdITtWPT6aTiikJgl26heFNxnM16UJi0-qnlUxQ=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
            "isChannelVerified": false,
            "channelDescription": "Thank you so much! I appreciate you all watching the videos.\n",
            "channelJoinedDate": "Aug 9, 2021",
            "channelLocation": "United States",
            "isAgeRestricted": false,
            "inputChannelUrl": "https://www.youtube.com/@rainbowicecream9780/shorts"
        },
        "duration": "00:00:51",
        "commentsCount": 0,
        "text": null,
        "translatedText": null,
        "descriptionLinks": null,
        "subtitles": null,
        "order": 0,
        "commentsTurnedOff": false,
        "fromYTUrl": "https://www.youtube.com/@rainbowicecream9780/shorts",
        "isMonetized": null,
        "hashtags": [],
        "formats": [],
        "isMembersOnly": false,
        "input": "https://www.youtube.com/@rainbowicecream9780/shorts",
        "fromChannelListPage": "shorts",
        "isPaidContent": false,
        "music": {
            "song": "Night",
            "artist": "Kilo G",
            "album": "Mercy",
            "thumbnailUrl": "https://yt3.googleusercontent.com/28bcrPUQOxi6GimxKsf…",
            "source": "videoAttribute"
        },
        "engagementRate": 0.007218,
        "viewsPerDay": 561.26,
        "daysSincePublished": 310
    }
]
```

#### Output Fields Explanation

Each short in the output contains the following fields:

##### 🎬 **Video Information**

- `title` *(string)*: The title of the YouTube Short as it appears on YouTube
- `translatedTitle` *(string|null)*: Translated title if translation is enabled, otherwise null
- `type` *(string)*: Content type, always "shorts" for YouTube Shorts
- `id` *(string)*: Unique YouTube video ID for the short
- `url` *(string)*: Full URL to access the short on YouTube
- `thumbnailUrl` *(string)*: High-quality thumbnail image URL for the short
- `duration` *(string)*: Video duration in HH:MM:SS format (e.g., "00:00:51")
- `date` *(string)*: Upload/publish date in ISO 8601 format
- `order` *(number)*: Sequential order number of the short in the result set

##### 📊 **Engagement Metrics**

- `viewCount` *(number)*: Total number of views the short has received
- `likes` *(number)*: Total number of likes on the short
- `commentsCount` *(number)*: Total number of comments on the short (read from the Shorts page; `0` when none are visible)
- `commentsTurnedOff` *(boolean)*: Whether comments are disabled for this short
- `engagementRate` *(number|null)*: Likes ÷ views ratio (0–1, 6 decimals); `null` when views are unknown
- `viewsPerDay` *(number|null)*: Views ÷ days since publish — spot virality at a glance
- `daysSincePublished` *(number|null)*: Whole days since the publish date

##### 🎵 **Music / Sound**

- `music` *(object|null)*: Sound credits when the Short uses licensed audio, otherwise `null` (original audio)
  - `song` *(string|null)*: Track title
  - `artist` *(string|null)*: Artist name
  - `album` *(string|null)*: Album name when available
  - `thumbnailUrl` *(string|null)*: Cover art URL
  - `source` *(string)*: Which YouTube data shape supplied the credits (`musicSection` or `videoAttribute`)

##### 📺 **Channel Information**

- `channelName` *(string)*: Display name of the channel that posted the short
- `channelUrl` *(string)*: Full URL to the channel page
- `channelUsername` *(string)*: Channel username/handle (without @ symbol)
- `channelId` *(string)*: Unique YouTube channel ID
- `channelDescription` *(string)*: Channel's about/description text
- `channelJoinedDate` *(string)*: Date when the channel was created (e.g., "Aug 9, 2021")
- `channelLocation` *(string)*: Geographic location of the channel
- `channelAvatarUrl` *(string)*: URL to the channel's profile picture/avatar
- `channelBannerUrl` *(string)*: URL to the channel's banner image
- `channelDescriptionLinks` *(array)*: Array of links from the channel description

##### 📈 **Channel Statistics**

- `numberOfSubscribers` *(number)*: Total subscriber count for the channel
- `channelTotalViews` *(number)*: Total all-time views across all channel videos
- `channelTotalVideos` *(number)*: Total number of videos published on the channel
- `isChannelVerified` *(boolean)*: Whether the channel has YouTube verification badge

##### 🔍 **Additional Metadata**

- `location` *(string|null)*: Geographic location tag for the video (if set)
- `collaborators` *(array|null)*: List of collaborators on the video (if any)
- `isAgeRestricted` *(boolean)*: Whether the content is age-restricted
- `isMonetized` *(boolean|null)*: Monetization status of the video
- `isMembersOnly` *(boolean)*: Whether the content is restricted to channel members
- `isPaidContent` *(boolean)*: Whether this is paid promotional content
- `hashtags` *(array)*: Array of hashtags extracted from the video title/description
- `text` *(string|null)*: Video description text
- `translatedText` *(string|null)*: Translated description if translation is enabled
- `descriptionLinks` *(array|null)*: Links extracted from video description
- `subtitles` *(object|null)*: Transcript data when `includeTranscript` is enabled and a transcript exists:
  - `plainText` *(string)*: Full transcript as one string
  - `segments` *(array)*: Timed segments `{ text, startMs, endMs, startTimeText }`
  - `srt` *(string)*: Ready-to-save **SubRip (.srt)** file content
  - `vtt` *(string)*: Ready-to-save **WebVTT (.vtt)** file content
  - `source` *(string)*: Transcript provider used
- `formats` *(array)*: Available video format information

##### 🔄 **Scraper Context**

- `inputChannelUrl` *(string)*: The original input URL used to scrape this short
- `fromYTUrl` *(string)*: The YouTube URL where this short was found
- `input` *(string)*: The exact input parameter provided to the scraper
- `fromChannelListPage` *(string)*: Which channel page type was scraped ("shorts", "videos", etc.)

##### 📦 **aboutChannelInfo Object**

Contains a complete snapshot of channel metadata at the time of scraping:

- `channelName` *(string)*: Channel display name
- `channelId` *(string)*: Unique channel identifier
- `channelUrl` *(string)*: Full channel URL
- `channelUsername` *(string)*: Channel username/handle
- `numberOfSubscribers` *(number)*: Subscriber count
- `channelTotalViews` *(number)*: All-time channel views
- `channelTotalVideos` *(number)*: Total videos published
- `channelAvatarUrl` *(string)*: Profile picture URL
- `channelBannerUrl` *(string)*: Channel banner URL
- `isChannelVerified` *(boolean)*: Verification status
- `channelDescription` *(string)*: Channel description
- `channelJoinedDate` *(string)*: Channel creation date
- `channelLocation` *(string)*: Channel location
- `isAgeRestricted` *(boolean)*: Age restriction status
- `inputChannelUrl` *(string)*: Input URL used for scraping

***

### Error Items

When the scraper cannot retrieve data for a given input — for example a channel does not exist or a hashtag has no Shorts — it pushes an **error item** to the dataset instead of silently skipping it. Normal output rows never have an `error` field, so you can tell them apart reliably in integrations (Make, Zapier, n8n, API consumers).

#### Error item structure

```json
{
    "url": "https://www.youtube.com/@somechannel/shorts",
    "input": "https://www.youtube.com/@somechannel/shorts",
    "error": "CHANNEL_HAS_NO_SHORTS",
    "note": "The channel has no Shorts."
}
```

#### Error codes reference

| `error` | Meaning |
| --- | --- |
| `CHANNEL_DOES_NOT_EXIST` | The channel does not exist (YouTube returned 404). Detected instantly — no retry loop. |
| `CHANNEL_PAGE_FETCH_FAILED` | The channel Shorts page could not be fetched (network/other errors after retries). |
| `CHANNEL_PAGE_BLOCKED` | YouTube blocked the request (bot check). Try residential proxies. |
| `CHANNEL_PARSE_FAILED` | The channel Shorts page could not be parsed. |
| `CHANNEL_HAS_NO_SHORTS` | The channel exists but has no Shorts. |
| `SEARCH_PAGE_FETCH_FAILED` | The Shorts search results page could not be fetched. |
| `SEARCH_PAGE_BLOCKED` | YouTube blocked the search request (bot check). |
| `SEARCH_PARSE_FAILED` | The search results page could not be parsed. |
| `SEARCH_HAS_NO_SHORTS` | The search query returned no Shorts. |
| `HASHTAG_PAGE_FETCH_FAILED` | The hashtag Shorts page could not be fetched. |
| `HASHTAG_PAGE_BLOCKED` | YouTube blocked the hashtag page request (bot check). |
| `HASHTAG_PARSE_FAILED` | The hashtag Shorts page could not be parsed. |
| `HASHTAG_HAS_NO_SHORTS` | The hashtag has no Shorts. |
| `SHORT_DETAIL_FAILED` | A Short's detail page could not be scraped after all retries. |

### Use Cases

This YouTube Shorts scraper is perfect for:

- **Content Creators:** Analyze competitor shorts performance and engagement metrics
- **Marketers:** Track trending shorts and identify viral content patterns
- **Researchers:** Collect data on shorts engagement, channel growth, and content trends
- **Data Analysts:** Build datasets for YouTube Shorts analytics and performance studies
- **Social Media Managers:** Monitor channel performance and shorts strategy effectiveness
- **SEO Specialists:** Analyze hashtag usage and optimize short video discoverability

### Notes

- The scraper automatically handles YouTube's dynamic content loading
- Desktop YouTube structure is used to ensure likes and views data is available
- Proxy usage is recommended to avoid rate limiting on large scrapes
- All engagement metrics are captured in real-time at the moment of scraping
- Channel metadata is extracted once per channel and applied to all shorts from that channel

### Support

- For issues or feature requests, please use the [Issues](https://console.apify.com/actors/D3edLjry0l0eAY0T2/issues) section of this actor.
- If you need customization or have questions, feel free to contact the author:
  - Author's website: <https://muhamed-didovic.github.io/>
  - Email: <muhamed.didovic@gmail.com>

### Additional Services

- Request customization or whole dataset: <muhamed.didovic@gmail.com>
- If you need anything else scraped, or this actor customized, email: <muhamed.didovic@gmail.com>
- For API services of this scraper (no Apify fee, just usage fee for the API), contact: <muhamed.didovic@gmail.com>

# Actor input Schema

## `startUrls` (type: `array`):

All channel sources in one list: handles (`@name` or `name`), full Shorts tab URLs (`https://www.youtube.com/@handle/shorts`, `m.youtube.com`, `/channel/UC…/shorts`, `/c/…/shorts`), or scheme-less `youtube.com/…`. Optional if you use **Search queries** (or other sources) only. If you call the API with the old `channels` field, those entries are still merged (deprecated—use this list instead).

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

Keywords for **YouTube Shorts search** (`/results` with Shorts filter). Each term is searched separately; results feed the same detail pipeline as channel Shorts. **Max results per query** follows *Maximum number of shorts per search term* below.

## `hashtags` (type: `array`):

Tags for **YouTube hashtag Shorts hubs** (`/hashtag/{tag}/shorts`). Enter `apify` or `#apify` per row. Same **max results per hashtag** cap as channel URLs / search (see below).

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

Direct links to specific Shorts, e.g. `https://www.youtube.com/shorts/VIDEO_ID`. Also accepts `watch?v=` and `youtu.be/` — each unique video id is scraped once. Counts toward **Max items**.

## `maxItems` (type: `integer`):

Maximum number of shorts to scrape (global cap across all sources). Free users are capped at 30.

## `maxResultsShorts` (type: `integer`):

Cap per channel **or** per keyword search (in addition to the global max items cap).

## `sortChannelShortsBy` (type: `string`):

Listing order for each channel's Shorts tab. **Newest** uses the default grid; **Popular** and **Oldest** use YouTube's sort chips (same as `request-popular.json` / `request-oldest.json` browse flow).

## `regionCode` (type: `string`):

ISO 3166-1 alpha-2 country code (e.g. `US`, `DE`, `JP`) applied to listing pages and InnerTube requests. Leave empty to use the proxy IP's default region.

## `contentLanguage` (type: `string`):

Interface language code (e.g. `en`, `de`, `pt-BR`) applied to listing pages and InnerTube requests. Affects localized metadata text. Leave empty for the default.

## `oldestPostDate` (type: `string`):

Apify date picker: **Absolute** = `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM[:SS]Z` (UTC, inclusive). **Relative** = e.g. `30 minutes`, `2 hours`, `7 days`, `2 weeks`, `3 months`, `1 year` (cutoff = now minus that span). Leave empty to disable. Filtering uses each video’s publish date from the detail page.

## `includeTranscript` (type: `boolean`):

Fetch the transcript for each Short and add a `subtitles` object to the output (plain text, timed segments, and ready-to-save **SRT** and **WebVTT** strings). Slightly slower runs.

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

Preferred transcript language code (e.g. `en`, `de`, `es`). `default` = YouTube's default track. Falls back to English / the default track when the language is unavailable.

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

Maximum number of pages that can be processed at the same time.

## `minConcurrency` (type: `integer`):

Minimum number of pages that will be processed at the same time.

## `maxRequestRetries` (type: `integer`):

Number of times the crawler will retry a failed request before giving up.

## `proxy` (type: `object`):

Leave empty — the actor already routes all traffic through its own built-in residential proxy at no extra cost to you. Only set this if you want to use your own proxies.

## Actor input object example

```json
{
  "startUrls": [
    "rainbowicecream9780"
  ],
  "searchQueries": [],
  "hashtags": [
    "apify",
    "crawlee"
  ],
  "shortUrls": [
    "https://www.youtube.com/shorts/HKs9NvVRi5s"
  ],
  "maxItems": 10000,
  "sortChannelShortsBy": "NEWEST",
  "includeTranscript": false,
  "language": "default",
  "maxConcurrency": 10,
  "minConcurrency": 1,
  "maxRequestRetries": 10
}
```

# 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 = {
    "startUrls": [
        "rainbowicecream9780"
    ],
    "searchQueries": [],
    "hashtags": [
        "apify",
        "crawlee"
    ],
    "shortUrls": [
        "https://www.youtube.com/shorts/HKs9NvVRi5s"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/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 = {
    "startUrls": ["rainbowicecream9780"],
    "searchQueries": [],
    "hashtags": [
        "apify",
        "crawlee",
    ],
    "shortUrls": ["https://www.youtube.com/shorts/HKs9NvVRi5s"],
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/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 '{
  "startUrls": [
    "rainbowicecream9780"
  ],
  "searchQueries": [],
  "hashtags": [
    "apify",
    "crawlee"
  ],
  "shortUrls": [
    "https://www.youtube.com/shorts/HKs9NvVRi5s"
  ]
}' |
apify call memo23/youtube-shorts-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/SSRwepGKwzFKYeRrk/builds/X1wgyoAw1cs5uFx7S/openapi.json
