# YouTube Channel Scraper (`thenetaji/youtube-channel-scraper`) Actor

Scrape one or many YouTube channels by URL, @handle, username, or ID. Collect channel details, videos, Shorts, live streams, playlists, community posts, store products, or a search inside the channel.

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

## 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Channel Scraper

The Actor reads one or many public YouTube channels and collects the sections you select — channel details, videos, Shorts, live streams, playlists, community posts, home shelves, store products, or a search performed inside the channel. Channels are accepted as URLs, `@handles`, legacy usernames, or `UC…` IDs, and are resolved to a channel ID automatically. No YouTube account, API key, or cookie is required.

### Accepted input

| Field | Type | Default | Description |
|---|---|---|---|
| `channel_sources` | array | — | Required. Channel URLs, `@handles`, usernames, or `UC…` IDs. |
| `channel_sections` | multi-select | `["about","videos"]` | Required. Sections to collect from every channel. |
| `channel_search_term` | string | — | Required when `search_results` is selected. |
| `maxItems` | integer | `100` | Maximum rows saved across all channels and sections. `0` removes the limit. |
| `region_code` | string | `US` | Two-letter country code used to localize results. |
| `language_code` | string | `en` | Language code for result text. |

```json
{
  "channel_sources": [
    { "url": "https://www.youtube.com/@TED" },
    { "url": "@veritasium" },
    { "url": "UC_x5XG1OV2P6uZZ5FSM9Ttw" }
  ],
  "channel_sections": ["about", "videos", "shorts"],
  "maxItems": 200,
  "region_code": "US"
}
```

### The sections

| Value | Produces | Paginates |
|---|---|---|
| `about` | One profile row per channel | — |
| `videos` | Long-form uploads, newest first | Yes |
| `shorts` | Shorts, newest first | Yes |
| `live_streams` | Past and scheduled live streams | No |
| `playlists` | Playlists the channel publishes | Yes |
| `community_posts` | Community tab posts, with attachments | Yes |
| `home_sections` | The shelves shown on the channel home tab | No |
| `store_products` | Products listed on the channel store | No |
| `search_results` | Results of `channel_search_term` inside the channel | Yes |

Sections are collected per channel in the order listed above, and `maxItems` is a budget shared across all of them. Asking for `about`, `videos`, and `shorts` from three channels with `maxItems: 100` will not necessarily reach the third channel's Shorts — raise the limit or run the sections separately when even coverage matters.

### How channel targets are resolved

A `UC…` ID is used directly. Anything else — a URL, an `@handle`, or a legacy username — is sent to YouTube's own resolver first, and the resulting channel ID is written to the run log so the interpretation is visible.

Resolution costs one extra request per channel, and only for targets that are not already IDs. Supplying `UC…` IDs skips it entirely.

### Response fields

One row per item. Which fields appear depends on the section — a profile row and a community post have little in common.

Common to every row:

| Field | Contents |
|---|---|
| `recordType` | Section that produced the row, such as `channel_about` or `channel_videos` |
| `source` | The channel target as supplied in the input |
| `url` | Canonical URL, derived from the row's identifier |
| `position` | One-based position within the run |
| `meta` | The parent channel's profile, on paginated sections |

Channel details (`about`):

| Field | Contents |
|---|---|
| `channelId`, `title`, `description` | Channel identity |
| `channelHandle` | The `@handle` |
| `subscriberCount`, `subscriberCountText` | Subscriber count, numeric and displayed |
| `videosCount`, `viewCount` | Lifetime totals |
| `avatar`, `banner` | Image sets |
| `country`, `joinedDate` | Declared country and creation date |
| `keywords` | Channel tags |
| `links` | Public links listed on the channel |

Videos, Shorts, live streams, playlists, and search results:

| Field | Contents |
|---|---|
| `type` | `video`, `shorts`, or `playlist` |
| `videoId` or `playlistId` | Item identifier |
| `title`, `description` | Item text |
| `viewCount`, `viewCountText` | View counts |
| `lengthText` | Duration |
| `publishedTimeText`, `publishedAt` | Relative and ISO 8601 publication time |
| `videoCount` | Number of videos, on playlist rows |
| `thumbnail` | Thumbnail images |

Community posts:

| Field | Contents |
|---|---|
| `postId` | Post ID |
| `contentText` | Post body |
| `authorText`, `authorChannelId`, `authorChannelHandle` | Author |
| `replyCount` | Reported replies |
| `attachment` | Image, poll, or video attached to the post |

```json
{
  "recordType": "channel_about",
  "channelId": "UCAuUUnT6oDeKwE6v1NGQxug",
  "title": "TED",
  "channelHandle": "@TED",
  "subscriberCount": 27700000,
  "subscriberCountText": "27.7M",
  "videosCount": "5745",
  "viewCount": "3199315747",
  "country": "United States",
  "joinedDate": "2006-12-06",
  "url": "https://www.youtube.com/channel/UCAuUUnT6oDeKwE6v1NGQxug"
}
```

