# YouTube Channel Scraper 📺 (all videos, stats, new uploads) (`tagadanar/youtube-channel-scraper`) Actor

Every video a YouTube channel has published, in one table: title, views, publish date, duration, Shorts and live streams, plus the channel's subscribers, total views, join date, country and links. Schedule it with "only new videos" to get just the fresh uploads. No API key, no login.

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

## Pricing

from $0.35 / 1,000 videos

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: every video a channel has published, with stats

Give it a list of YouTube channels and get back one table: every video each channel has published, newest first, with title, views, publish date, duration, thumbnail and link. Shorts and live streams too if you want them. Each channel also gets its own row with subscribers, total channel views, video count, join date, country, description and the links on its About page.

Put it on a schedule with **Only new videos since the last run** switched on and each run returns just the uploads that appeared since the previous one. **Scheduled runs cost almost nothing when nothing changed**: a quiet channel is checked against its latest-uploads feed and nothing is charged beyond the run start.

No API key, no login, no Google Cloud quota. Platform usage is included in the price.

### Who it is for

- **Agencies and brand teams tracking competitors or creators.** See what every channel on your watchlist publishes, how fast it gets views, and which formats (long videos, Shorts, live) they lean on.
- **Influencer marketers.** Vet a creator's whole back catalogue before a deal: posting cadence, view counts per video, Shorts vs long-form, links to their other platforms.
- **Analysts and researchers.** Build a dataset of a channel's entire output for content analysis, then feed the video IDs into the [transcript](https://apify.com/tagadanar/youtube-transcript-extractor) or [comments](https://apify.com/tagadanar/youtube-comments-scraper) actors.
- **Content teams.** Find a competitor's most-viewed videos and the topics that keep working for them.

### What you get

Two kinds of rows in the same dataset, told apart by `type`. The **Videos** view of the dataset shows the videos, the **Channels** view shows the channel rows.

**Video rows** (`type: "video"`)

| Field | What it is |
| --- | --- |
| `videoId`, `url`, `title` | The video |
| `channelId`, `channelTitle`, `channelHandle` | Who published it |
| `viewCount` | Views. Exact for the channel's 15 newest uploads; for older videos it is YouTube's rounded figure (2.9M → 2,900,000) |
| `viewCountText`, `viewCountIsExact` | The figure as YouTube shows it, and whether `viewCount` is exact |
| `publishedAt` | Exact publish time, for the 15 newest uploads |
| `publishedTimeText` | As YouTube shows it ("3 weeks ago", "Streamed 6 years ago") |
| `publishedAtApprox` | A date estimated from that text (exact when `publishedAt` is known) |
| `durationSeconds`, `durationText` | Length (Shorts have none on the channel page) |
| `isShort`, `isLive`, `wasLive`, `isUpcoming` | Short, live right now, a past live stream, scheduled |
| `isMembersOnly` | A members-only upload (YouTube shows no view count for these, so `viewCount` is empty) |
| `thumbnailUrl` | Largest thumbnail |
| `tab`, `position` | Which channel tab it came from (`videos`, `shorts`, `streams`) and its position there, 1 = newest |
| `capturedAt` | When the row was collected |

**Channel rows** (`type: "channel"`)

| Field | What it is |
| --- | --- |
| `channelId`, `handle`, `title`, `channelUrl` | The channel |
| `description`, `keywords`, `country` | From the About page |
| `subscriberCountText`, `subscriberCountApprox` | Subscribers as YouTube shows them ("8.7M subscribers") and as a number. YouTube rounds this figure publicly |
| `totalViewCount` | Total channel views, exact |
| `videoCount`, `videoCountText` | Videos on the channel |
| `joinedDate` | Date the channel was created (YYYY-MM-DD) |
| `externalLinks` | `[{ title, url }]` — website, Instagram, X, Patreon… as listed on the About page |
| `avatarUrl`, `bannerUrl`, `isVerified` | Profile picture, banner, verification badge |
| `capturedAt` | When the row was collected |

### Input

