---
title: "YouTube channel scraper"
description: "Scrape YouTube channel pages as JSON: channel ID, name, handle URL, description, avatar and links. One API request from Python, Node.js, the CLI or MCP."
canonical: https://www.zenrows.com/scrape/youtube-channel
updated: 2026-10-20
---

# YouTube channel scraper

The Zenrows YouTube channel scraper turns a YouTube channel URL into structured JSON: the permanent channel ID, channel name, channel URL, About description, avatar image and social links. You send the handle or channel URL, Fetch in Adaptive Stealth Mode opens the page, and Extract returns the fields. Run it from an API call, the CLI or an AI agent.

- Site: youtube.com
- Returns: Channel IDs, names, descriptions and avatars

## Run it: one YouTube channel in, JSON out

```json Input
{
  "url": "https://www.youtube.com/@mkbhd",
  "mode": "auto",
  "extract": "auto"
}
```

```json Output
{
  "channel": {
    "avatar_url": "https://yt3.googleusercontent.com/qu4TmIaYUlS41-dJ9gZ7DUR3nilvmB5_11i6OKSdvNnBNiyOusZP1bMN6ICnuxtjFBb6ioKgRQ=s900-c-k-c0x00ffffff-no-rj",
    "channel_id": "UCBJycsmduvYEL83R_U4JriQ",
    "channel_url": "https://www.youtube.com/channel/UCBJycsmduvYEL83R_U4JriQ",
    "description": "MKBHD: Quality Tech Videos | YouTuber | Geek | Consumer Electronics | Tech Head | Internet Personality!…",
    "name": "Marques Brownlee"
  },
  "social_links": []
}
```

Request and output of a live call to a YouTube channel page on Oct 20, 2026, trimmed for length. A field is returned when the page shows it.

## What data can you scrape from a YouTube channel?

A channel page returns the channel record. Pair it with the watch pages of the channel's videos and you also get per-video views, likes, tags and upload dates, all keyed to the same channel.

| Field | What it holds | Example |
|---|---|---|
| `channel.channel_id` | The permanent `UC…` ID, which never changes when the handle does | `UCBJycsmduvYEL83R_U4JriQ` |
| `channel.name` | The channel's display name | `Marques Brownlee` |
| `channel.channel_url` | The canonical channel URL built on the ID | `https://www.youtube.com/channel/UCBJycsmduvYEL83R_U4JriQ` |
| `channel.description` | The About text the creator wrote | `MKBHD: Quality Tech Videos…` |
| `channel.avatar_url` | The channel's profile picture, full size | `https://yt3.googleusercontent.com/…=s900-…` |
| `social_links[]` | The links the creator lists on the channel header, when present | `[]` |
| `channel.name` (watch page) | The channel behind any video, from the video's own page | `Rick Astley` |
| `channel.channel_url` (watch page) | The channel's handle URL, from a video page | `http://www.youtube.com/@RickAstleyYT` |
| `engagement.view_count` (watch page) | Views on one of the channel's videos | `1828456716` |
| `engagement.like_count` (watch page) | Likes on one of the channel's videos | `19489981` |
| `video.upload_date` (watch page) | When that video went live | `2009-10-24T23:57:33-07:00` |
| `video.tags[]` (watch page) | The tags the creator set on that video | `["rick astley", "nggyu", …]` |

## How to scrape a YouTube channel with Zenrows

1. **Create a free Zenrows account** and copy your API key from the dashboard.
2. **Pick the channel URL.** `https://www.youtube.com/@handle` and `https://www.youtube.com/channel/UC…` open the same channel. Older `/c/name` and `/user/name` links redirect to it.
3. **Send it with the default configuration**: Adaptive Stealth Mode opens the page and Extract returns the channel fields. No country is needed.
4. **Store `channel.channel_id`** as the key for that creator, since the handle can change.
5. **Add the channel's videos.** Request the watch pages of its uploads, in Batch, for views, likes and dates per video.

```python Python
# pip install requests
import requests

params = {
    "apikey": "YOUR_ZENROWS_API_KEY",
    "url": "https://www.youtube.com/@mkbhd",
    "mode": "auto",      # Adaptive Stealth Mode
    "extract": "auto",   # structured JSON
}
response = requests.get("https://api.zenrows.com/v1/", params=params, timeout=180)
response.raise_for_status()

channel = response.json()["parsed"]["channel"]
print(channel["channel_id"], channel["name"])
print(channel["description"])
```

