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

YouTube channel scraper — turn @handles, channel URLs, or UC IDs into YouTube channel data: subscribers, video count, views, About text, country, and joined date. CRM-ready profiles with a stable channelId.

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

## Pricing

$1.99 / 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.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

**[YouTube Channel Scraper](https://apify.com/scrapemamba/youtube-channel-scraper)** is a **youtube channel scraper** for Apify: scrape YouTube `@handles`, `/channel/`, `/c/`, and `/user/` URLs, or raw `UC…` channel IDs into structured **youtube channel data** — title, description, subscriber count, video count, view count, country, joined date, canonical URL — and write each result to an Apify Dataset you can export as JSON, CSV, or Excel.

Built by **ScrapeMamba** as an **apify youtube scraper** Actor for **youtube scraping** at the channel level. For every input string the Actor resolves a canonical channel identity, then calls `/youtube/channel_details` and maps public About/profile statistics into flat fields. Failures become isolated `type: "error"` rows that still include your original `input`. Use it when you need a **youtube scraper** that turns messy channel references into a stable `channelId` — a practical way to **scrape YouTube** creator profiles without maintaining browser automation.

***

### Overview

Channel identity is the backbone of most YouTube analytics pipelines — a reliable `UC…` ID plus profile stats (subscribers, views, country, About). Hand collection does not scale; fragile scrapers break on UI changes; official API projects add quota overhead.

This Actor’s path:

1. You pass a `channels` list of handles, URLs, or IDs.
2. Each entry is resolved to a channel identity (`channelId`, and when applicable handle/URL context).
3. The Actor requests channel details from ScrapeMamba and maps public fields.
4. Up to **10 workers** process the list in parallel.
5. Success rows use `type: "channel"`; failures use `type: "error"` with the original `input` preserved for retries.
6. A `raw` payload is retained alongside mapped columns.

The result is a warehouse-ready channel dimension table keyed by `channelId`, with original lookup strings in `input` for lineage.

***

### Who this Actor is for

- **Market researchers and agencies** building competitor or creator rosters from mixed URL formats.
- **Growth and partnerships teams** qualifying YouTube leads before outreach.
- **Analytics / BI teams** needing a channel dimension table to join uploads and video facts.
- **Automation builders** who schedule Apify runs or call Actors from Python/JS ETL.
- **Pipelines** that continue into **Channel Videos**, **Channel Shorts**, **Video Scraper**, or **Search**.

#### Who this is not for

- **Not a comments scraper, email finder, or private-data tool.** This Actor returns **public creator profile / About statistics** only — display name, description, subscriber and video counts, views, country, joined date, and canonical URL. It does not harvest comment threads, scrape contact emails, or access private channel data.
- Choose a different Actor for keyword discovery (**YouTube Search Scraper**) or per-video stats (**YouTube Video Scraper**). This Actor is for **channel profile** resolution and metadata.

***

### What it does

- Accepts `@handles`, `youtube.com/@…` links, `/channel/UC…`, `/c/…`, `/user/…` URLs, or raw `UC…` IDs
- Resolves each target to a canonical `channelId` before fetching details
- Returns profile metadata and public statistics in a stable schema
- Batches multiple channels with **isolated per-item errors**
- Echoes the original lookup string in `input` on both success and error paths (errors always include `input`)
- Includes `raw` channel detail payload for advanced consumers
- Runs with up to **10 parallel workers**

***

### Why ScrapeMamba on Apify

ScrapeMamba keeps profile schemas stable so you can refresh creator rosters on a schedule without rewriting parsers when the YouTube UI shifts. Teams often want a managed **youtube data scraper** that joins cleanly with the rest of the Apify YouTube suite — this Actor is that profile layer.

On Apify you get Dataset exports (JSON / CSV / Excel), Apify Client and REST integration, schedules and webhooks, and pay-per-result economics instead of browser infrastructure. Use this Actor early: resolve profiles → list videos/Shorts → enrich videos → optionally pull subtitles or related graphs. For many workflows it is a strong **best youtube scraper** starting point when the first job is normalizing creator identity.

***

### What data can it extract?

Successful rows expose mapped fields such as:

| Field | Description |
|-------|-------------|
| `type` | Always `"channel"` on success |
| `channelId` | Canonical `UC…` channel identifier |
| `input` | Exact string you supplied for this row |
| `title` | Channel display name |
| `description` | Public About / description text when available |
| `subscriberCount` | Subscriber count when exposed |
| `videoCount` | Public video count when exposed |
| `viewCount` | Lifetime (or reported) view total when exposed |
| `country` | Country when shown publicly (may be `null`) |
| `joinedDate` | Channel joined date when available |
| `url` | Canonical channel URL |
| `raw` | Unwrapped backend channel detail object |

Error rows use `type: "error"` with:

| Field | Description |
|-------|-------------|
| `input` | Original channel string that failed |
| `error` | Error message string |

***

### Pricing

- **$1.99 per 1,000 results**

Billed on Apify for Dataset rows produced by the run. See the Store page for current packaging and free-tier details.

Store listing: <https://apify.com/scrapemamba/youtube-channel-scraper>

***

### Input

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `channels` | `string[]` | **Yes** | Channel IDs, `@handles`, or YouTube channel URLs |

#### Accepted formats

Each entry may be:

- Handle with at-sign: `@GoogleDevelopers`
- Handle URL: `https://www.youtube.com/@GoogleDevelopers`
- Channel ID URL: `https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw`
- Custom URL style: `/c/…` or legacy `/user/…` paths
- Bare channel ID: `UC_x5XG1OV2P6uZZ5FSM9Ttw`

The Actor resolves these via `resolveChannelId` before calling channel details. Prefer `@handle` or `UC…` when known; full URLs work for CRM exports that only store links.

#### Prefill / quick example

```json
{
  "channels": ["@GoogleDevelopers"]
}
```

#### Mixed batch example

```json
{
  "channels": [
    "@GoogleDevelopers",
    "https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw",
    "UCXuFOgbObldcQGwMwXiu62Q"
  ]
}
```

Empty or missing `channels` exits early before workers start.

***

### Output

#### Output types

| `type` | Meaning |
|--------|---------|
| `channel` | Successful profile extraction |
| `error` | Resolution or details failure; includes original `input` |

#### Successful example

```json
{
  "type": "channel",
  "channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw",
  "input": "@GoogleDevelopers",
  "title": "Google for Developers",
  "description": "Subscribe to join a community of creative developers...",
  "subscriberCount": 2450000,
  "videoCount": 6124,
  "viewCount": 312450000,
  "country": "US",
  "joinedDate": "2007-08-23",
  "url": "https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw",
  "raw": {}
}
```

(`raw` holds the unwrapped details object; truncated here.)

#### Error example

```json
{
  "type": "error",
  "input": "@this-handle-does-not-exist-xyz",
  "error": "Error: ..."
}
```

`input` is preserved so you can join failures back to the source row.

#### Downstream joins

Use `channelId` as the primary key for Channel Videos / Shorts. Keep `input` for audit trails. Filter `type == "channel"` before BI loads.

***

### How to scrape YouTube channel profiles on Apify

1. Open **[YouTube Channel Scraper](https://apify.com/scrapemamba/youtube-channel-scraper)** in the Apify Store.
2. Provide a small `channels` list — start with `@GoogleDevelopers` or one public competitor.
3. Run and confirm `type: "channel"`, a populated `channelId`, and expected stats in the **Dataset**.
4. Expand the list, then export JSON/CSV/Excel or wire schedules and webhooks.

#### Quick start checklist

1. Test one public `@handle`
2. Confirm `channelId` + core stats
3. Batch additional channels
4. Schedule or call via Apify API for production

***

### Local run notes

```bash
cd youtube-channel-scraper-js
cp .env.example .env
npm install
```

Provide input at `storage/key_value_stores/default/INPUT.json`:

```json
{
  "channels": ["@GoogleDevelopers"]
}
```

Then `node src/main.js`.

***

### YouTube scraper API examples (Apify)

Treat this Actor as a **youtube scraper api** for channel profiles: start a run through Apify, let ScrapeMamba resolve and fetch details, then consume Dataset items in any language.

#### cURL (start a run)

```bash
curl "https://api.apify.com/v2/acts/scrapemamba~youtube-channel-scraper/runs" \
  -H "Content-Type: application/json" \
  -d '{
    "channels": ["@GoogleDevelopers"]
  }'
```

Poll the run and list Dataset items from `defaultDatasetId`.

#### JavaScript (Apify Client)

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

const client = new ApifyClient();

const run = await client
  .actor('scrapemamba/youtube-channel-scraper')
  .call({
    channels: [
      '@GoogleDevelopers',
      'https://www.youtube.com/@GoogleDevelopers',
    ],
  });

const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const row of items) {
  if (row.type === 'channel') {
    console.log(row.channelId, row.title, row.subscriberCount);
  } else {
    console.error('Failed:', row.input, row.error);
  }
}
```

#### Python (youtube channel scraper python)

For a **youtube channel scraper python** / **youtube scraper python** workflow:

```python
from apify_client import ApifyClient

client = ApifyClient()

run = client.actor("scrapemamba/youtube-channel-scraper").call(
    run_input={
        "channels": [
            "@GoogleDevelopers",
            "https://www.youtube.com/channel/UC_x5XG1OV2P6uZZ5FSM9Ttw",
        ]
    }
)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item.get("type") == "channel":
        print(item["channelId"], item.get("title"), item.get("subscriberCount"))
```

#### What the Actor calls internally

1. Resolve input → channel identity (`resolveChannelId`).
2. `POST` to `/youtube/channel_details` with resolved `channel_id` / handle / URL context.
3. Map fields and push Dataset item with `raw`.

Prefer the Actor over reimplementing those steps so you keep Apify Dataset billing, logging, and orchestration.

***

### Pipeline patterns

#### Profile → catalogs → enrichment

1. Resolve creators here (`channelId`, stats, About).
2. Fetch uploads (**Channel Videos**) and/or Shorts (**Channel Shorts**).
3. Enrich videos with **YouTube Video Scraper**.
4. Optionally discover adjacent creators via **YouTube Search Scraper**.

#### CRM / lead flow

Import messy URLs into `channels` → run → score with `subscriberCount` / `videoCount` / `country` → push qualified `channelId`s into catalog scrapers. Snapshot counts with `runStartedAt` if you need growth history (`channelId` stays stable).

***

### Where teams use the data

Competitor and creator roster building; lead qualification; channel dimension tables for warehouses; seeds for videos / Shorts scrapers; geography and maturity signals (`country`, `joinedDate`); deduplicating the same creator listed under handle vs `/channel/` URL in CRM.

***

### Export and automation

| Tool | Role |
|------|------|
| Dataset **JSON / CSV / Excel** | Analysts, Sheets, one-off shares |
| **Apify Client** | JS/Python services |
| **REST API** | Any language / no-SDK scripts |
| **Schedules** | Nightly roster refresh |
| **Webhooks** | Kick off Channel Videos after profiles succeed |

Common pattern: webhook on success → backend reads Dataset → enqueues Channel Videos for new or updated `channelId`s.

***

### Error handling

- Bad Input (missing `channels`) → fail fast.
- Per-channel failures → Dataset error row with `input` + `error`; siblings continue.

```text
channels_ok  = rows where type == "channel"
channels_bad = rows where type == "error"
upsert dim_channel from channels_ok on channelId
insert scrape_errors(input, error, runId) from channels_bad
```

If a handle is ambiguous or renamed, try the full `@` URL or a known `UC…` ID.

***

### Best practices

1. **Validate with one public handle** before bulk CRM imports.
2. **Prefer `UC…` when known** — skips handle resolution ambiguity after renames.
3. **Keep `input` lineage** — explains mismatches in the warehouse.
4. **Null-safe stats** — `country`, `joinedDate`, and counts can be missing.
5. **Split huge rosters** — multiple scheduled runs for clearer monitoring.
6. **Dedupe by `channelId` after the run** if the same creator appears as handle + URL.
7. **Chain next Actors on `channelId`**, not display title.
8. **Document compliance** before continuous collection; snapshot counts if growth history matters.

***

### Troubleshooting

| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| Handle not found | Typo, rename, or non-public | Try full `@` URL or known `UC…` ID |
| Mix of channel + error rows | Bad inputs in batch | Use error `input` to correct source data |
| Stats look stale vs UI | Point-in-time scrape / UI rounding | Re-run later; treat counts as approximate |
| `country` is null | Not shown publicly | Allow nulls in schema |
| Local run has no channels | Missing INPUT.json | Add `storage/key_value_stores/default/INPUT.json` |
| Need upload titles, not profile | Wrong Actor | Use Channel Videos / Shorts scrapers |

***

### Limitations

- Missing, terminated, or non-resolvable channels produce error rows.
- Some profile fields may be `null` when YouTube does not expose them.
- Subscriber and view figures are public platform numbers — precision can differ from the UI.
- Public data only; you own compliance with terms and law.
- Does not paginate uploads or Shorts — use dedicated catalog Actors after `channelId`.
- Does not scrape comments, emails, or private settings — public profile metadata only.

***

### Compliance and responsible use

Use this Actor only for **public** channel metadata. You own compliance with YouTube’s terms, privacy laws, and internal policies. Do not access private data or evade protections. ScrapeMamba and Apify provide tooling; **you** own the compliance outcome.

***

### FAQ

#### How to scrape YouTube channels with this Actor?

Pass `@handle`, channel URL, or `UC…` ID in the `channels` array, start the run, and export the Dataset (or pull it via Apify API/Client). That is the supported path to **scrape YouTube** creator profiles into structured rows.

#### How do I get YouTube channel data for a competitor list?

Load handles or URLs into `channels`, run the Actor, and filter `type == "channel"`. You get `channelId`, subscriber/video/view counts, About text, and related fields ready for CRM scoring or warehouse joins.

#### Can I call this as a YouTube scraper API?

Yes. Start runs through Apify’s REST API or Client with the same JSON input. The Actor resolves channels, calls ScrapeMamba’s channel-details path, and writes Dataset items you can poll and export — a managed API-style workflow without hosting scrapers yourself.

#### How do I use YouTube channel scraper Python code with Apify?

Install `apify-client`, call `client.actor("scrapemamba/youtube-channel-scraper").call(...)` with a `channels` list, then iterate Dataset items.

#### What formats does `channels` accept?

`@handles`, `/channel/`, `/c/`, `/user/` URLs, `youtube.com/@…` links, and raw `UC…` IDs. The Actor resolves them before calling `/youtube/channel_details`.

#### Handle not found — what should I try?

Verify spelling, try the full `https://www.youtube.com/@…` URL, or supply a known `UC…` channel ID from a previous scrape or YouTube share dialog.

#### Why does the error row include `input`?

So you can map failures back to the exact CRM/sheet value that failed, even when no `channelId` was resolved.

#### Can I get a channel’s videos from this Actor?

No. This Actor returns profile metadata. Use **YouTube Channel Videos Scraper** or **YouTube Channel Shorts Scraper** with the resolved `channelId`.

#### Does this scrape comments or emails?

No. Output is public channel profile and About statistics only — not comment threads or harvested contact emails.

#### How does pricing work?

**$1.99 per 1,000 results** on Apify for this Actor. Confirm details on the Store page when budgeting large rosters.

#### Are subscriber counts always present?

Usually for public channels, but treat numeric fields as nullable. UI rounding and temporary unavailability can yield gaps.

#### How do I refresh a roster weekly?

Save an Actor task with your `channels` list (or generate Input dynamically), attach an Apify Schedule, and optionally a webhook into your warehouse loader.

#### What is stored in `raw`?

The unwrapped channel details object from ScrapeMamba after resolution. Use mapped fields for BI; use `raw` for attributes not yet flattened.

***

### Related ScrapeMamba Actors

| Actor | Best for |
|-------|----------|
| [YouTube Channel Videos Scraper](https://apify.com/scrapemamba/youtube-channel-videos-scraper) | Upload catalogs |
| [YouTube Channel Shorts Scraper](https://apify.com/scrapemamba/youtube-channel-shorts-scraper) | Shorts catalogs |
| [YouTube Video Scraper](https://apify.com/scrapemamba/youtube-video-scraper) | Per-video enrichment |
| [YouTube Search Scraper](https://apify.com/scrapemamba/youtube-search-scraper) | Keyword discovery |

**Suggested pipeline:** **YouTube Channel Scraper** → Channel Videos / Shorts → Video Scraper (and optionally Search for net-new creators).

# Actor input Schema

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

Channel IDs, @handles, or YouTube channel URLs.

## Actor input object example

```json
{
  "channels": [
    "https://www.youtube.com/@IShowSpeed"
  ]
}
```

# Actor output Schema

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

Default dataset items produced by this Actor.

# 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/@IShowSpeed"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapemamba/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/@IShowSpeed"] }

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

```

## MCP server setup

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