# YouTube Channel Statistics Scraper (`khadinakbar/youtube-channel-statistics-scraper`) Actor

Bulk enrich known YouTube channels with public statistics only — subscribers, views, video count, joined date, country. No recent videos. Cookieless, MCP-ready.

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

## Pricing

from $3.50 / 1,000 channel statistics

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

### What does YouTube Channel Statistics Scraper do?

Bulk-enrich **known** YouTube channels with lean public **statistics only**: subscribers, lifetime views, video count, joined date, country, handle, and avatar. Paste channel URLs, `@handles`, or `/channel/UC…` IDs and get one predictable dataset row per channel — focused on channel counters rather than video catalogs.

This Actor is for analysts and AI agents that already know which channels matter and need a fast size/reach check before they spend on full profile + video scrapes.

### Best fit for this Actor

- Enrich a CRM or watchlist of known YouTube channels with public counters.
- Compare subscriber / view / video totals across a short list before outreach.
- Feed MCP or enrichment pipelines when you need stats, channel-counter catalogs.

For profile **plus recent videos/Shorts**, use [YouTube Channel Scraper](https://apify.com/khadinakbar/youtube-channel-scraper). For keyword channel discovery, use [YouTube Channel Search Scraper](https://apify.com/khadinakbar/youtube-channel-search-scraper). For video lists only, use [YouTube Channel Videos Scraper](https://apify.com/khadinakbar/youtube-channel-videos-scraper). For SocialBlade ranks/earnings estimates, use a SocialBlade-oriented Actor instead.

### Practical scenario

A media buyer pastes `@Apify` and `https://www.youtube.com/@GoogleDevelopers`, keeps `includeDescription` on, and runs with the default Residential proxy. The Actor returns one stats row each: `subscriberCount`, `viewCount`, `videoCount`, `joinedDateText`, and `country` when YouTube exposes them. A fake handle finishes `SUCCEEDED` with `VALID_EMPTY` and keeps `channel-stats` at zero. Channels that clear the size bar can later be sent to the full channel scraper for video listings.

### Quick start input

```json
{
  "channelUrls": ["@Apify"],
  "maxChannels": 2,
  "includeDescription": true,
  "providerMode": "auto"
}
```

`channelUrls` accepts `@handles`, plain handles, `/channel/UC…` IDs, `/c/` or `/user/` paths, and full YouTube channel URLs. Duplicates (URL vs handle for the same channel) are collapsed before any fetch.

### Input reference

| Field | Type | What it controls |
|---|---|---|
| `channelUrls` | array | Known channel URLs, handles, or UC IDs. Prefill `@Apify`. Max 100 unique after dedupe. |
| `maxChannels` | integer | Hard cap after dedupe. Default 100. Prefill 2 for cheap quality tests. |
| `includeDescription` | boolean | Include a short about-text preview. Default true. |
| `providerMode` | enum | `auto` (native then providers), `direct`, or `providerOnly`. |
| `country` / `language` | string | YouTube `gl` / `hl` locale. Defaults `US` / `en`. |
| `proxyConfiguration` | object | Apify proxy for native fetches. Residential by default. |

### What data you receive

One dataset item is one public channel statistics row. The contract is stats-only (sibling Actors cover video listings).

```json
{
  "input": "@Apify",
  "channelId": "UCTgwcoeGGKmZ3zzCXN2qo_A",
  "channelUrl": "https://www.youtube.com/channel/UCTgwcoeGGKmZ3zzCXN2qo_A",
  "handle": "@Apify",
  "title": "Apify",
  "description": "Full-stack web scraping and automation platform...",
  "subscriberCount": 29200,
  "subscriberCountText": "29.2K subscribers",
  "viewCount": 13548406,
  "viewCountText": "13,548,406 views",
  "videoCount": 288,
  "videoCountText": "288 videos",
  "joinedDateText": "Joined Jan 4, 2017",
  "country": "Czechia",
  "isVerified": false,
  "avatarUrl": "https://yt3.googleusercontent.com/...",
  "keywords": ["scraping", "automation"],
  "source": "youtube",
  "provider": "youtube",
  "scrapedAt": "2026-01-15T12:00:00.000Z"
}
```

| Field | Meaning |
|---|---|
| `subscriberCount` / `viewCount` / `videoCount` | Parsed public counters |
| `joinedDateText` / `country` | Public About fields when YouTube shows them |
| `source` / `provider` | Provenance: `youtube`, `scrapecreators`, or `sociavault` |
| `scrapedAt` | ISO-8601 collection time |

`OUTPUT` and `RUN_SUMMARY` in the default key-value store hold `outcome`, `itemsPushed`, `channelsFound`, and `chargedEventCounts`.

### Use through the API

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~youtube-channel-statistics-scraper/runs" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"channelUrls":["@Apify"],"maxChannels":1}'
```

Download rows as JSON, CSV, Excel, or HTML from the Dataset tab.

### Use with AI agents through Apify MCP

> Enrich these known YouTube channels with public statistics only: @Apify. Return channelId, handle, subscriberCount, viewCount, videoCount, joinedDateText, country, and source. Keep the job to channel stats (use sibling Actors for video catalogs).

Connect via <https://mcp.apify.com>. Read `OUTPUT.outcome` and `itemsPushed` to interpret empty datasets. Cost signal: about `$0.0035` per found channel plus platform usage. Missing channels surface as `VALID_EMPTY` and keep `channel-stats` at zero.

### Connect the workflow

- Need recent videos too? After this stats pass, continue with [YouTube Channel Scraper](https://apify.com/khadinakbar/youtube-channel-scraper) when you want profile detail plus recent videos/Shorts.
- Still discovering channels? Start with [YouTube Channel Search Scraper](https://apify.com/khadinakbar/youtube-channel-search-scraper) for keyword discovery, then enrich known matches here for lean counters.
- Need emails from channel About? Use [YouTube Channel Email Extractor](https://apify.com/khadinakbar/youtube-channel-email-extractor) after you confirm the handle exists and meets your size bar.

### Pricing

This Actor uses Pay per event plus Apify platform usage. The live Pricing tab is the current source of truth for billing details.

| Event | Price | When it charges |
|---|---|---|
| `apify-actor-start` | $0.00005 | Once per run |
| `channel-stats` | **$0.0035** | Per persisted valid statistics row |

Billing unit: 1 `channel-stats` event per persisted valid statistics row. Worked example: 1 row (`@Apify` prefill) ≈ `$0.0035` in result events plus a few seconds of Apify platform usage (passed through). 10 rows ≈ `$0.035` in `channel-stats` if all resolve. Invalid inputs and missing channels keep `channel-stats` at zero.

### How it works

1. Normalize and deduplicate channel URLs, `@handles`, and UC IDs.
2. Fetch the public YouTube `/about` page and parse `ytInitialData` (stats only).
3. On native block or empty parse, fall through to owner-managed ScrapeCreators, then SociaVault.
4. Charge `channel-stats` for found rows, then write the dataset item.
5. Always write `OUTPUT` + `RUN_SUMMARY` with an honest outcome from this set:

```text
COMPLETE | PARTIAL | VALID_EMPTY | INVALID_INPUT | UPSTREAM_FAILED | CONFIG_ERROR
```

### Best results tips

- Prefer `@handles` or `/channel/UC…` IDs over ambiguous vanity paths.
- Keep batches small for MCP canaries; raise `maxChannels` only when you need bulk enrichment.
- Leave `providerMode` on `auto` so Residential native fetches can fall back to providers when YouTube serves a consent or empty page.

### Recovery and scope notes

- Native YouTube HTML can be intermittent; `auto` recovers via owner-managed providers. Prefer `providerMode: "auto"` when Residential returns an empty About page.
- Public About fields such as `joinedDateText` and `country` appear only when YouTube shows them on the About surface.
- This Actor's dataset contract is channel statistics; use sibling Actors when you need recent videos.
- Recovery: retry with `providerMode: "auto"`, confirm the handle/URL resolves in a browser, and open an Issue and include the Console run URL when providers also return empty.

### Builder's note

I built this as a stats-only SKU after learning that most channel enrichment jobs only need public counters. I found that YouTube's About `ytInitialData` already carries subscribers, views, videos, joined date, and country for many channels, so one HTTP About fetch per target is enough and provider calls stay as recovery. My goal was a predictable mid-pack price that stays distinct from the fuller channel scraper that bills separately for video rows.

### Legal and responsible use

This Actor collects publicly visible YouTube channel metadata only. It runs cookieless against public pages and optional owner-managed providers; it does not use a Google OAuth token or the official YouTube Data API. You are responsible for complying with YouTube Terms of Service, applicable privacy laws, and your own data-use policies. Use results for legitimate research, enrichment, and monitoring workflows.

YouTube is a trademark of Google LLC. This independent Actor is not affiliated with, associated with, or endorsed by YouTube or Google.

### FAQ

**Does this return recent videos?** Video listings stay with `youtube-channel-scraper` and `youtube-channel-videos-scraper`. This Actor returns channel statistics.

**Do I need a YouTube API key?** The Actor is cookieless and uses public page data plus optional owner provider fallbacks.

**What if a channel is missing?** The Actor returns `SUCCEEDED` with `VALID_EMPTY` for that input and keeps `channel-stats` at zero.

### Support

Open an Issue on the Actor page with the run ID and input (redact secrets). Custom enrichment workflows are available on request.

# Changelog

This Actor's version history is a separate document: https://apify.com/khadinakbar/youtube-channel-statistics-scraper/changelog.md

# Actor input Schema

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

Known YouTube channels to enrich with public statistics. Accepts https://www.youtube.com/@handle, /channel/UC…, /c/ or /user/ paths, bare @handles, or plain handles. Deduplicates URL vs handle for the same channel. Does NOT discover channels by keyword — use youtube-channel-search-scraper for discovery. Does NOT return recent videos.

## `maxChannels` (type: `integer`):

Hard cap on unique channels processed after dedupe. Defaults to 100. Lower this to bound spend. Each found channel costs $0.0035 as channel-stats.

## `includeDescription` (type: `boolean`):

When true, include a short public channel description preview (truncated). Defaults to true. Set false for counters-only rows.

## `providerMode` (type: `string`):

auto tries the native YouTube about page first, then owner-managed public-data API fallbacks. direct uses native YouTube only. providerOnly uses owner-managed public-data APIs only (fails with CONFIG_ERROR if those secrets are missing).

## `country` (type: `string`):

YouTube gl country code for page locale and residential proxy pinning. Defaults to US.

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

YouTube hl language code for page locale. Defaults to en.

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

Apify proxy for native YouTube fetches. Defaults to Residential when omitted. Disable only for local debugging. Not a YouTube login session.

## Actor input object example

```json
{
  "channelUrls": [
    "@Apify",
    "https://www.youtube.com/@GoogleDevelopers",
    "UC_x5XG1OV2P6uZZ5FSM9Ttw"
  ],
  "maxChannels": 2,
  "includeDescription": true,
  "providerMode": "auto",
  "country": "US",
  "language": "en",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

One statistics row per found YouTube channel (no video listings).

## `output` (type: `string`):

Final outcome, itemsPushed, channelsFound, and chargedEventCounts.

## `runSummary` (type: `string`):

Per-channel outcomes, source counts, and billing counters.

# 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": [
        "@Apify"
    ],
    "maxChannels": 2,
    "includeDescription": true,
    "providerMode": "auto",
    "country": "US",
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/youtube-channel-statistics-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": ["@Apify"],
    "maxChannels": 2,
    "includeDescription": True,
    "providerMode": "auto",
    "country": "US",
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/youtube-channel-statistics-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": [
    "@Apify"
  ],
  "maxChannels": 2,
  "includeDescription": true,
  "providerMode": "auto",
  "country": "US",
  "language": "en"
}' |
apify call khadinakbar/youtube-channel-statistics-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,khadinakbar/youtube-channel-statistics-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/mIxUxnbVIjlSbb1rG/builds/3PcUOloR8bsXULVJf/openapi.json
