# YouTube Channel Scraper & Tracker - Videos, Subscribers, Alerts (`akhil_rajesh/youtube-channel-scraper`) Actor

YouTube channel scraper & tracker, no login or API key: exact total views, video counts, subscribers, videos, Shorts, live streams, popular videos. YouTube channel monitor: new and removed videos, title changes, subscriber growth, alerts to Slack, Discord, Telegram. API & MCP. $1 per 1,000 results.

- **URL**: https://apify.com/akhil_rajesh/youtube-channel-scraper.md
- **Developed by:** [Akhil rajesh](https://apify.com/akhil_rajesh) (community)
- **Categories:** Videos, Social media, MCP servers
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Channel Scraper & Tracker

Scrape **YouTube channels** without a login, an API key or Google quotas: **exact total views and video count**, subscribers, joined date, country, description and links, plus each channel's **videos, Shorts, live streams and most popular videos**: title, views, age, length, live and upcoming marks. Paste handles (`@mkbhd`), channel links or channel ids, up to 1,000 at a time.

It is also a **YouTube channel tracker and monitor**. Schedule it with **Only changes** and each run returns one row per channel with **what it gained since the last run** (subscribers, total views, videos, and over 7 and 30 days), and only what moved: **new videos, removed videos, changed titles, streams that went live and view jumps**, posted to **Slack, Discord, Telegram or Microsoft Teams** if you like. It also runs as a **live API and MCP server for AI agents**.

**One price, no extras: $1.00 per 1,000 results, with platform usage included and no row cap on Apify's free plan.** (Apify's Store page lists platform usage too, because the live API below adds it; ordinary runs never pay it.)

### Why this scraper

