# YouTube Channel Scraper - Subscribers, Views & Links (`rocketyard/youtube-channel-scraper`) Actor

$0.70 per 1,000 channels, no subscription. Returns the public profile of YouTube channels with their latest uploads (channelId, handle, name, description, subscriberCount, subscriberCountText, videoCount, viewCount, joinedDate, country and more). Paste URLs or IDs; get JSON, CSV or Excel.

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

## Pricing

from $0.46 / 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

## YouTube Channel Scraper - Subscribers, Views & Links

### What does YouTube Channel Scraper do?

YouTube Channel Scraper returns the public profile of YouTube channels with their latest uploads: one clean record per channel, with typed values (numbers, booleans, ISO dates) ready for spreadsheets, databases and AI pipelines.

- Exact video and total view counts, the join date and country, read from the channel's own About page
- Latest uploads (up to 30) with views, duration and age in the same record
- The links the channel publishes, resolved to their real URLs
- Accepts @handles, channel IDs and legacy /c/ and /user/ URLs
- An error item with a clear code for every channel that cannot be read, never charged
- No login, no cookies, no browser; respects robots.txt

### Use cases

- **Build creator lists with subscriber, view and video counts**
- **Track competitor channels: growth, upload cadence and latest videos**
- **Collect the links channels publish for partnership research**
- **Feed clean channel data into CRMs, dashboards and AI pipelines**

### Why this YouTube channel scraper?

- Several competitors have unreliable runs (<90% success in 30 days)
- Cheaper than typical alternatives ($0.70 vs $1.00 per 1,000 results)

### How it compares

| YouTube channel scraper | Users (last 30 days) | Successful runs (last 30 days) | Price per 1,000 results |
| --- | --- | --- | --- |
| Fast YouTube Channel Scraper | 3780 | 97.9% | $1.30 |
| Youtube Channel Video Scraper | 1580 | 100.0% | $1.00 |
| Fast YouTube Channel Scraper API / Profiles, Subs & Stats | 1219 | 99.9% | $0.50 |
| **This Actor** | new | every release is tested on live pages first | **$0.70** |

Apify Store data from 2026-11-06, free-plan prices. Prices and stats change; check each listing before you compare.

### How it works

YouTube embeds each channel's data in the HTML of its public About and Videos pages. The Actor fetches those two pages over plain HTTP, without a browser, login or cookies, honours YouTube's robots.txt, and reads the embedded data: subscriber, video and total view counts, the join date and country, the description, the links the channel publishes, its avatar and banner, and its latest uploads with views, duration and age. A channel that cannot be read gets an error item that says why, and is not charged.

### How to use it

1. Click **Try for free**.
2. Add channel URLs to **Channel URLs** (for example `https://www.youtube.com/@Google`), or handles and IDs to **Channel handles or IDs**.
3. Optionally lower **Latest videos per channel** (up to 30, or 0 for profiles only).
4. Click **Start**, then download results as JSON, CSV, Excel or via the API.

### Input example

```json
{
  "startUrls": [
    {
      "url": "https://www.youtube.com/@Google"
    }
  ],
  "channels": [
    "@NASA"
  ],
  "maxVideosPerChannel": 30
}
```

### Output example

A real record from the latest test run (youtube.com) on 2026-11-07. Fields the page didn't publish are left out here; the Actor returns them as `null`.