```javascript Node.js
// Node 18+ (built-in fetch)
const params = new URLSearchParams({
  apikey: "YOUR_ZENROWS_API_KEY",
  url: "https://www.youtube.com/@mkbhd",
  mode: "auto",
  extract: "auto",
});

const response = await fetch(`https://api.zenrows.com/v1/?${params}`, {
  signal: AbortSignal.timeout(180_000),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);

const { parsed } = await response.json();
console.log(parsed.channel.channel_id, parsed.channel.name, parsed.channel.avatar_url);
```

```bash cURL
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.youtube.com%2F%40mkbhd&mode=auto&extract=auto"

# Only the fields you need
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.youtube.com%2F%40mkbhd&mode=auto&extract=auto&extract_fields=channel.channel_id%2Cchannel.name%2Cchannel.description"
```

```python Python SDK
# pip install zenrows
from zenrows import ZenRowsClient

client = ZenRowsClient("YOUR_ZENROWS_API_KEY")
for handle in ["@mkbhd", "@RickAstleyYT"]:
    response = client.get(
        f"https://www.youtube.com/{handle}",
        params={"mode": "auto", "extract": "auto"},
    )
    channel = response.json()["parsed"]["channel"]
    print(handle, channel["channel_id"], channel["name"])
```

## Input

The scraper takes one channel URL per request, plus the options below. A Batch job applies the same options to every URL, so a creator list of any size is one job.

| Parameter | Type | Default | Description |
|---|---|---|---|
| `url` | string | required | A channel page: `/@handle`, `/channel/UC…`, or a legacy `/c/` or `/user/` link |
| `mode` | string | `auto` | Adaptive Stealth Mode: starts with the lightest setup and adds rendering and protected-site handling only when the page needs them |
| `extract` | string | `auto` | Returns the channel fields as JSON in `parsed`, next to the raw `html` |
| `extract_fields` | string | all fields | Comma-separated paths to keep, such as `channel.channel_id,channel.name` |
| `proxy_country` | string | any | Two-letter country code, for channels whose page differs by region |
| `wait_for` | string | none | A CSS selector to wait for before the page is read |

```json Batch input
{
  "type": "regular",
  "status": "closed",
  "zenrows_params": {
    "mode": "auto",
    "extract": "auto"
  },
  "tasks": [
    { "url": "https://www.youtube.com/@mkbhd", "external_id": "mkbhd" },
    { "url": "https://www.youtube.com/@RickAstleyYT", "external_id": "rickastley" },
    { "url": "https://www.youtube.com/channel/UCBJycsmduvYEL83R_U4JriQ", "external_id": "mkbhd-by-id" }
  ]
}
```

## Output

Every response is JSON with two keys: `html`, the page as YouTube served it, and `parsed`, the structured record. The channel page fills `channel`; a watch page from the same channel adds the per-video numbers. Both samples are trimmed outputs of live requests on Oct 20, 2026.

```json Channel page
{
  "channel": {
    "avatar_url": "https://yt3.googleusercontent.com/qu4TmIaYUlS41-dJ9gZ7DUR3nilvmB5_11i6OKSdvNnBNiyOusZP1bMN6ICnuxtjFBb6ioKgRQ=s900-c-k-c0x00ffffff-no-rj",
    "channel_id": "UCBJycsmduvYEL83R_U4JriQ",
    "channel_url": "https://www.youtube.com/channel/UCBJycsmduvYEL83R_U4JriQ",
    "description": "MKBHD: Quality Tech Videos | YouTuber | Geek | Consumer Electronics | Tech Head | Internet Personality!…",
    "name": "Marques Brownlee"
  },
  "social_links": []
}
```

```json Video page from a channel
{
  "channel": {
    "channel_url": "http://www.youtube.com/@RickAstleyYT",
    "name": "Rick Astley"
  },
  "engagement": {
    "like_count": 19489981,
    "view_count": 1828456716
  },
  "video": {
    "video_id": "dQw4w9WgXcQ",
    "title": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)",
    "upload_date": "2009-10-24T23:57:33-07:00",
    "duration_iso": "PT3M34S",
    "tags": ["rick astley", "Never Gonna Give You Up", "nggyu"]
  }
}
```

The avatar URL ends in a size suffix (`=s900`). Change the number to get a smaller image for a dashboard. For the full video record, including description, genre and thumbnails, see the [YouTube scraper](/scrape/youtube).

## Scrape YouTube channels from your coding agent

Claude Code, Cursor, Codex and any MCP client can look up YouTube channels from a prompt.

The agent sends the same Fetch and Extract request shown above and reads the channel record from it. Connect the Zenrows MCP server once, or install the CLI and let the agent run it in the terminal.

```bash Connect the MCP server (Claude Code)
claude mcp add zenrows -e ZENROWS_API_KEY=YOUR_ZENROWS_API_KEY -- npx -y @zenrows/mcp
```

```json MCP config (Cursor, Claude Desktop, Windsurf)
{
  "mcpServers": {
    "zenrows": {
      "command": "npx",
      "args": ["-y", "@zenrows/mcp"],
      "env": { "ZENROWS_API_KEY": "YOUR_ZENROWS_API_KEY" }
    }
  }
}
```

```bash Or run the CLI
npx -y @zenrows/cli init
zenrows extract "https://www.youtube.com/@mkbhd"
```

```text Then ask your agent
Use Zenrows to open these YouTube channels and give me a table with the
channel ID, display name and the first line of each About description:
https://www.youtube.com/@mkbhd
https://www.youtube.com/@RickAstleyYT
```

## Scrape YouTube channels at scale with Batch and Crawl

**Batch** runs a creator list as one job, in parallel, with your own ID on each result. Send the handles you have, read back the `UC…` IDs, and you have a clean creator table to join everything else on.

**Crawl** collects a channel's videos. Start it on the channel's `/videos` tab, keep only links that contain `/watch?v=`, and it returns the video pages it reaches. Those pages carry the views, likes and dates you need for a channel report.

```bash Batch (cURL)
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "regular",
    "status": "closed",
    "zenrows_params": { "mode": "auto", "extract": "auto" },
    "tasks": [
      { "url": "https://www.youtube.com/@mkbhd", "external_id": "mkbhd" },
      { "url": "https://www.youtube.com/@RickAstleyYT", "external_id": "rickastley" }
    ]
  }'