### Behaviour on partial results

A channel that cannot be resolved is logged and skipped, and the run continues with the remaining channels. A section YouTube declines to serve for one channel is logged and skipped, and the other sections for that channel still run. Rows already collected are kept in both cases. The run fails only when no supplied target resolved to a public channel at all.

This matters on large input lists: one deleted or renamed channel among two hundred costs that channel's rows, not the run.

Promoted results carrying `type: "ad"` are dropped before rows are saved, so they are neither stored nor billed.

### Frequently asked questions

**Which forms of channel address are accepted?**
Full channel URLs in any form, `@handles` with or without the `@`, legacy `/user/` names, and `UC…` IDs. Mixing forms in one run is fine. Only `UC…` IDs skip the resolution request.

**Why did a channel return fewer videos than it has published?**
`maxItems` is shared across every channel and section in the run, so it is usually the limit that was reached first. Where a channel genuinely has more, the video and Shorts tabs paginate until YouTube stops serving pages.

**Why can live streams and home shelves not be paginated?**
YouTube serves those tabs as a single page with no cursor to follow. The Actor collects what that page contains and moves on. Videos, Shorts, playlists, community posts, and in-channel search all paginate normally.

**Can videos be sorted by popularity instead of newest?**
Not currently. YouTube's channel tabs accept a sort parameter but reject every value except newest, so offering the other options would only produce failed sections. Sorting the collected rows on `viewCount` afterwards gives the same result for a fully collected tab.

**Why is `store_products` empty?**
Most channels have no store. The section returns rows only for channels that have configured one, and returns nothing rather than failing for those that have not.

**How is `subscriberCount` different from `subscriberCountText`?**
`subscriberCountText` is what YouTube displays, such as `27.7M`. `subscriberCount` is the number behind it, `27700000`. YouTube rounds public subscriber counts to three significant figures above 1,000, so both are approximations — that rounding is YouTube's, not the Actor's. `videosCount` and `viewCount` are exact.

**Is a YouTube account or API key required?**
No. Only publicly visible channel content is read, with no credentials or logged-in session, and no YouTube Data API quota is consumed.

### Related Actors

| Actor | Purpose |
|---|---|
| [YouTube Video Scraper](https://apify.com/thenetaji/youtube-video-scraper) | Full metadata and transcripts for known videos and Shorts |
| [YouTube Search Scraper](https://apify.com/thenetaji/youtube-search-scraper) | Keyword search, hashtags, Trending, Hype, and Home feeds |
| [YouTube Comments Scraper](https://apify.com/thenetaji/youtube-comments-scraper) | Comments from videos, Shorts, and community posts |
| [YouTube Playlist Scraper](https://apify.com/thenetaji/youtube-playlist-scraper) | Playlist metadata and every video in it |

# Actor input Schema

## `channel_sources` (type: `array`):

One or more public YouTube channels. Full URLs, @handles, usernames, and UC channel IDs are accepted.

## `channel_sections` (type: `array`):

Choose the channel sections to collect. Channel details produces one profile record per channel.

## `channel_search_term` (type: `string`):

Words or a phrase to find when Search within channel is selected.

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

Maximum number of primary records to save across all targets. Set 0 to continue until no more pages remain.

## `region_code` (type: `string`):

Optional two-letter country code used to localize results, such as US, IN, or DE.

## `language_code` (type: `string`):

Optional language code used to localize result text, such as en, es, or pt-BR.

## Actor input object example

```json
{
  "channel_sources": [
    {
      "url": "https://www.youtube.com/@TED"
    }
  ],
  "channel_sections": [
    "about",
    "videos"
  ],
  "channel_search_term": "behind the scenes",
  "maxItems": 20,
  "region_code": "US",
  "language_code": "en"
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing all scraped data

# 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 = {
    "channel_sources": [
        {
            "url": "https://www.youtube.com/@TED"
        }
    ],
    "maxItems": 20,
    "region_code": "US"
};

// Run the Actor and wait for it to finish
const run = await client.actor("thenetaji/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 = {
    "channel_sources": [{ "url": "https://www.youtube.com/@TED" }],
    "maxItems": 20,
    "region_code": "US",
}

# Run the Actor and wait for it to finish
run = client.actor("thenetaji/youtube-channel-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 '{
  "channel_sources": [
    {
      "url": "https://www.youtube.com/@TED"
    }
  ],
  "maxItems": 20,
  "region_code": "US"
}' |
apify call thenetaji/youtube-channel-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/if13FYXh9goBNQbSl/builds/bDGjzHAYl4krtBpfb/openapi.json