| Field | Default | What it does |
| --- | --- | --- |
| **Channels** | — | Channel URLs, `@handles`, `UC…` channel IDs, old `/c/` and `/user/` links. A video link works too (you get its uploader). |
| **Max videos per channel** | 100 | Newest first, up to 5,000. Counted separately for videos, Shorts and live streams. The run status says when a channel has more. |
| **Include Shorts** | off | Also collect the Shorts tab. |
| **Include live streams** | off | Also collect the Live tab (past, live-now and scheduled streams). |
| **Only new videos since the last run** | off | Return only uploads that are new since the previous run of the same channel list and settings. |

Example — two channels, their latest 200 videos and their Shorts:

```json
{
    "channels": ["https://www.youtube.com/@mkbhd", "@3blue1brown"],
    "maxVideosPerChannel": 200,
    "includeShorts": true
}
```

Example — a daily watchlist that only returns fresh uploads (schedule it in Apify):

```json
{
    "channels": ["@mkbhd", "@LinusTechTips", "https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw"],
    "maxVideosPerChannel": 50,
    "onlyNewSinceLastRun": true
}
```

### Output example

A real video row (3Blue1Brown, captured 2026-10-15):

```json
{
    "type": "video",
    "channelId": "UCYO_jab_esuFRV4b17AJtAw",
    "channelTitle": "3Blue1Brown",
    "channelHandle": "@3blue1brown",
    "videoId": "Nbwv5wHQoj0",
    "url": "https://www.youtube.com/watch?v=Nbwv5wHQoj0",
    "title": "The last IMO problem AI could not solve",
    "viewCount": 2974539,
    "viewCountText": "2.9M views",
    "viewCountIsExact": true,
    "publishedAt": "2026-09-18T17:12:53.000Z",
    "publishedTimeText": "3 weeks ago",
    "publishedAtApprox": "2026-09-18T17:12:53.000Z",
    "durationSeconds": 3116,
    "durationText": "51:56",
    "isShort": false,
    "isLive": false,
    "wasLive": false,
    "isUpcoming": false,
    "isMembersOnly": false,
    "thumbnailUrl": "https://i.ytimg.com/vi/Nbwv5wHQoj0/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLARIa200D0WGqdKfn4aF2sBHLllHA",
    "tab": "videos",
    "position": 1,
    "capturedAt": "2026-10-15T21:46:19.562Z"
}
```

And its channel row (description and links shortened here):

```json
{
    "type": "channel",
    "channelId": "UCYO_jab_esuFRV4b17AJtAw",
    "handle": "@3blue1brown",
    "title": "3Blue1Brown",
    "description": "My name is Grant Sanderson. Videos here cover a variety of topics in math, or adjacent fields like physics and CS, all w…",
    "country": "United States",
    "subscriberCountText": "8.7M subscribers",
    "subscriberCountApprox": 8700000,
    "totalViewCount": 783431784,
    "videoCount": 245,
    "videoCountText": "245 videos",
    "joinedDate": "2015-03-03",
    "externalLinks": [
        { "title": "All things 3b1b", "url": "https://www.3blue1brown.com" },
        { "title": "Patreon", "url": "https://www.patreon.com/3blue1brown" }
    ],
    "avatarUrl": "https://yt3.googleusercontent.com/ytc/AIdro_nFzZFPLxPZRHcE3SSwzdrbuWqfoWYwLAu0_2iO6blQYAU=s900-c-k-c0x00ffffff-no-rj",
    "bannerUrl": "https://yt3.googleusercontent.com/JfUD9Tu79zgoYGo5-WdP5YYj0XvAjPgV3c2Snj-cgy8jslro0Ln5by024zWL7XDin7Vs-qnxVg=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj",
    "isVerified": true,
    "keywords": "Mathematics",
    "channelUrl": "https://www.youtube.com/@3blue1brown",
    "capturedAt": "2026-10-15T21:46:19.562Z"
}
```

### Pricing

Pay per result, platform usage included — the price below is all you pay.

| Event | Price | Per 1,000 | Gold plan |
| --- | --- | --- | --- |
| Video row | $0.0005 | **$0.50 per 1,000 videos** | $0.35 per 1,000 |
| Channel row | $0.002 | $2 per 1,000 channels | $1.40 per 1,000 |
| Run start | $0.001 | once per run | $0.001 |

Bronze and Silver get $0.45 and $0.40 per 1,000 videos ($1.80 and $1.60 per 1,000 channels).