- **It tracks channels, not just lists them.** Most YouTube channel scrapers return the same rows every run, and you work out what changed. This one keeps a history per channel, with a reading a day, and returns only what is new.
- **A title test isn't a title change.** YouTube lets creators test several titles at once, so different viewers see different titles for the same video. A title this tracker has seen before is not reported again, and a real change comes with every title the video has shown.
- **Removed means removed.** A video that leaves a channel's list is checked with YouTube itself: `deletedOrPrivate` when YouTube says it is gone, `hiddenFromChannel` when it still exists off the channel's lists.
- **Exact where YouTube is exact.** The channel's total views and video count are exact numbers, and they move every day, so `totalViewsGained` works for channels whose rounded subscriber count barely changes.
- **Better than a one-off look.** Median views per kind (videos, Shorts, streams), upload pace, days since the last upload, views a day, and how each video did against the channel's usual one (`viewsVsMedian`: 3.2 is 3.2 times its median).
- **No login, no API key, no quota.** The Actor reads the public channel pages and video lists anyone can open.
- **Honest numbers.** Fields carry what the pages show. What a list doesn't show (see [What it can't do](#what-it-cant-do)) is left empty, never guessed.

| | Typical YouTube channel scrapers | This Actor |
|---|---|---|
| Subscribers, total views, video count, joined date, country, links | Yes | Yes |
| Videos, Shorts, live streams | Yes | Yes, plus the most popular videos |
| New and removed videos, title changes since the last run | You compare runs yourself (a few small monitors do new videos) | Built in (Only changes) |
| Subscriber and view growth, over 7 and 30 days | Rare | Built in, with a reading a day |
| Title tests told apart from real changes | Rare | Yes |
| Alerts to Slack, Discord, Telegram, Teams | Rare | Yes |
| Median views, upload pace, views against the channel's usual | Some | Yes, on every channel row |
| MCP server for AI agents | Rare | Its own (4 tools) |
| Exact views and exact dates per video, likes, every video a channel ever made | Those that open every video | No: see [What it can't do](#what-it-cant-do) |

### Use cases

- **Competitor monitoring**: a daily schedule on your rivals' channels that posts each new video, title change and view jump to Slack.
- **YouTube subscriber tracking**: subscribers, total views and video count per day for your channels and your competitors', with 7-day and 30-day gains.
- **Influencer research**: compare hundreds of channels by median views, upload pace, country and last upload before you reach out. **Channel rows only** gives one row per channel.
- **Content research**: which of a channel's videos beat its own median, and which titles it tested.
- **News and brand monitoring**: know when a channel posts, goes live, or quietly removes a video.
- **AI agents**: ask an assistant "compare @mkbhd and @LinusTechTips by median views and upload pace" through the MCP server.

### How to use it in 4 steps

1. Add **Channels**: `@mkbhd`, `https://www.youtube.com/@mkbhd`, `https://www.youtube.com/channel/UCBJycsmduvYEL83R_U4JriQ` or `UCBJycsmduvYEL83R_U4JriQ`.
2. Set how many **Videos**, **Shorts**, **Live streams** and **Popular videos** to read per channel (100 at most each). Set all four to 0 for channel figures alone, or switch on **Channel rows only** for one row per channel with its medians and pace.
3. Set **Max results** and any filters, and run it.
4. To track changes, switch on **Only changes since the last run**, add an alert if you want one, and schedule it.

### What you get

One row per channel (`type: "channel"`) and one per video (`type: "video"`). A real channel row, shortened:

```json
{
    "type": "channel",
    "input": "@mkbhd",
    "channelId": "UCBJycsmduvYEL83R_U4JriQ",
    "handle": "@mkbhd",
    "name": "Marques Brownlee",
    "channelUrl": "https://www.youtube.com/@mkbhd",
    "subscribers": 21400000,
    "subscribersText": "21.4M subscribers",
    "totalViews": 5856382564,
    "videoCount": 1863,
    "joinedDate": "2008-03-21",
    "country": "United States",
    "isVerified": true,
    "longVideoCount": 1729,
    "shortsCount": 125,
    "streamCount": 6,
    "medianViews": 5150000,
    "medianShortsViews": 5050000,
    "medianStreamViews": 945000,
    "lastUploadAbout": "2026-10-29",
    "uploadsLast30Days": 6,
    "uploadsPerMonth": 8.3,
    "uploadIntervalDays": 3.7
}
```

A channel row also has the description, keywords, links, avatar, banner and the tabs the channel shows. A real video row:

```json
{
    "type": "video",
    "channelId": "UCBJycsmduvYEL83R_U4JriQ",
    "handle": "@mkbhd",
    "channelName": "Marques Brownlee",
    "videoId": "2reQut8WNGc",
    "url": "https://www.youtube.com/watch?v=2reQut8WNGc",
    "title": "Macbook PROLED XDR Impressions: They Said They Wouldn't!",
    "videoType": "video",
    "views": 10000000,
    "viewsShown": "10M",
    "publishedText": "3 days ago",
    "publishedAbout": "2026-10-29",
    "ageDays": 3.0,
    "durationSeconds": 654,
    "durationText": "10:54",
    "position": 1,
    "lists": ["videos"],
    "viewsPerDay": 3333333,
    "viewsVsMedian": 1.94
}
```

Live streams add `isLiveNow`, `watchingNow`, `isUpcoming` and `scheduledFor` (in UTC); a premiere adds `isPremiere`, and a scheduled stream whose time passed days ago adds `scheduleLapsed` instead of `isUpcoming` (T-Series still lists streams scheduled for 2018). Popular videos add `popularRank`. A video made with other channels adds `collaborators`, which names all of them, also those YouTube's list hides behind "and 2 more". A video on two lists (the newest and the most popular) is one row, naming both in `lists`. A name YouTube has no channel for gets a free `notFound` row.

**Titles**: `title` is what the channel wrote. YouTube shows English readers a translation when the creator added one (Felipe Neto's Portuguese titles, HikakinTV's Japanese ones), so each list is read twice, and that translation comes in `titleEnglish`. Switch off **The channel's own titles** to read each list once, in about half the time, with the titles English readers see.

**Numbers**: `subscribers` and `views` are as YouTube rounds them for everyone (`21.4M`, `10M`), to 3 digits at most. `totalViews` and `videoCount` are exact. YouTube's lists of a channel's videos stop at about 20,000, so `longVideoCount` stops there too, while `videoCount` doesn't. Medians leave out streams that never ran (0 views, no length). **Dates**: lists word a video's age ('3 days ago', '2 years ago'), so `publishedAbout` is about, and only as fine as those words.

**Regions**: YouTube shows each country what it may watch there, and the Actor reads from Apify's servers in the United States, or wherever your proxy is. When a list hides videos (deleted, private or blocked in that region), the channel row names it in `hiddenOnLists`, and the run says so. SET India's list showed 25 videos from Apify's servers and 56 from a home connection, so for a channel like that, use **Proxy** in its own country if you have one there.

With **Only changes**, a channel row adds `subscribersGained`, `totalViewsGained`, `videosAdded`, `viewsPerDay`, `daysSinceLastRun`, `subscribersGained7d`, `totalViewsGained7d`, `subscribersGained30d`, `totalViewsGained30d`, `previousName` and `previousHandle` when they changed, and `history` (the last 30 daily readings). Video rows add `change`:

| change | meaning |
|---|---|
| `newVideo` | a video, Short or stream posted since the last run |
| `removed` | it left the channel: `removalKind` is `deletedOrPrivate` (YouTube says it is gone) or `hiddenFromChannel` (it still exists, off the channel's lists) |
| `titleChanged` | a title this tracker has never seen for the video, with `previousTitle` and `titlesSeen` |
| `wentLive` | a stream or premiere that went live; `isLiveNow` says whether it still is |
| `viewsJump` | views rose past your **View jump (%)** since the last report, with `previousViews`, `viewsGained` and `viewsGainedPercent` (ask for it in **Changes to return**) |
| `firstRun` | the first run's baseline: the videos there now |

The dataset has views for **Overview**, **Videos**, **Channels**, **Growth**, **Changes** and **Live** (a view picks columns: every view lists every row, so filter on `type` or `change` if you need to).

### How to use it

#### Channels

A channel is a handle (`@mkbhd`, or `mkbhd`), a link (`youtube.com/@mkbhd`, `youtube.com/channel/UC...`, `youtube.com/user/...`, `youtube.com/c/...`, or a bare `youtube.com/name`) or a channel id (`UC...`). Two names of one channel are read once. An old `/c/` link that no longer answers is tried as a handle, and the run says so.

#### Lists and limits

Lists read newest first, the popular list by YouTube's own ranking. **Max results** (1,000 by default) is shared between channels, in rounds, so a big channel doesn't use up a small one's share; on one channel it keeps some of each list. Rows are never cut at random: what doesn't fit is counted in the run's status message. **Channel rows only** returns one row per channel, without a row per video.

#### Filters

**Posted after** (a date or `7 days`), **Minimum views**, **Only titles containing** and **Exclude words** apply to video rows. Words are looked for in the channel's own title and in `titleEnglish`. Dates are about, as lists word them, and Shorts show none, so Posted after doesn't filter Shorts. Minimum views leaves out streams live now, which show no views.

### Tracking changes on a schedule (YouTube channel tracker)

1. Switch on **Only changes since the last run**. Optionally pick the **Changes to return**.
2. Run it once: the first run returns each channel's row and its videos as `firstRun`, and saves them as the baseline.
3. Schedule it (Apify Console, Schedules). Each later run returns a row per channel with its gains, and only the changes.

How it decides:

- **New**: lists run newest first, so a video above the first known one is new, unless its age says it came before the last run. Live and upcoming videos are new wherever they sit. A video below the first known one moved into view and is recorded without a row. **Videos per channel** sets how many newest videos a run watches. A stream first seen while live is one `wentLive` row with `isNew: true`. A new video under **Minimum views** is reported on the run that it passes them.
- **Removed**: a watched video that left its list while older ones stayed is checked with YouTube's public video check. If YouTube says it is gone, it is reported at once. If it still exists, or YouTube doesn't answer, it is reported when it has been missing two runs in a row, because a list can leave a video out for one fetch.
- **Changed title**: titles are kept per video, so a title YouTube is testing doesn't come back as a change each time it shows, and a new translation isn't a new title. The tracker also keeps one anonymous YouTube visitor per history, as a returning browser does, because different visitors are shown different titles.
- **View jumps**: per-video views are rounded, so a jump is measured from the last report, and it counts from 1,000 views: 500 to 5,000 is a jump, 200 to 900 isn't. Use it for watched videos; a fresh video always jumps, so it isn't on by default.
- **Growth**: `totalViewsGained` and `videosAdded` are exact. `subscribersGained` moves in YouTube's rounded steps: a channel at 21.4M shows no change until it reaches 21.5M. YouTube also updates a channel's total views in steps, not by the minute: 12 channels, MrBeast's among them, showed no gain across 3 hours, so runs close together can show none.
- Histories are kept per channel and filters (two trackers with different filters don't mix), in the key-value store `youtube-tracker-history`, or one you name in **History name**.
- Only what a run returns moves the history: if Max results or your spending limit stops a run, the changes it didn't return come with the next run.

### Alerts in Slack, Discord, Telegram or Microsoft Teams

Paste an incoming-webhook URL in **Alert webhook URL** (Slack, Discord, Microsoft Teams, or any HTTPS endpoint that takes JSON, such as Zapier, Make or n8n), or a **Telegram bot token** and **Telegram chat id**. Each switches on Only changes. The first run posts one short "alerts are set up" message; each later run posts its changes (new videos by default, or those you pick in **Alert on**), up to 50 per run. A run that stops early (aborted, or failing partway) still posts the changes it stored. A restarted run doesn't post a message twice, and a failed post doesn't fail a run whose data loaded: its status says why.

### Run summary for pipelines

Each run saves a `RUN_SUMMARY` record in its key-value store: per channel, its rows and what each list held; plus the changes, what didn't load and why, and the filters used.

### YouTube channel API: use it from code or from an AI assistant

Start a run and get the rows in one call (replace `<YOUR_TOKEN>`; a call that waits gives up after 5 minutes, so start bigger runs without waiting and read the dataset afterwards):

```bash
curl -X POST "https://api.apify.com/v2/acts/akhil_rajesh~youtube-channel-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"channels": ["@mkbhd", "@Fireship"], "maxVideos": 30}'
```

Or from Python with `apify-client`:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_TOKEN>")
run = client.actor("akhil_rajesh/youtube-channel-scraper").call(run_input={
    "channels": ["@mkbhd", "@Fireship"], "maxVideos": 30, "maxShorts": 10, "postedAfter": "30 days",
})
for row in client.dataset(run.default_dataset_id).iterate_items():
    print(row["type"], row.get("name") or row.get("title"))
```

#### For AI agents: MCP server and live API

The Actor also runs as a **live endpoint** (Apify Standby): an **MCP server** that agents call directly, and plain HTTP endpoints. Once a Standby run is up, a request is answered in seconds; the first request starts one. Authenticate with your Apify API token in the `Authorization: Bearer <token>` header.

**MCP server** (Streamable HTTP): `https://akhil-rajesh--youtube-channel-scraper.apify.actor/mcp`

```json
{"mcpServers": {"youtube-channels": {"type": "http", "url": "https://akhil-rajesh--youtube-channel-scraper.apify.actor/mcp",
  "headers": {"Authorization": "Bearer <YOUR_APIFY_TOKEN>"}}}}
```

In Claude Code:

```bash
claude mcp add --transport http youtube-channels https://akhil-rajesh--youtube-channel-scraper.apify.actor/mcp --header "Authorization: Bearer <YOUR_APIFY_TOKEN>"
```

A client that can't send headers can use `https://akhil-rajesh--youtube-channel-scraper.apify.actor/mcp?token=<YOUR_APIFY_TOKEN>`; keep that URL private, as it carries your token.

| Tool | What it returns |
|---|---|
| `get_channel_info` | One row per channel: subscribers, exact total views and video count, joined date, country, description, links |
| `get_channel_videos` | A channel's videos, Shorts, streams and popular videos, with filters |
| `compare_channels` | One row per channel, biggest first, with median views, upload pace and days since the last upload |
| `run_actor` | The Actor's whole input in one call |

**HTTP endpoints**, such as `GET https://akhil-rajesh--youtube-channel-scraper.apify.actor/videos?channels=@mkbhd|@Fireship&videos=30` (separate several values with `|`). The Actor's **Endpoints** tab in Apify Console lists them too, and lets you try them.

| Endpoint | Parameters |
|---|---|
| `GET /channel` | `channels` |
| `GET /videos` | `channels`, `videos`, `shorts`, `streams`, `popular`, `max`, `after`, `keywords`, `exclude`, `minViews`, `originalTitles` |
| `GET /compare` | `channels` |
| `POST /run` | The Actor's whole input as JSON |

A tool call reads up to 5 channels and 200 rows, an HTTP request 20 channels and 2,000 rows. A request stops at its time and size limits and names what it left in `notRead`. Tracking and alerts belong to scheduled runs: a request is answered on its own. On the live endpoint, platform usage is added to the price of the rows while the run serves you, and a request keeps reading until its limit even if the caller stops waiting.

### How much does it cost?

You pay **$1.00 per 1,000 results**, less on paid Apify plans, plus a start fee of $0.00005 per run. A result is a channel row or a video row. **Platform usage is included** in runs of the Actor: there is no compute charge on top. (The Store page's pricing box mentions platform usage because of the live endpoint, which adds it; ordinary runs never do.) Names that weren't found are free.

| Apify plan | Per 1,000 results |
|---|---|
| Free | $1.00 |
| Starter | $0.90 |
| Scale | $0.80 |
| Business and above | $0.70 |

| Run | Results | Cost (Free plan) |
|---|---|---|
| One channel and its last 30 videos | 31 | about $0.03 |
| 100 channels with Channel rows only | 100 | about $0.10 |
| 100 channels and 10 videos each | 1,100 | about $1.10 |
| One channel's four lists, full | up to 401 | up to $0.40 |
| 33 large channels, all four lists | 6,669 | about $6.67 |
| 10 channels tracked daily, about one new video each | about 20 a day | about $0.60 a month |

Apify's free plan ($5 of monthly credit) covers about 5,000 results. To cap spending, lower Max results or set a **maximum cost per run** in the run options: the run stops at the limit and says so.

### What it can't do

- **Exact views, likes, comments and video descriptions**: these need each video's own page, and those pages ask visitors from cloud servers to sign in. This Actor doesn't get around that. Views are the list's rounded figure.
- **More than the newest 100 per list**: that is what a channel's list shows without YouTube's API. Together, the four lists can hold more than 100 videos a channel. Older videos can't be read, so this isn't a full archive of a channel.
- **Dates on Shorts**: YouTube's Shorts list shows views, but no dates or lengths.
- **Search**: finding channels by keyword isn't offered: YouTube's rules for automated visitors exclude its search pages.
- **Emails**: YouTube keeps channels' business emails behind a sign-in. A channel's description comes as its owner wrote it.
- **Subscriber numbers more exact than YouTube's**: nobody outside YouTube has them.

### FAQ

**Do I need a YouTube API key or a Google account?** No.

**How often can I run it?** Daily suits growth tracking. For a channel that posts often, hourly works too. A run takes about 2 seconds per page: one page per channel, and two per list you ask for (one with **The channel's own titles** off).

**Is it legal to scrape YouTube channels?** This Actor reads public pages only and collects no personal data beyond what a channel publishes about itself. Check your own use against the laws that apply to you and YouTube's terms.

**Is this an official YouTube product?** No. This Actor isn't affiliated with or endorsed by YouTube or Google. YouTube is a trademark of Google LLC.

# Actor input Schema

## `channels` (type: `array`):

YouTube channels: a handle (@mkbhd), a channel link (youtube.com/@mkbhd, youtube.com/channel/UC..., youtube.com/user/...) or a channel id (UC...). Up to 1,000. A name YouTube has no channel for gets a free 'notFound' row.

## `maxVideos` (type: `integer`):

Newest long videos per channel. 100 at most: that is what a channel's list shows without YouTube's API. Set all four lists to 0 for channel figures alone. With Only changes: the newest videos each run watches.

## `maxShorts` (type: `integer`):

Newest Shorts per channel (100 at most). YouTube's Shorts list shows views but no dates or lengths.

## `maxStreams` (type: `integer`):

Newest live streams per channel, past, live now and upcoming (100 at most).

## `maxPopular` (type: `integer`):

The channel's most popular long videos, as YouTube ranks them (100 at most), with popularRank.

## `channelsOnly` (type: `boolean`):

Return one row per channel, without a row per video: its lists are still read, so the row has its median views, upload pace and counts per kind. The cheapest way to compare many channels. With Only changes, the channels' figures are tracked alone.

## `originalTitles` (type: `boolean`):

On by default. YouTube shows English readers the titles a channel translated, so each list is read a second time for the title the channel wrote; the translation goes in titleEnglish. Turn it off to read each list once, in about half the time, and get the English titles. Keywords and Exclude words match both.

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

Most rows a run returns (channel and video rows), shared between channels. With Only changes: most changes a run returns, with one channel row per channel on top (the rest of the changes come with the next run).

## `postedAfter` (type: `string`):

Only videos from about this time on: a date ('2026-10-01'), or an amount of time back from now ('7 days', '2 weeks', '1 month'). About, since YouTube words ages in days, weeks, months and years. Shorts show no dates, so this doesn't filter them.

## `minViews` (type: `integer`):

Only videos with at least this many views, as YouTube rounds them. Live streams in progress show none, so they are left out.

## `keywords` (type: `array`):

Only videos whose title has any of these words or phrases ('iphone', 'review'). Case and accents don't matter.

## `excludeWords` (type: `array`):

Leave out videos whose title has any of these words or phrases ('sponsored', '#shorts').

## `onlyChanges` (type: `boolean`):

Track your channels: each run returns a row per channel with what it gained (subscribers, total views, videos) and only what changed since the last run with the same channels and filters: new videos, removed videos, changed titles, streams that went live. The first run saves what's there as the baseline and returns it as firstRun. Schedule it (every hour, every day) to monitor channels.

## `changeTypes` (type: `array`):

Which changes Only changes returns. Leave empty for new videos, removed videos, changed titles and streams that went live.

## `viewsJumpPercent` (type: `integer`):

With View jumps among the changes: report a watched video whose views rose this much since the last report. Views are rounded, and a video under 1,000 views never counts.

## `alertWebhookUrl` (type: `string`):

Post each run's changes to Slack, Discord or Microsoft Teams (their incoming-webhook URL), or to any HTTPS endpoint that takes JSON (Zapier, Make, n8n). Switches on Only changes. The first run posts a short 'alerts are set up' message.

## `telegramBotToken` (type: `string`):

Post each run's changes to a Telegram chat through your own bot: its token from @BotFather (123456789:AAH...). Add the bot to the chat (to a channel as an admin that can post). Switches on Only changes.

## `telegramChatId` (type: `string`):

Where the bot posts: a public channel or group (@mychannel), or a chat id (-1001234567890 for a private group or channel; your own id for a direct message, from @userinfobot).

## `alertChangeTypes` (type: `array`):

Which changes are posted. Leave empty for new videos.

## `historyName` (type: `string`):

Keep a separate history for this monitor (a-z, 0-9 and hyphens). Leave empty to share the default one: histories are kept per channel and filters anyway.

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

Not needed: YouTube's channel pages answer Apify's servers directly. You can use your own proxies or Apify's datacenter proxies; residential proxies aren't available in this Actor.

## Actor input object example

```json
{
  "channels": [
    "@mkbhd"
  ],
  "maxVideos": 10,
  "maxShorts": 0,
  "maxStreams": 0,
  "maxPopular": 0,
  "originalTitles": true,
  "maxResults": 1000,
  "viewsJumpPercent": 25
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

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

No description

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

No description

## `growth` (type: `string`):

No description

## `changes` (type: `string`):

No description

## `live` (type: `string`):

No description

## `notFound` (type: `string`):

No description

## `allData` (type: `string`):

No description

## `runSummary` (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 = {
    "channels": [
        "@mkbhd"
    ],
    "maxVideos": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("akhil_rajesh/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 = {
    "channels": ["@mkbhd"],
    "maxVideos": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("akhil_rajesh/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 '{
  "channels": [
    "@mkbhd"
  ],
  "maxVideos": 10
}' |
apify call akhil_rajesh/youtube-channel-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,akhil_rajesh/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/fLUnhK1cgsvj13nz6/builds/Hz3jPoTvZn46S01lg/openapi.json
