# YouTube Channel Scraper | Rich Channel Info & Videos (`hridayrungta/youtube-channel-scraper`) Actor

An alternative YouTube Data API with no limits or quotas. Scrape one or many channels for rich info (subscribers, total views, creation date, country, verified badge, links) plus that channel's videos, paginated. No login, no browser, no proxy. $0.002/run + $0.004/channel + $0.00015/video.

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

## Pricing

from $2.00 / 1,000 actor starteds

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/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 | Rich Channel Info & Videos

An alternative YouTube Data API with no limits or quotas. Scrape one or many YouTube channels for rich channel info — subscribers, total views, creation date, country, verified badge, avatar/banner, external links — plus that channel's videos, paginated. No login, no API key sign-up, no browser, no proxy.

### What you get

- **Channel info** (one row per channel): channel id, handle, title, description, subscriber count (exact number + raw text), total video count, total view count, join/creation date, country, verified badge, avatar url, banner url, canonical channel url, external links (website, socials).
- **Channel videos**: that channel's videos (title, view count, published time, duration, thumbnail), paginated past the first page via YouTube's own internal "innertube" API.
- **Incremental mode**: track one or many channels' videos over time. Each run after the first returns only videos published since the last run — no re-scraping, no re-paying for old videos.

Turn either mode off with `scrapeChannelInfo` / `scrapeVideos` if you only need one.

### How this works (honestly)

YouTube's own pages embed the same JSON its front-end uses to render itself server-side. This Actor reads two channel surfaces:

1. **`/about`** — for channel info. Confirmed live: this page's `ytInitialData` already carries an "about" panel (`aboutChannelRenderer`) with total view count, join date, country and external links — none of which appear on the plain channel header. The header itself (shared with the `/videos` page) supplies the avatar, banner, and verified checkmark. A `microformat` block on the same page carries the subscriber count as an exact integer, used in preference to parsing the "21.3M subscribers" display text.
2. **`/videos`** — for the channel's video grid, plus YouTube's internal `/youtubei/v1/browse` endpoint for further pages via the page's own continuation token, anonymously.

No headless browser, no residential proxy, no login wall to fight — because there isn't one on either surface. That keeps this fast, reliable, and cheap, and that cost is passed on to you.

### Incremental mode (channel videos)

Set `mode: "changes"`. On a channel's first run, it seeds from `firstRunSince` (default 30 days back). Every run after that resumes from a per-channel high-water mark stored in a key-value store. Channel grids only expose a relative publish time ("12d ago", "2w ago", "1mo ago"), not an exact timestamp, so the mark uses that as an approximate cutoff; a remembered set of video ids is the real safety net that guarantees no video is ever billed twice, even right at the boundary. A run cut short by your budget still advances the mark safely. This only affects channel *videos* — the channel-info row is always fetched fresh.

### Input at a glance

| Field | Description |
|---|---|
| `channels` | Channels to scrape — a handle (`@nasa`), a full URL, or a `UC...` id, one per line. |
| `scrapeChannelInfo` | Emit the enriched channel-info row (default on). |
| `scrapeVideos` | Emit the channel's videos (default on). |
| `mode` | `"all"` (default) or `"changes"` (incremental) — videos only. |
| `maxItems` | Budget cap on billed video rows across all channels. |
| `maxPagesPerSource` | Cap on innertube pagination pages per channel. |
| `firstRunSince` | How far back a channel's first incremental run looks (e.g. `"30 days"`). |

### Billing (pay-per-event)

| Event | Price |
|---|---|
| Actor started | $0.002 — charged once per run, regardless of results |
| Channel scraped | $0.004 — one enriched metadata row per channel |
| Video scraped | $0.00015 — one row per channel video |

Real-measured cost on Apify's own infrastructure is dominated by fixed per-run overhead (no browser, no proxy), so pricing is a flat per-event rate with no hidden per-GB or "with extra fields" tier — every row already includes everything this Actor can extract for it. The per-video price undercuts the market's cheapest volume tier for a plain video row, and the channel-info row is priced for the extra "/about" page fetch and enrichment behind it.

# Actor input Schema

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

One or more YouTube channels, one per line: a handle ("@nasa"), a full channel/handle URL, or a UC... channel id.

## `scrapeChannelInfo` (type: `boolean`):

Emit one enriched metadata row per channel: subscriber/video/total-view counts, join date, country, verified badge, avatar/banner, description, external links.

## `scrapeVideos` (type: `boolean`):

Emit that channel's videos (title, view count, published time, duration, thumbnail), paginated past the first page.

## `mode` (type: `string`):

Only affects "Scrape channel videos" above. "all": every video the run reaches, every time. "changes": only videos new since your last run of that channel.

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

Cost cap on billed video rows across all channels combined. Has no effect on channel-info rows.

## `maxPagesPerSource` (type: `integer`):

How many innertube continuation pages to follow per channel's video listing before moving on - a safety cap independent of Max video rows.

## `firstRunSince` (type: `string`):

A channel's first incremental run only takes videos published since this date/span. Default "30 days"; "all" to take everything the run reaches.

## `maxRetries` (type: `integer`):

Retries with backoff for network errors and 5xx responses.

## `stateStoreName` (type: `string`):

Name of the key-value store (in YOUR account) that holds the high-water mark per channel. Leave blank for the default.

## `stateNamespace` (type: `string`):

Advanced: an explicit namespace for the mark key. Leave blank to namespace by your Apify user id automatically.

## Actor input object example

```json
{
  "channels": [
    "https://www.youtube.com/@nasa"
  ],
  "scrapeChannelInfo": true,
  "scrapeVideos": true,
  "mode": "all",
  "maxItems": 100,
  "maxPagesPerSource": 10,
  "firstRunSince": "30 days",
  "maxRetries": 3,
  "stateStoreName": "",
  "stateNamespace": ""
}
```

# Actor output Schema

## `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 = {
    "channels": [
        "https://www.youtube.com/@nasa"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("hridayrungta/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": ["https://www.youtube.com/@nasa"] }

# Run the Actor and wait for it to finish
run = client.actor("hridayrungta/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": [
    "https://www.youtube.com/@nasa"
  ]
}' |
apify call hridayrungta/youtube-channel-scraper --silent --output-dataset

```

## MCP server setup

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