# 🔥Fast Youtube Channel Scraper (`aimscrape/youtube-channel-scraper`) Actor

Extract public channel metadata from YouTube @handles, channel IDs, and channel URLs. Collect descriptions, images, subscriber and video counts, total views, verification, and external links when available.

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

## Pricing

from $0.75 / 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/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 Scraper do?

**YouTube Channel Scraper** extracts public channel metadata from [YouTube](https://www.youtube.com/) @handles, channel IDs, and channel URLs. Collect channel names, descriptions, images, subscriber counts, video counts, total views, verification status, and public external links when available. Results are stored in a structured dataset for export or access through the Apify API.

The Actor collects publicly available YouTube channel data.

### How to scrape YouTube channels

1. Open **Input** and add targets to **YouTube handles, channel IDs, or channel URLs**.
2. Start with a few channels to check the data available for your use case.
3. Follow progress in the run log and open **Channels** in the **Output** tab.
4. Download results as JSON, CSV, Excel, or another format supported by Apify.

Use the Actor's **API** tab for programmatic runs and Apify scheduling for recurring collection. Compare separate runs using `crawledAt` to track changes.

### Why use YouTube Channel Scraper?

- Compare creator channels using public audience size, video counts, and total views.
- Maintain a channel directory with stable IDs, handles, descriptions, and images.
- Collect public channel links for research and reporting.

### Input

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

`channels` is required and accepts **1 to 100,000 entries**. Supported formats:

| Format | Example |
| --- | --- |
| @handle | `@YouTube` |
| Channel ID | `UCBR8-60-B28hp2BmDPdntcQ` |
| Handle URL | `https://www.youtube.com/@YouTube` |
| Channel-ID URL | `https://www.youtube.com/channel/UCBR8-60-B28hp2BmDPdntcQ` |

URLs must use HTTPS and `www.youtube.com`.
A trailing slash is allowed. International handles and percent-encoded handle
URLs are supported. Remove surrounding spaces, query parameters, and fragments.
Video, Shorts, playlist, and `youtu.be` links are not accepted. Bare usernames
and YouTube `/c/` or `/user/` URLs are not accepted. This Actor does not search
by channel title.

The input form requires each entry to have one of the supported shapes above,
but deliberately does not restrict the characters after `@`. The Actor validates
each entry before adding it to the queue. Valid entries are collected; invalid
handles are stored with `status: "invalid_input"` without a YouTube request. One
invalid handle does not stop other entries. For example, both `@hm_son7` and
`@messibrasilhd_` pass the input form, then runtime validation classifies the
latter as `invalid_input`. Empty strings and unsupported input shapes are rejected
by the input form. The list itself must still contain 1 to 100,000 strings.

Handle spelling is normalized to lowercase; channel IDs keep their original
case. Repeated syntactic aliases such as `@YouTube` and its handle URL are
processed once. A handle and a channel ID that refer to the same channel remain
separate requested targets. Provide one form per channel if you want one row per
channel.

When YouTube resolves a requested handle through a different channel address or
returns a different canonical handle, the Actor follows that resolution and
checks the returned channel ID. `username` keeps your normalized requested
identity; `handle` and `profileUrl` reflect the public handle YouTube reports.

Repeated invalid strings are also processed once. Credentials recognized in
invalid strings are redacted before output; identical redacted values share one
result.

### What data can the Actor extract?

Every result has the same fields. Missing optional values are explicit `null`,
and real zero counts are preserved.

| Fields | Meaning |
| --- | --- |
| `status`, `username`, `crawledAt` | Result status, requested identity, and result time. For `invalid_input`, `username` retains the submitted string with recognizable credentials redacted. |
| `requestedUrl` | Normalized requested channel URL, before address resolution; null for `invalid_input`. |
| `isRedirected` | Whether the lookup followed another channel address returned by YouTube; null when unknown. |
| `handleMatchesInput` | Whether the reported handle matches the requested handle; null for channel-ID inputs or unavailable handles. |
| `id`, `channelUrl`, `handle` | Channel ID, canonical channel-ID URL, and reported public handle. |
| `fullName`, `title` | Public channel display name. Both fields contain the same value. |
| `profileUrl` | Public handle URL, such as `https://www.youtube.com/@example_creator`; null when unavailable. |
| `description`, `keywords` | Public description and raw channel keyword string. |
| `avatarUrl`, `bannerUrl`, `verified` | Public images and verification/official artist badge indication. |
| `subscriberCount`, `videoCount`, `viewCount` | Public subscriber, video, and total channel view counts. |
| `country`, `joinedDate` | Channel-reported country label and join date (`YYYY-MM-DD`). |
| `externalLinks` | Public URLs from returned channel About metadata. |

Counts expanded from abbreviated values such as `12.5K` are **estimates** (`12500`),
not exact underlying counts. Hidden or absent counts are `null`. The Actor requests
English page data. Optional About fields, including views, country, join date,
and links, depend on what YouTube returns in the page. `externalLinks: null`
means links were unavailable; `[]` means an empty links list was returned.
Image URLs may expire. No email-address lookup is performed.

Age-restricted channels may still expose a public display name and avatar. The
Actor retains these in `fullName`, `title`, and `avatarUrl`, together with the
resolved channel ID when available. `username` remains the normalized requested
identity. Hidden subscriber counts and other unavailable details stay `null`.

`channelUrl` uses the stable channel-ID URL for successful results and age-gated
channels with a resolved ID. `profileUrl` uses a reported handle URL, normalized
to HTTPS. It is not guessed from the input.
Both URL fields are `null` for `invalid_input`.

Use `requestedUrl` alongside `profileUrl` to compare the requested and reported
identities. `isRedirected: true` means YouTube's JSON response pointed to another
channel address during resolution. The final handle can still match the input.
`handleMatchesInput: false` means YouTube resolved the request to a different
public handle, even if no address transition occurred. Check the returned `id`,
`handle`, and `title` before treating that result as the channel you intended.
Neither field proves that a channel changed its handle.

`isRedirected` is `null` when the address transition cannot be determined,
including HTTP-error results.
`handleMatchesInput` is `null` for channel-ID inputs and when no public handle
is available. All three resolution fields are `null` for `invalid_input`.

### Output example

The following is a **synthetic example**, not a live channel record:

```json
{
  "status": "ok",
  "id": "UCAAAAAAAAAAAAAAAAAAAAAA",
  "username": "example_creator",
  "requestedUrl": "https://www.youtube.com/@example_creator",
  "isRedirected": false,
  "handleMatchesInput": true,
  "channelUrl": "https://www.youtube.com/channel/UCAAAAAAAAAAAAAAAAAAAAAA",
  "profileUrl": "https://www.youtube.com/@example_creator",
  "handle": "@example_creator",
  "title": "Example Creator",
  "fullName": "Example Creator",
  "description": "Cooking and travel",
  "avatarUrl": "https://example.com/avatar.jpg",
  "bannerUrl": "https://example.com/banner.jpg",
  "verified": false,
  "subscriberCount": 12500,
  "videoCount": 85,
  "viewCount": 450000,
  "country": "Singapore",
  "joinedDate": "2020-01-15",
  "keywords": "cooking travel",
  "externalLinks": [
    "https://example.com"
  ],
  "crawledAt": "2026-10-28T09:00:00Z"
}
```

### Availability and partial results

| Status | Meaning |
| --- | --- |
| `ok` | YouTube returned public metadata matching the requested channel ID or the channel ID resolved from the requested handle. |
| `not_found` | The channel lookup returned HTTP 404, a JSON error with code 404, or a structured page error explicitly stating that the page/channel is unavailable, does not exist, or the account was terminated. The result does not establish whether a handle can be registered. |
| `restricted` | A channel age-gate response or structured page error explicitly reports an age or region restriction. Public basic metadata is retained when supplied. |
| `invalid_input` | Local validation rejected the submitted handle, channel ID, or URL. The target was never queued or scraped. |

All four statuses are stored. For `not_found`, the requested identity, requested
URL, and collection time are retained; channel metadata is `null`. A 404 produces
a `not_found` row immediately without retrying. For `restricted`, the Actor also
retains any available channel ID, display name, avatar, and reported handle or
handle URL. Other channel details stay `null`. For `invalid_input`, `username`
retains the submitted string with recognizable
credentials redacted; channel metadata and both URL fields are `null`.
Blank, malformed, consent, verification, rate-limit, and other inconclusive
responses are retried up to **3 times**, for at most **4 attempts per target**.
After retries are exhausted, the target counts as failed in the log and has no
dataset row.

YouTube can change public page formats or restrict access by request location.
The Actor does not solve challenges, log in, or access restricted content.

### How much does it cost to scrape YouTube channels?

Check the Actor's **Pricing** tab for current rates and review your run limits.
On pay-per-event runs, each stored row counts toward dataset-item charges,
including `not_found`, `restricted`, and `invalid_input` rows. Invalid inputs
require no scraping requests but still produce stored results.

When a result or charge budget is reached, the Actor stops with partial results.
Increase the applicable budget and **resurrect the same run** to continue,
keeping the same normalized target set. Targets can be reordered and run memory
can change; keep the same invalid input strings as well. Completed results
awaiting storage are saved for recovery when cleanup can finish, then replayed
before more scraping. Actual dataset records are checked before replay to
reconcile uncertain writes.

### Stopping and resuming a run

Use a **graceful abort** when you intend to resume. The Actor stops taking new
tasks while already claimed tasks finish their requests and retries. Completed
results and task outcomes are confirmed incrementally, and completed results
awaiting storage are saved for recovery. Platform termination can interrupt
cleanup; unfinished tasks may need another attempt and a forced stop can prevent
complete recovery.

To continue an interrupted run, open that run and select **Actions >
Resurrect**. The Actor reconciles the rows already stored in its Dataset with
the saved task outcomes before it resumes work.

Do not use **Re-run** to resume: it starts a separate run.

### FAQ

#### Can I scrape videos or subscriber lists?

This Actor collects channel metadata. `videoCount` is a count, not a video list.

#### Why are some fields null or some channels missing?

YouTube may omit public details or return only part of a channel's About metadata.
Missing rows indicate requests that exhausted retries; check the failed count
and retry logs. Explicit unavailable-channel responses have their own rows.

#### Can I check handle registration availability?

A `not_found` result describes the page response. It does not mean YouTube will
allow registration of that handle.

#### Where can I report an issue?

Use the Actor's **Issues** tab when available. Include the public channel URL,
run URL, expected behavior, and how any earlier execution was stopped.

### More Actors by AimScrape

Explore other public-data tools from [AimScrape](https://apify.com/aimscrape):

| Actor | Best for |
| --- | --- |
| [ Fast YouTube Channel Video Scraper 🚀](https://apify.com/aimscrape/youtube-channel-video-scraper) | Exporting public video metadata from a YouTube channel's Videos tab. |
| [Fast TikTok Profile Scraper 🚀](https://apify.com/aimscrape/tiktok-profile-scraper) | Collecting public TikTok profile details, audience counts, likes, and verification. |
| [ Fast YouTube Channel Scraper](https://apify.com/aimscrape/youtube-channel-scraper) | Collecting public YouTube channel metadata, counts, verification, and external links. |
| [ Snapchat Profile Scraper](https://apify.com/aimscrape/snapchat-profile-scraper) | Collecting public Snapchat profile metadata, subscriber counts, verification, and Snapcodes. |
| [ GitHub Profile Scraper](https://apify.com/aimscrape/github-profile-scraper) | Collecting public GitHub user, organization, and bot profile metadata. |

### Legal & ethical notice

YouTube Channel Scraper is an independent, third-party tool. It is not affiliated
with, endorsed by, or sponsored by YouTube or Google.

You are responsible for ensuring that your use of this Actor and the collected
data complies with:

- [YouTube's Terms of Service](https://www.youtube.com/static?template=terms),
  including any permission required for automated access.
- Applicable laws and regulations, including privacy, data protection, and
  intellectual property requirements.

The Actor is designed to collect channel metadata that YouTube returns publicly.
It does not log in, access subscriber lists or restricted content, or perform
email-address lookup. However, results such as channel names, descriptions,
images, keywords, and external links may contain personal data or third-party
content. Public availability alone does not establish permission to collect,
reuse, or redistribute that data.

Only collect data you are authorized to access, ensure that you have a lawful
basis for processing personal data where required, and do not use the results
for harassment, spam, or other abusive purposes.

# Actor input Schema

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

Add @handles, UC channel IDs, https://www.youtube.com/@handle URLs, or https://www.youtube.com/channel/CHANNEL_ID URLs. International handles are supported. Each entry is validated before queueing. Invalid entries produce invalid_input results without scraping; other entries continue. Remove query parameters and fragments. Video, Shorts, playlist, and short links are not supported.

## Actor input object example

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

# Actor output Schema

## `overview` (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/@YouTube"
    ]
};

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

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

```

## MCP server setup

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