# YouTube Shorts & Channel Scraper: Videos, Subs, About (`datagleaner/youtube-channel-scraper`) Actor

YouTube Shorts scraper and channel video scraper: every video, Short and live stream of a channel with views, duration and date, plus the About tab (subscribers, country, links). By URL, @handle or ID. No login, no API key.

- **URL**: https://apify.com/datagleaner/youtube-channel-scraper.md
- **Developed by:** [Data Gleaner](https://apify.com/datagleaner) (community)
- **Categories:** Videos, For creators, Marketing
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 video or 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 & Channel Scraper: Videos, Subs, About

A YouTube Shorts scraper and channel video scraper in one Actor. Give it channels by URL, @handle or channel ID and get every **video, Short and live stream** with title, views, length, publish age and thumbnail, plus one **About row per channel** with subscribers, total views, video count, country, join date, description and links. $0.0005 per video or Short ($0.50 per 1,000), $0.001 per channel. Plain HTTP: no browser, no login, no YouTube API key and no quota.

Sort by newest, most viewed or oldest, take up to 5,000 rows per channel and tab, and switch on exact views, exact dates, likes and full descriptions when you need them. The rows are flat JSON with the same fields every time, so people, spreadsheets and AI agents can all use them.

### What does the YouTube Shorts & Channel Scraper do?

For each channel you give it, the Actor reads the channel's public **Videos**, **Shorts** and **Live** tabs and its **About** tab, the same pages a logged-out visitor sees. It pages through each tab the way the site does, in the order you pick, until it has the number of rows you asked for.

- **Videos tab:** `videoId`, `url`, `title`, `viewCount`, `publishedText`, `publishedAt`, `durationSeconds`, `thumbnailUrl`.
- **Shorts tab:** the same fields for every Short, with `isShort: true` and a `youtube.com/shorts/...` link. Shorts are the lane with the fewest tools, which is why this Actor opens with them.
- **Live tab:** past and upcoming streams, with `isLive` set for a stream that is live right now.
- **About tab:** one `channel` row per channel: `subscriberCount`, `viewCount`, `videoCount`, `joinedDate`, `country`, `description`, `links`, `avatarUrl`, `bannerUrl`, `isVerified`.
- **Optional video details:** `includeVideoDetails` adds the exact view count, the exact publish date, the like count and the full description to every video and Short.

It does **not** return emails (the About tab shows none without a sign-in), comments, transcripts or video files. For channel emails and socials, see Related Actors below.

### Use cases

- **Shorts research:** pull a creator's or a niche's Shorts with views, sorted by most viewed, to see which hooks and topics work.
- **Competitor and creator monitoring:** schedule a daily run with `sortBy: newest` and a small limit, and diff on `videoId` to catch every new upload.
- **Influencer vetting:** subscribers, country, join date, upload cadence and average views, in one table for a list of channels.
- **Content and trend analysis:** rank a channel's whole back catalogue by views, length or age.
- **Datasets for AI and analytics:** titles, view counts and dates for thousands of videos, without managing API quota.
- **Lead and outreach pipelines:** the channel's `links` carry its website and socials, which you can pass on to a contact finder.

### Input

| Field | Meaning |
|---|---|
| `channelUrls` | Channel URLs (`https://www.youtube.com/@MKBHD`, `/channel/UC...`, `/c/...`, `/user/...`). @handles and `UC...` IDs also work. |
| `handles` | Handles with or without the @. |
| `channelIds` | Channel IDs starting with `UC`. |
| `tabs` | Any of `videos`, `shorts`, `streams`. Default `["videos"]`. An empty list with `includeAbout` on returns channel rows only. |
| `maxVideosPerChannel` | Rows per channel **and tab**. Default 50, up to 5,000. |
| `sortBy` | `newest` (default), `popular` (most viewed) or `oldest`: YouTube's own Latest, Popular and Oldest sort. |
| `includeAbout` | Add one channel row per channel. Default true. |
| `includeVideoDetails` | Exact views, exact date, likes and full description per video. Default false. |
| `maxConcurrency`, `requestDelaySecs` | Politeness controls. Defaults of 4 requests at a time and 0.25 s spacing are enough for most runs. |
| `proxyConfiguration` | Optional. Works without a proxy. |

Example: the 20 most viewed Shorts and the 20 newest videos of two channels, with channel facts.

```json
{
  "channelUrls": ["https://www.youtube.com/@MKBHD", "@NASA"],
  "tabs": ["videos", "shorts"],
  "maxVideosPerChannel": 20,
  "sortBy": "popular",
  "includeAbout": true
}
```

Note that `sortBy` applies to every selected tab. For the newest videos and the most viewed Shorts together, run the Actor twice.

An empty input runs a built-in example (one channel, 2 videos and 2 Shorts, 5 rows) so you can see the output format for a few cents. Any input that names a channel runs only what you asked for.

### Output

Video and Short row (`includeVideoDetails` off):

```json
{
  "type": "video",
  "videoId": "QVv3mQzlrN0",
  "url": "https://www.youtube.com/watch?v=QVv3mQzlrN0",
  "title": "Apple Homeview Impressions: Not Convinced!",
  "viewCount": 10000000,
  "viewCountText": "10M views",
  "viewCountExact": false,
  "publishedText": "6d ago",
  "publishedAt": "2026-10-15T00:00:00Z",
  "publishedApprox": true,
  "durationText": "11:47",
  "durationSeconds": 707,
  "thumbnailUrl": "https://i.ytimg.com/vi/QVv3mQzlrN0/hq720.jpg",
  "isShort": false,
  "isLive": false,
  "badges": [],
  "tab": "videos",
  "position": 2,
  "channelId": "UCBJycsmduvYEL83R_U4JriQ",
  "channelHandle": "@mkbhd",
  "channelTitle": "Marques Brownlee",
  "inputUrl": "https://www.youtube.com/@MKBHD",
  "scrapedAt": "2026-10-21T09:12:44Z"
}
```

With `includeVideoDetails`, the same row also has `description` and `likeCount`, `viewCount` becomes exact (`10378636`, `viewCountExact: true`) and `publishedAt` becomes the real date (`publishedApprox: false`).

Channel row:

```json
{
  "type": "channel",
  "channelId": "UCBJycsmduvYEL83R_U4JriQ",
  "handle": "@mkbhd",
  "url": "https://www.youtube.com/@mkbhd",
  "title": "Marques Brownlee",
  "description": "MKBHD: Quality Tech Videos | YouTuber | Geek ...",
  "subscriberCount": 21400000,
  "subscriberCountText": "21.4M subscribers",
  "videoCount": 1859,
  "viewCount": 5800350438,
  "joinedDate": "2008-03-21",
  "country": "United States",
  "countryCode": "US",
  "links": [{"title": "Instagram", "url": "https://instagram.com/MKBHD"}],
  "avatarUrl": "https://yt3.googleusercontent.com/...",
  "bannerUrl": "https://yt3.googleusercontent.com/...",
  "isVerified": true,
  "keywords": "MKBHD MarquesBrownlee Marques Brownlee",
  "rssUrl": "https://www.youtube.com/feeds/videos.xml?channel_id=UCBJycsmduvYEL83R_U4JriQ",
  "inputUrl": "https://www.youtube.com/@MKBHD",
  "scrapedAt": "2026-10-21T09:12:42Z"
}
```

#### How exact are the numbers?

The channel's list pages show **rounded** views (`10M`, `8.3M`) and relative ages (`6d ago`). By default the Actor returns exactly that: `viewCount` is the rounded number as YouTube shows it, flagged `viewCountExact: false`, and `publishedAt` is worked out from the age and flagged `publishedApprox: true`. Shorts carry no age at all on the list page. Turn on `includeVideoDetails` for exact views, exact dates and likes. Subscriber counts are always rounded to three significant digits, because YouTube hides the rest.

### Pricing

Pay per event, and nothing else:

| Event | Price | Per 1,000 |
|---|---|---|
| Video, Short or live stream row | **$0.0005** | $0.50 |
| Video row with `includeVideoDetails` | **$0.0008** | $0.80 |
| Channel row (About) | **$0.001** | $1.00 |

There is no start fee and no extra charge for compute or proxies. You pay for rows pushed to the dataset. A channel that does not exist, a tab a channel does not have and a video whose details could not be read (it is billed at the plain video price instead) cost nothing extra. The run stops at your maximum charge.

Worked examples:

- 1,000 Shorts from 10 creators: 1,000 x $0.0005 = **$0.50**. Shorts-focused scrapers on the Apify Store charged up to $0.003 per result when we checked on 2026-10-21, which is $3.00 for the same rows.
- A creator list of 200 channels with the About row and their 50 newest videos each: 200 x $0.001 + 10,000 x $0.0005 = **$5.20**.
- A daily monitor of 25 channels, 5 newest videos each, no About row: 125 x $0.0005 = **$0.06 a day**, about $1.90 a month.
- 100 videos with exact views, dates and likes: 100 x $0.0008 = **$0.08**.
- The default test (prefill: one channel, 10 videos and 10 Shorts) costs about **$0.011**.

### Use it from the API

```bash
curl -X POST "https://api.apify.com/v2/acts/datagleaner~youtube-channel-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"channelUrls": ["@MKBHD"], "tabs": ["shorts"], "maxVideosPerChannel": 20, "sortBy": "popular", "includeAbout": false}'
```

### Use with Python

`pip install apify-client`, set `APIFY_TOKEN`, run. This input returns 20 Shorts for $0.01.

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("datagleaner/youtube-channel-scraper").call(run_input={
    "channelUrls": ["@MKBHD"],
    "tabs": ["shorts"],
    "maxVideosPerChannel": 20,
    "sortBy": "popular",
    "includeAbout": False,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["viewCount"], item["title"], item["url"])
```

### Use with JavaScript / Node.js

`npm install apify-client`, set `APIFY_TOKEN`, run as an ES module.

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('datagleaner/youtube-channel-scraper').call({
    channelUrls: ['@NASA'],
    tabs: ['videos'],
    maxVideosPerChannel: 10,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const row of items) console.log(row.type, row.title ?? row.handle);
```

### Use it from n8n, Make, Zapier or an AI agent

Actor ID: `datagleaner/youtube-channel-scraper`

Minimal input:

```
{"channelUrls": ["@MKBHD"], "tabs": ["videos", "shorts"], "maxVideosPerChannel": 10}
```

- **n8n:** add the **Apify** node (`@apify/n8n-nodes-apify`), choose **Run an Actor and get dataset**, set Actor to `datagleaner/youtube-channel-scraper` and paste the input.
- **Make:** the Apify app's **Run an Actor** module, then **Get Dataset Items**. **Watch Actor Runs** can trigger a scenario when a run finishes.
- **Zapier:** the Apify action **Run Actor**, then **Fetch dataset items**.
- **AI agents (MCP):** connect to `https://mcp.apify.com?tools=datagleaner/youtube-channel-scraper`. In Claude Code:

  ```
  claude mcp add --transport http apify "https://mcp.apify.com?tools=datagleaner/youtube-channel-scraper"
  ```

  Then ask in plain language, for example: "Get the 30 most viewed Shorts of this channel and tell me what they have in common." An agent without the Actor preloaded can find it with Apify's `search-actors` tool by searching "youtube shorts".

### Limits

- **Lists show rounded views and relative ages.** Use `includeVideoDetails` for exact numbers and dates. Shorts have no date without it.
- **Likes and descriptions need `includeVideoDetails`.** Likes come back empty when a creator hides them.
- **Subscriber counts are rounded to three significant digits** by YouTube. Some channels hide the count; it is empty then.
- **Only public content.** Members-only videos, private and unlisted videos, age-restricted videos that need a sign-in, and comments are not returned. There are no video files, captions or transcripts.
- **No email field.** The public About tab does not show one without a sign-in. The channel's `links` and description are returned as published.
- **A channel with no Shorts or Live tab returns nothing for that tab.** The status message lists the tabs that did not exist; you are not billed for them.
- **`sortBy` follows YouTube's own sort buttons** (Latest, Popular, Oldest), so a tab that does not offer one keeps its default newest-first order. The log says so.
- **Rate limits.** The Actor keeps to 4 requests at a time with a short pause, and backs off when YouTube answers 429. If a very large run is slowed down, turn on `proxyConfiguration` or lower `maxConcurrency`.
- YouTube changes its pages now and then. If a field starts coming back empty, report it and it will be fixed.

### FAQ

**Do I need a YouTube API key or quota?** No. The Actor reads the public pages a logged-out visitor sees, so there is no key and no daily quota.

**Can it scrape YouTube Shorts?** Yes. Add `shorts` to `tabs`. Each Short comes back with its link, title, views and thumbnail, and exact date and likes with `includeVideoDetails`.

**How do I get all videos of a channel?** Set `maxVideosPerChannel` high (up to 5,000 per tab). The Actor pages through the tab until it runs out.

**How do I get a channel's most viewed videos?** `sortBy: "popular"`.

**How do I monitor new uploads?** Schedule a run with `sortBy: "newest"`, a small `maxVideosPerChannel`, and compare `videoId` with the last run. The `position` field is the rank in the tab.

**Does it work with a handle only?** Yes: `@MKBHD`, `MKBHD`, a `/channel/UC...` URL, a `/c/` or `/user/` URL, or a bare `UC...` ID.

**What does the About row cost?** $0.001 per channel, and you can switch it off with `includeAbout: false`.

**Can I get emails from the channels?** Not from this Actor. Use the YouTube channel email Actor listed below, which reads the description and links for published emails.

**Do I need a proxy?** No. It works without one on Apify. The option is there for very large runs.

### Related Actors

- [YouTube Channel Email Scraper](https://apify.com/datagleaner/youtube-channel-contacts): published emails, websites and socials for a list of channels or a niche keyword. Run it after this Actor on the same channels when you need contacts rather than videos.
- [YouTube Search Scraper](https://apify.com/datagleaner/youtube-search-scraper): find channels and videos by keyword first, with date, length and sort filters, then pass the `channelUrl` values to this Actor.
- [YouTube Comments Scraper](https://apify.com/datagleaner/youtube-comments-scraper): the comments and replies under any video, top or newest, with authors, likes and an optional keyword filter. Take the `videoId` values from this Actor's dataset, or give it this run's dataset ID.
- [YouTube Transcript Scraper](https://apify.com/datagleaner/youtube-transcript-scraper): the transcript of any video. Take the `videoId` values from this Actor's dataset and get the spoken text.
- [Website Contact Details Scraper](https://apify.com/datagleaner/website-contact-details-scraper): emails, phones and social profiles from the websites listed in a channel's `links`.

### Responsible use

This Actor reads public YouTube pages without logging in or bypassing any sign-in, and it paces its requests. Use the data in line with YouTube's terms and applicable law. Channel and video data is public, but if you store or combine it with other data about individuals, the data-protection obligations are yours.

# Actor input Schema

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

YouTube channel URLs such as `https://www.youtube.com/@MrBeast`, `https://www.youtube.com/channel/UC...` or older `/c/` and `/user/` links. @handles and `UC...` IDs also work here.

## `handles` (type: `array`):

Handles with or without the @, e.g. `@MrBeast` or `MrBeast`. Use this or the URL field, whichever your list has.

## `channelIds` (type: `array`):

Channel IDs that start with `UC` and are 24 characters long, e.g. `UCBJycsmduvYEL83R_U4JriQ`.

## `tabs` (type: `array`):

Which parts of each channel to read: regular videos, Shorts, live streams (past and current). Pick one or several; `maxVideosPerChannel` applies to each. The channel's About facts come from `includeAbout`, not from this list. Leave the list empty with `includeAbout` on to get channel rows only (subscribers, views, country, links).

## `maxVideosPerChannel` (type: `integer`):

Stops after this many videos for each channel and each selected tab (so 2 tabs and 50 give up to 100 rows per channel). The list is read newest first unless you change `sortBy`. Each row is billed once.

## `sortBy` (type: `string`):

The order YouTube's own sort buttons give: Latest, Popular or Oldest. Use newest to monitor a channel, popular for its best content.

## `includeAbout` (type: `boolean`):

Adds one channel row per channel: subscribers, total views, video count, country, join date, description, links and avatar. It is billed as one channel row. Turn off if you only want the videos.

## `includeVideoDetails` (type: `boolean`):

One extra request per video fills in the exact view count, the exact publish date, the like count and the full description. Without it, view counts are rounded as YouTube shows them on the channel page (`1.2M`) and dates are approximate (`3 weeks ago`). Billed at the higher video-details price for each row that was filled in.

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

Requests in flight at once. Keep it low; the default is polite to YouTube and fast enough.

## `requestDelaySecs` (type: `number`):

Minimum spacing between requests across the whole run, with random jitter. Raise it if you run many channels and see rate-limit warnings in the log.

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

Optional. The Actor works without a proxy. Turn on Apify Proxy only if YouTube rate-limits your run.

## Actor input object example

```json
{
  "channelUrls": [
    "https://www.youtube.com/@MKBHD"
  ],
  "tabs": [
    "videos",
    "shorts"
  ],
  "maxVideosPerChannel": 10,
  "sortBy": "newest",
  "includeAbout": true,
  "includeVideoDetails": false,
  "maxConcurrency": 4,
  "requestDelaySecs": 0.25
}
```

# Actor output Schema

## `videos` (type: `string`):

No description

## `channels` (type: `string`):

No description

## `results` (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 = {
    "channelUrls": [
        "https://www.youtube.com/@MKBHD"
    ],
    "tabs": [
        "videos",
        "shorts"
    ],
    "maxVideosPerChannel": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("datagleaner/youtube-channel-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 = {
    "channelUrls": ["https://www.youtube.com/@MKBHD"],
    "tabs": [
        "videos",
        "shorts",
    ],
    "maxVideosPerChannel": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("datagleaner/youtube-channel-scraper").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 '{
  "channelUrls": [
    "https://www.youtube.com/@MKBHD"
  ],
  "tabs": [
    "videos",
    "shorts"
  ],
  "maxVideosPerChannel": 10
}' |
apify call datagleaner/youtube-channel-scraper --silent --output-dataset

```

## MCP server setup

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

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/xAK1Bq4OGIpEjpRpH/builds/7NnH7Zd1WStUcccMI/openapi.json