```json
{
  "url": "https://www.youtube.com/@Google",
  "type": "Channel",
  "channelId": "UCK8sQmJBp8GCxrOtXWBpyEA",
  "handle": "@Google",
  "name": "Google",
  "description": "Here to help. \n\nReimagining how AI can make your life better and help you explore your creativity, connect with the world, and discover new possibilities. Browse our latest product demos, unboxings, developer roundtables, podcasts, tips, tricks and more. Subscribe for the latest product updates,…",
  "subscriberCount": 14700000,
  "subscriberCountText": "14.7M subscribers",
  "videoCount": 2796,
  "viewCount": 6753156352,
  "joinedDate": "2005-09-18",
  "isVerified": true,
  "isFamilySafe": true,
  "avatarUrl": "https://yt3.googleusercontent.com/bAseQlKvNmjdLQrvYWm_q3QDp8C8YKyYI-nYJewgOkPi0JU1_3X9oFgjrEdzkOlXzLGFxFbnsw=s900-c-k-c0x00ffffff-no-rj",
  "bannerUrl": "https://yt3.googleusercontent.com/H9gGqPJUwNvqOwEZBewLZiW_gV2nFdeQOugRyKv1qclCvIH4ucb6E5z5zYUOZJE4Z2E0KcS6=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
  "keywords": [
    "Google",
    "Technology",
    "Science",
    "Android",
    "Google app",
    "Google Doodles",
    "Google Gemini",
    "Gemini AI",
    "Google AI",
    "Google Chrome",
    "Google Search",
    "YouTube",
    "Google Play Store",
    "AI",
    "Artificial Intelligence",
    "Tech",
    "Innovation",
    "Machine Learning",
    "Quantum Computing",
    "Google I/O",
    "Made by Google",
    "Google Doodle",
    "Team Google",
    "Explained",
    "How-to",
    "Tutorial",
    "Google Tips",
    "Tech Tips",
    "Google Help",
    "Google products",
    "Google updates",
    "NotebookLM",
    "NanoBanana",
    "Veo",
    "Gen AI",
    "Pixel",
    "unboxing"
  ],
  "links": [
    {
      "title": "Google Search",
      "url": "https://google.com/"
    },
    {
      "title": "Gemini App",
      "url": "https://gemini.google.com/app"
    },
    {
      "title": "News from Google",
      "url": "https://blog.google/"
    }
  ],
  "videos": [
    {
      "videoId": "DDjr6gXqtN8",
      "url": "https://www.youtube.com/watch?v=DDjr6gXqtN8",
      "title": "What’s New in Google Accessibility | Episode 13 | American Sign Language",
      "viewCount": 12000,
      "viewCountText": "12K",
      "publishedText": "11 days ago",
      "durationSeconds": 478,
      "thumbnailUrl": "https://i.ytimg.com/vi/DDjr6gXqtN8/hq720_custom_2.jpg?sqp=CJDwudcG-oaymwEXCNAFEJQDSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLCeS1lD2x5NE-QtnSZXCevXW_8rOQ"
    },
    {
      "videoId": 
```

#### Output fields

| Field | Description |
|---|---|
| `url` | Channel URL |
| `type` | Always `Channel` |
| `channelId` | Channel ID (UC...) |
| `handle` | Handle (@name) |
| `name` | Channel name |
| `description` | Full channel description |
| `subscriberCount` | Subscribers as a number, from the count YouTube displays (rounded for large channels) |
| `subscriberCountText` | Subscribers as YouTube displays them ("14.7M subscribers") |
| `videoCount` | Number of public videos (exact) |
| `viewCount` | Total channel views (exact) |
| `joinedDate` | Date the channel was created (YYYY-MM-DD) |
| `country` | Country the channel set, when public |
| `isVerified` | `true` when the channel has a verified badge |
| `isFamilySafe` | YouTube family-safe flag |
| `avatarUrl` | Largest avatar image |
| `bannerUrl` | Largest banner image |
| `keywords` | Channel keywords |
| `links` | Links the channel publishes (title and URL) |
| `videos` | Latest uploads: ID, URL, title, views, age and duration |
| `scrapedAt` | ISO timestamp |

### Error items

When an input produces no data, the dataset gets one **error item** for it, so nothing is skipped silently. Error items are **free**: only result records are charged.

```json
{
  "url": "https://www.youtube.com/@no-such-channel-example",
  "input": "https://www.youtube.com/@no-such-channel-example",
  "error": {
    "type": "https://rocketyard.dev/errors#channel-not-found",
    "title": "Channel not found",
    "status": 404,
    "detail": "YouTube answered HTTP 404 for https://www.youtube.com/@no-such-channel-example/about",
    "instance": "https://www.youtube.com/@no-such-channel-example",
    "code": "CHANNEL_NOT_FOUND"
  }
}
```