# Read the results when the job finishes
curl "https://async.api.zenrows.com/v1/jobs/JOB_ID/results?status=successful" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY"
```

```bash Batch (CLI)
# channels.jsonl: one {"url": "...", "external_id": "...", "extract": "auto"} per line
zenrows batch create channels.jsonl --wait
zenrows batch results <job-id> --out youtube-channels.jsonl
```

```bash Crawl (cURL)
curl -X POST "https://api.zenrows.com/v1/crawls" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.youtube.com/@mkbhd/videos",
    "depth": 1,
    "max_pages": 100,
    "include_patterns": ["/watch?v="]
  }'
```

**Scheduled jobs** run the same Batch job on a timetable, on Zenrows' side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can tell your app when a run finishes, and you can pause or resume the schedule at any time, with no cron server to keep alive.

```bash Scheduled job (cURL)
# Runs every day on Zenrows' side; each run keeps its own results
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
      "type": "scheduled",
      "status": "closed",
      "schedule": {
        "rate": {
          "every": 1,
          "unit": "day"
        }
      },
      "zenrows_params": {
        "mode": "auto",
        "extract": "auto"
      },
      "tasks": [
        {
          "url": "https://www.youtube.com/@mkbhd",
          "external_id": "youtube-channel"
        }
      ]
    }'