So a channel's last 1,000 videos cost about $0.50 plus $0.002 for its channel row. A daily watchlist of 20 channels that publishes 10 new videos a day costs about $0.006 a run, plus $0.002 for each channel that posted (its fresh channel row). A run where no channel posted anything costs just the run start. You are never charged for a channel that does not exist or a tab a channel does not have.

### FAQ

**How far back does it go?** As far as the channel's own Videos tab goes — the full upload history, up to 5,000 per tab per run. Set **Max videos per channel** to what you need; the run status tells you when a channel has more.

**Are view counts exact?** For each channel's 15 newest uploads, yes (`viewCountIsExact: true`). Older videos carry the rounded figure YouTube shows on the channel page ("2.9M views"), turned into a number. The channel's total views are always exact; subscriber counts are rounded by YouTube itself for everyone.

**How does "Only new videos since the last run" work?** The actor remembers which videos it has already returned for that exact channel list and settings. The first run returns everything up to your cap and starts the memory; every later run returns only videos published since. Changing the channel list or the Shorts / live-stream switches starts a fresh memory. Channel rows come with the first run and again whenever that channel has new videos, so you also get a fresh subscriber and view snapshot.

**What happens with a wrong handle or a deleted channel?** That entry is skipped and the run status names it ("Not found on YouTube"). Nothing is charged for it, and the other channels are scraped normally.

**Do I need a YouTube API key?** No. No key, no Google Cloud project, no quota, no login.

**Can I get the transcripts or comments of these videos?** Yes — pipe the `url` column into the transcript or comments actors below.

### Related YouTube actors

- [YouTube Search Scraper](https://apify.com/tagadanar/youtube-search-scraper) — videos, Shorts and channels for any search.
- [YouTube Comments Scraper](https://apify.com/tagadanar/youtube-comments-scraper) — every comment and reply on a video.
- [YouTube Shorts Scraper](https://apify.com/tagadanar/youtube-shorts-scraper) — Shorts by keyword or channel.
- [YouTube Channel Email Scraper](https://apify.com/tagadanar/youtube-channel-email-scraper) — creator contact details for outreach.
- [YouTube Transcript Scraper](https://apify.com/tagadanar/youtube-transcript-extractor) — transcripts for any list of videos.

# Changelog

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

# Actor input Schema

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

One channel per line, in any form: <code>https://www.youtube.com/@mkbhd</code>, <code>@mkbhd</code>, <code>https://www.youtube.com/channel/UC…</code>, a bare <code>UC…</code> channel ID, or old <code>/c/name</code> and <code>/user/name</code> links. A video link works too: you get the channel that uploaded it. Duplicates are removed.

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

Newest first. Counted separately for regular videos, Shorts and live streams, so 100 with Shorts on means up to 100 videos and up to 100 Shorts per channel. The run status tells you when a channel has more than this.

## `includeShorts` (type: `boolean`):

Also collect the channel's Shorts tab. Shorts rows are marked <code>isShort: true</code>.

## `includeLiveStreams` (type: `boolean`):

Also collect the channel's Live tab: past streams (<code>wasLive</code>), streams live right now (<code>isLive</code>) and scheduled ones (<code>isUpcoming</code>).

## `onlyNewSinceLastRun` (type: `boolean`):

For scheduled runs. The actor remembers which videos it already gave you for this exact channel list and settings, and returns (and charges) only the new uploads. The first run returns everything up to the cap and starts the memory. A channel with nothing new costs nothing beyond the run start.

## Actor input object example

```json
{
  "channels": [
    "https://www.youtube.com/@3blue1brown",
    "@mkbhd"
  ],
  "maxVideosPerChannel": 30,
  "includeShorts": false,
  "includeLiveStreams": false,
  "onlyNewSinceLastRun": false
}
```

# Actor output Schema

## `videos` (type: `string`):

Video rows and channel rows in the default dataset.

## `channels` (type: `string`):

The channel rows.

# 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/@3blue1brown",
        "@mkbhd"
    ],
    "maxVideosPerChannel": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("tagadanar/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/@3blue1brown",
        "@mkbhd",
    ],
    "maxVideosPerChannel": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("tagadanar/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/@3blue1brown",
    "@mkbhd"
  ],
  "maxVideosPerChannel": 30
}' |
apify call tagadanar/youtube-channel-scraper --silent --output-dataset

```

## MCP server setup

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