The `error` object follows [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) (Problem Details). Its `type` links to the [explanation of the code](https://rocketyard.dev/errors), and `status` is the site's HTTP status when there was one. Filter on `error.code` to separate failures from data; it has its own column in CSV and Excel exports.

| Code | Meaning | Retry? |
|---|---|---|
| [`ROBOTS_DISALLOWED`](https://rocketyard.dev/errors#robots-disallowed) | The site's robots.txt does not allow automated access to this URL (or to the page it redirects to), so it was not fetched. | no |
| [`ROBOTS_UNREACHABLE`](https://rocketyard.dev/errors#robots-unreachable) | The site's robots.txt could not be loaded because of a server or network error. Under RFC 9309, the page is then not fetched. | yes |
| [`PRIVATE_ADDRESS`](https://rocketyard.dev/errors#private-address) | The URL, or a redirect from it, points to a private or local network address. Only public websites are fetched. | no |
| [`NOT_FOUND`](https://rocketyard.dev/errors#not-found) | The page or source does not exist (HTTP 404 or 410). | no |
| [`BLOCKED`](https://rocketyard.dev/errors#blocked) | The site refused access (HTTP 401, 403 or 429) or answered with a bot-check or consent page instead of the content. | sometimes |
| [`HTTP_ERROR`](https://rocketyard.dev/errors#http-error) | The site answered with another HTTP error: a server error (5xx) that persisted after retries, or an unexpected 4xx status. | sometimes |
| [`TIMEOUT`](https://rocketyard.dev/errors#timeout) | The site did not answer in time, even after retries. | yes |
| [`NETWORK_ERROR`](https://rocketyard.dev/errors#network-error) | The connection failed (DNS, TLS or a reset connection), even after retries. | yes |
| [`WRONG_CONTENT_TYPE`](https://rocketyard.dev/errors#wrong-content-type) | The URL returned something the Actor doesn't read, such as a PDF or image instead of an HTML page, or a web page where an API response was expected. | no |
| [`TOO_LARGE`](https://rocketyard.dev/errors#too-large) | The response exceeded the size limit (10 MiB for web pages, 48 MiB for API responses). | no |
| [`PARSE_ERROR`](https://rocketyard.dev/errors#parse-error) | The response could not be read (malformed HTML or JSON). | sometimes |
| [`CHANNEL_NOT_FOUND`](https://rocketyard.dev/errors#channel-not-found) | No public channel exists at this handle, ID or URL. | no |

### Limits

- The video list holds the latest uploads YouTube shows on the channel's Videos tab (up to 30). Older uploads load through YouTube's internal API, which robots.txt disallows.
- Subscriber counts are as YouTube displays them, rounded for large channels (14.7M). Video and total view counts are exact.
- Contact emails that some channels show only after a sign-in and a CAPTCHA are never collected.

### Pricing

Pay per result: **$0.70 per 1,000 channels**, plus a tiny per-run start fee. Channels that cannot be read produce an error item, which is not charged. There is no monthly rental, and you can cap spend per run with **Max results** or **Maximum cost per run**.

### Integrations and API

Run it from the [Apify API](https://docs.apify.com/api/v2), the JavaScript/Python clients, Make, Zapier, n8n, LangChain or any MCP-compatible AI agent, and send results to Google Sheets, webhooks, S3 and more. Schedule it to track changes over time.

### FAQ

**Which channels does it work on?** Any public YouTube channel: @handle URLs, /channel/UC... IDs, legacy /c/ and /user/ URLs, or just the handle or ID.

**How exact are the numbers?** Video and total view counts are exact, as YouTube publishes them on the About page at the time of the run. The subscriber count is the number YouTube displays, which it rounds for large channels (14.7M); `subscriberCountText` keeps it as shown.

**Does it return contact emails?** No. YouTube shows business emails only after a sign-in and a CAPTCHA; the Actor never signs in or solves CAPTCHAs. It returns the links a channel publishes on its About page.

**Can it list every video of a channel?** It lists the latest uploads (up to 30) that the channel's Videos page shows. Loading more needs YouTube's internal API, which robots.txt disallows.

**How much does it cost?** You pay per result: $0.70 per 1,000 channels, plus a start fee of $0.00005 per run, with no subscription. Cap any run with **Maximum cost per run**.

**How do I call it from the API?** One request starts a run and returns its results, using your [Apify API token](https://console.apify.com/settings/integrations):

```bash
curl -X POST "https://api.apify.com/v2/acts/rocketyard~youtube-channel-scraper/run-sync-get-dataset-items" -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" -d '{"startUrls":[{"url":"https://www.youtube.com/@Google"}],"channels":["@NASA"],"maxVideosPerChannel":30}'
```

**How do I use it with AI agents?** Connect Apify's MCP server at `https://mcp.apify.com?tools=rocketyard/youtube-channel-scraper`, and the agent can call this Actor as a tool.

**Is it legal to scrape YouTube data?** The Actor reads only public pages that YouTube's robots.txt allows, without logging in, without cookies and without bypassing consent or bot checks. It returns no comment text and no data about commenters or viewers. You are responsible for how you use the data under YouTube's terms and the law (for example copyright and GDPR).

**What happens when an input fails?** If a channel can't be read, the dataset gets one [error item](#error-items) for it with a code and the reason. Error items are free, and the other channels still run.

**I need a field that is not supported.** Open an issue on the Actor's Issues tab. Requests are reviewed regularly and drive new features.

### You might also like

- [Article Scraper - Any Website (Schema.org)](https://apify.com/rocketyard/article-schema-scraper): article data from any website with schema.org markup
- [Ashby Jobs API & Scraper](https://apify.com/rocketyard/ashby-jobs-scraper): every open job from Ashby job boards
- [Events Scraper - Any Event Site to Structured Data](https://apify.com/rocketyard/event-schema-scraper): event data from any website with schema.org markup
- [Greenhouse Jobs API & Scraper](https://apify.com/rocketyard/greenhouse-jobs-scraper): every open job from Greenhouse job boards
- [Hotel Details Scraper - Address, Stars & Amenities](https://apify.com/rocketyard/hotel-schema-scraper): hotel data from any website with schema.org markup

### Made by Rocketyard

[Rocketyard](https://rocketyard.dev) builds pay-per-result scrapers for public web data, and every release is tested on live pages before it ships. Guides for this Actor: [overview](https://rocketyard.dev/youtube-channel-scraper), [REST API](https://rocketyard.dev/youtube-channel-scraper#api), [MCP for AI agents](https://rocketyard.dev/youtube-channel-scraper#mcp) and [n8n, Make and Zapier](https://rocketyard.dev/youtube-channel-scraper#automation).

# Actor input Schema

## `startUrls` (type: `array`):

YouTube channel URLs: https://www.youtube.com/@handle, /channel/UC..., /c/name or /user/name. Leave empty if you use Channel handles or IDs.

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

Handles such as "@Google" (the @ is optional) or channel IDs starting with "UC".

## `maxVideosPerChannel` (type: `integer`):

Latest uploads to include from each channel's Videos tab (YouTube shows up to 30 there). 0 skips the list.

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

Stop after this many channels.

## `maxConcurrency` (type: `integer`):

Pages fetched in parallel (a polite delay between requests to YouTube always applies).

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

Optional proxy.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.youtube.com/@Google"
    }
  ],
  "maxVideosPerChannel": 30,
  "maxItems": 100,
  "maxConcurrency": 3
}
```

# Actor output Schema

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

One record per YouTube channel, plus a free error item for each input that yielded no data, as JSON, CSV or Excel.

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

Channels read, error items, robots.txt skips and how long the run took.

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

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

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

```

## MCP server setup

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