# Or at set times: "schedule": { "calendar": { "times_of_day": ["09:00"],
#   "cadence": { "weekly": { "days": ["mon", "thu"] } } }, "timezone": "Europe/Madrid" }
```

## What teams do with YouTube channel data

| Use case | Data they pull | Who runs it |
|---|---|---|
| Creator discovery and vetting | Channel ID, name, About text, plus views and likes on recent videos | Influencer marketing agencies |
| Creator CRM enrichment | Channel ID and canonical URL to dedupe handles, avatar for the record | Partnerships and creator-economy platforms |
| Competitor channel tracking | The rival's channel record and the engagement of each new upload | Brand and content teams |
| Brand safety checks | About text and video tags before a sponsorship | Media buyers and agencies |
| Market maps of a niche | Channel records for every creator in a topic list | Analysts and investors |

## Tips for scraping YouTube channels

- **Resolve handles to IDs once.** Send `@handle` URLs, store `channel.channel_id`, and request `/channel/UC…` from then on. The ID URL keeps working after a rename.
- **Use the tabs as entry points.** `/@handle/videos`, `/@handle/shorts` and `/@handle/streams` list each kind of upload separately, which makes them good starting points for a crawl.
- **Turn the channel ID into the uploads playlist.** Replace the leading `UC` of a channel ID with `UU` and you get the ID of the channel's uploads playlist, `https://www.youtube.com/playlist?list=UU…`.
- **Dedupe your creator list on the ID.** Agencies often hold the same creator under a handle, a `/c/` link and a `/channel/` link. All three resolve to one `channel_id`.
- **Resize the avatar from the URL.** The `=s900` suffix sets the image size in pixels. Ask for `=s176` for a thumbnail.

## Frequently asked questions

### Is it legal to scrape YouTube channels?

Collecting publicly available channel data, such as a channel's name, ID, description and video statistics shown to every visitor, is common practice for creator research. A channel can belong to an individual, and personal data is protected by laws such as the GDPR and the CCPA, so collect only what you have a legitimate reason to use. Check YouTube's terms for your use case and ask your lawyer if you are unsure.

### Is there an official API for YouTube channel data?

Yes. The YouTube Data API v3 has a channels endpoint that returns a channel's snippet and statistics, and it needs a Google Cloud project and an API key. Every call counts against a daily quota of 10,000 units by default, and resolving many handles or searching for channels uses that quota fast. A scraper reads the public channel page with no quota.

### What YouTube channel pages can I scrape?

Any public channel: /@handle , /channel/UC… , and legacy /c/ and /user/ URLs, plus its tabs such as /videos , /shorts and /streams . For the videos themselves, use the YouTube scraper .

### How do I find a YouTube channel ID from a handle?

Send the @handle URL to the scraper and read channel.channel_id from the response. The same record holds the canonical channel_url built on that ID.

### How do I scrape YouTube channels with Python?

Send a GET request to https://api.zenrows.com/v1/ with your API key, the channel URL, Adaptive Stealth Mode and Extract turned on, as in the Python example above. The parsed key of the response holds the channel as a Python dictionary. The zenrows package on PyPI wraps the same request.

### How many YouTube channels can I scrape?

Send one URL per request, or a whole creator list as a Batch job that runs the URLs in parallel and keeps your own ID on each result. One Batch job accepts more than 10,000 URLs, sent inline or as a CSV file.

### Can AI agents scrape YouTube channels with Zenrows?

Yes. Connect the Zenrows MCP server to Claude, Cursor, Codex or any MCP client, or give your agent the Zenrows CLI. Ask for the channels you want in plain language and the agent calls Fetch and Extract for you.

### Can I scrape YouTube on a schedule?

Yes. Create a scheduled Batch job with your YouTube URLs and the same settings as a single request, and Zenrows runs it on its side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can notify your app when a run finishes, and the schedule can be paused or resumed at any time.

### Which integrations work with the YouTube channel scraper?

Zenrows works with n8n, Make, Zapier, Clay, Dify, LangChain, LlamaIndex, CrewAI and Mastra, plus the Python, Node.js and Go SDKs and any HTTP client. Creator teams often run it from Clay or n8n to enrich a list of handles. See the integrations page for the full list.

### What format does the data come in?

JSON by default, with the structured record in parsed and the original page in html . You can also ask for the page as Markdown or plain text, which is what most LLM and RAG pipelines want.

## More YouTube scrapers

- [YouTube scraper](https://www.zenrows.com/scrape/youtube.md)

All scrapers: https://www.zenrows.com/scrape. Start free: https://app.zenrows.com/register. Docs: https://docs.zenrows.com
