# YouTube Scraper — Videos, Channels, Shorts & Search (`zkill3r/youtube-scraper-channels-videos`) Actor

Scrape YouTube search results (with filters), channel info, a channel's videos, Shorts and live streams, playlists and full video details (likes, tags, chapters, exact date). No API key. From $1.50 per 1,000 results.

- **URL**: https://apify.com/zkill3r/youtube-scraper-channels-videos.md
- **Developed by:** [Zee Lex](https://apify.com/zkill3r) (community)
- **Categories:** Videos, Social media, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 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 Scraper — Videos, Channels, Shorts & Search

Scrape public YouTube data **without an API key or quota**. The scraper covers:

- search results, with YouTube's own filters
- channel info: subscribers, total views, joined date, country, links
- a channel's videos, Shorts and live streams
- playlists
- full video details: description, tags, exact publish date, likes, comment count, chapters and captions

It uses plain HTTP and YouTube's own InnerTube API, with no browser, so it is fast and runs at 512 MB.

### What you get

| Item `type` | When | Main fields |
|---|---|---|
| `video` / `short` | search, channel tabs, playlists, video URLs | title, channel (name, ID, handle, verified), views, duration, published time + date, thumbnail, live/upcoming/members-only flags, badges, snippet, `source`, `position` |
| same + details | `includeVideoDetails: true` | `description`, `likeCount`, `commentCount`, `tags`, `keywords`, `category`, `chapters`, `isFamilySafe`, `availableCountriesCount`, `hasCaptions`; exact `publishedAt` |
| `channel` | channel URLs (`includeChannelInfo`), channel search | handle, title, description, subscribers, total videos, total views, joined date, country, verified, avatar, banner, links, keywords |
| `playlist` | playlist URLs, playlist search | title, channel, video count, thumbnail |
| `status` (free) | inputs that can't be scraped | `not_found`, `private`, `unavailable` (terminated, members-only), `age_restricted`, `error` |

Each run also stores a **RUN_SUMMARY** record. For every source it gives items saved, pages, blocks, proxy escalations, status and why paging stopped. It also gives totals by type, the percentage of each field that came back empty, and an overall status of `ok`, `partial`, `no_results` or `failed`.

### Input examples

**Search with filters**: long, HD videos from this month, most viewed first

```json
{
  "searchQueries": ["home espresso setup", "latte art tutorial"],
  "searchType": "video",
  "uploadDate": "month",
  "duration": "long",
  "sortBy": "views",
  "features": ["hd"],
  "maxResultsPerQuery": 100
}
```

**A channel's videos and Shorts**, with channel info and only uploads from the last 30 days

```json
{
  "startUrls": ["https://www.youtube.com/@mkbhd"],
  "channelTabs": ["videos", "shorts"],
  "maxVideosPerChannel": 50,
  "includeChannelInfo": true,
  "publishedAfter": "2026-09-28"
}
```

**A playlist**

```json
{
  "startUrls": ["https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi"],
  "maxVideosPerPlaylist": 200
}
```

**A single video with full details**

```json
{
  "startUrls": ["https://www.youtube.com/watch?v=aircAruvnKk"],
  "includeVideoDetails": true
}
```

`startUrls` accepts any mix of the following:

- video URLs: `watch?v=`, `youtu.be/`, `/shorts/`, `/live/` and `/embed/`
- channel URLs: `@handle`, `/channel/UC…`, `/c/…` and `/user/…`. Add `/videos`, `/shorts` or `/streams` to scrape just that tab.
- playlist URLs
- YouTube search-result URLs, which keep their own `sp=` filters
- bare video, playlist or channel IDs, and bare @handles

### Output samples

**Video with details** (`includeVideoDetails: true`)

```json
{
  "type": "video",
  "videoId": "aircAruvnKk",
  "url": "https://www.youtube.com/watch?v=aircAruvnKk",
  "title": "But what is a neural network? | Deep learning chapter 1",
  "channelName": "3Blue1Brown",
  "channelId": "UCYO_jab_esuFRV4b17AJtAw",
  "channelUrl": "https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw",
  "channelHandle": "@3blue1brown",
  "isVerifiedChannel": true,
  "viewCount": 21034567,
  "durationSeconds": 1120,
  "durationText": "18:40",
  "publishedTimeText": "8 years ago",
  "publishedAt": "2017-10-05T15:00:01.000Z",
  "publishedAtIsApproximate": false,
  "thumbnailUrl": "https://i.ytimg.com/vi/aircAruvnKk/hqdefault.jpg",
  "isLive": false,
  "isUpcoming": false,
  "isMembersOnly": false,
  "badges": ["4K", "CC"],
  "descriptionSnippet": "What are the neurons, why are there layers, and what is the math",
  "source": "search: neural networks",
  "position": 1,
  "scrapedAt": "2026-10-28T09:53:33.224Z",
  "description": "Home page: https://www.3blue1brown.com …",
  "likeCount": 312456,
  "commentCount": 12000,
  "tags": ["neural networks", "deep learning", "3blue1brown"],
  "keywords": "neural networks, deep learning, 3blue1brown",
  "category": "Education",
  "chapters": [{ "title": "Introduction", "startSeconds": 0 }, { "title": "What are neurons?", "startSeconds": 194 }],
  "isFamilySafe": true,
  "availableCountriesCount": 3,
  "hasCaptions": true
}
```

**Channel**

```json
{
  "type": "channel",
  "channelId": "UCYO_jab_esuFRV4b17AJtAw",
  "url": "https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw",
  "handle": "@3blue1brown",
  "title": "3Blue1Brown",
  "description": "3Blue1Brown, by Grant Sanderson, is some combination of math and entertainment…",
  "subscriberCount": 7230000,
  "videoCount": 212,
  "viewCount": 612345678,
  "joinedAt": "2015-03-04",
  "country": "United States",
  "isVerified": true,
  "avatarUrl": "https://yt3.googleusercontent.com/…",
  "bannerUrl": "https://yt3.googleusercontent.com/…",
  "links": [{ "title": "Patreon", "url": "https://www.patreon.com/3blue1brown" }],
  "keywords": ["Mathematics", "linear algebra", "calculus"]
}
```

**Playlist and status items**

```json
{ "type": "playlist", "playlistId": "PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi", "url": "https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi", "title": "Neural networks", "channelName": "3Blue1Brown", "channelId": "UCYO_jab_esuFRV4b17AJtAw", "videoCount": 8, "thumbnailUrl": "https://i.ytimg.com/vi/aircAruvnKk/hqdefault.jpg" }
{ "type": "status", "input": "https://www.youtube.com/@doesnotexist", "status": "not_found", "message": "Channel not found (HTTP 404)." }
```

### Use cases

- **Influencer research**: search a niche with `searchType: "channel"`, then pull subscribers, views, country and links for each channel.
- **Competitor tracking**: schedule a weekly run on competitors' channels with `publishedAfter` so you only get new uploads, Shorts and streams.
- **Content strategy**: compare titles, durations, views and upload times across the top results for your keywords.
- **Lead lists**: export channel handles, countries and the business and social links from the About panel.
- **AI datasets**: collect titles, descriptions, tags and chapters at scale, deduplicated by video ID.

### Limitations

- **Only public data is collected.** Private, members-only, age-restricted and removed videos come back as free `status` items when you give them directly. In lists they are skipped or flagged with `isMembersOnly`.
- **List dates are approximate.** Search results, channel tabs and playlists only show "3 weeks ago", so `publishedAt` is estimated and `publishedAtIsApproximate` is `true`. Turn on `includeVideoDetails` to get the exact date.
- How `publishedAfter` behaves depends on where the video comes from:
  - **Channel tabs:** paging stops at the first older video.
  - **Searches:** older videos are only filtered out. Paging gives up after 3 pages in a row with nothing new.
  - **Shorts:** lists show no date, so Shorts are only filtered when `includeVideoDetails` is on.
  - **Playlists and direct video URLs:** the filter isn't applied.
- **Duration filter:** YouTube's buckets are under 3 minutes, 3–20 minutes and over 20 minutes.
- **Sorting:** YouTube search now only supports Relevance and Popularity (view count). For the newest videos, use the `uploadDate` filter (last hour, today, this week…).
- **`maxVideosPerChannel` applies per tab.** Videos plus Shorts can give up to twice that number per channel.
- **Shorts in lists have no duration or date.** Live streams show concurrent viewers instead of total views.
- **YouTube changes its page layout often.** All layout knowledge is kept in `src/mappings.ts`, so a change usually needs a small edit to that one file.
- **Blocking:** heavy runs can trigger YouTube's bot check. Blocked requests are retried on a fresh session with exponential backoff. From the second retry they move to RESIDENTIAL proxy, up to 4 retries. If RUN_SUMMARY shows many blocks, lower `maxConcurrency`.

### Pricing

Pay per event, with lower prices on higher Apify plans:

| Event | Free | Bronze | Silver | Gold+ |
|---|---|---|---|---|
| `result`: per 1,000 videos, Shorts, channels or playlists | $1.50 | $1.30 | $1.10 | $0.90 |
| `video-details`: per 1,000 videos enriched from the watch page (only with `includeVideoDetails`) | $1.00 | $0.90 | $0.80 | $0.70 |

- **`status` items are free** (private, removed, not found).
- Example: 1,000 search results cost **$1.50**; with full details, **$2.50**. That is cheaper than most YouTube scrapers on the Store.
- The run stops cleanly once your maximum charge is reached.

# Actor input Schema

## `searchQueries` (type: `array`):

Optional. Search terms, one per line, exactly as you would type them into YouTube's search box. Each query is scraped up to "Max results per query".

## `searchType` (type: `string`):

What search queries return: videos (including Shorts), channels or playlists.

## `uploadDate` (type: `string`):

YouTube's upload date filter for search queries.

## `duration` (type: `string`):

YouTube length filter for search queries: short = under 3 minutes, medium = 3–20 minutes, long = over 20 minutes.

## `sortBy` (type: `string`):

Order of search results. YouTube's search now only supports Relevance and Popularity; to get recent videos, use the Upload date filter (e.g. Last hour, Today, This week).

## `features` (type: `array`):

Optional search filters: live = live now, 4k, hd, subtitles = has subtitles/CC, cc = Creative Commons licence.

## `maxResultsPerQuery` (type: `integer`):

Maximum results saved per search query (and per search-results URL in Start URLs).

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

Optional. Any mix of video URLs (watch, youtu.be, /shorts/, /live/), channel URLs (@handle, /channel/UC…, /c/…, /user/…, optionally ending in /videos, /shorts or /streams), playlist URLs and search-result URLs (youtube.com/results?search_query=…).

## `channelTabs` (type: `array`):

Which tabs to scrape for channel URLs: Videos, Shorts and/or Live (past and current streams). A channel URL that ends in /shorts, /videos or /streams uses only that tab.

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

Maximum items saved from each selected tab of each channel (newest first). With Videos + Shorts selected you can get up to twice this number per channel.

## `maxVideosPerPlaylist` (type: `integer`):

Maximum videos saved from each playlist, in playlist order.

## `includeChannelInfo` (type: `boolean`):

For channel URLs, also save one channel item: subscribers, total videos, total views, joined date, description, country, links, verified badge, avatar and banner.

## `publishedAfter` (type: `string`):

Optional ISO date (e.g. 2026-10-01). Skips channel and search results older than this and stops paging channel tabs (and date-sorted searches) once older videos appear. Approximate: lists only show "3 weeks ago". Shorts have no date in lists; with "Include video details" they are filtered by their exact date. Not applied to playlists or direct video URLs.

## `includeVideoDetails` (type: `boolean`):

Open each video's page for full details: description, tags, exact publish date, likes, comment count, category, chapters, captions, family-safe flag. Slower and charged as an extra "video-details" event per video. Off = list data only (faster, cheaper).

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

Parallel requests. Lower it if RUN_SUMMARY shows many blocks.

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

Apify datacenter proxy by default. Blocked requests are retried on a new session with backoff and, from the 2nd retry, on RESIDENTIAL proxy (if your plan includes it). Max 4 retries.

## Actor input object example

```json
{
  "searchQueries": [
    "neural networks explained"
  ],
  "searchType": "video",
  "uploadDate": "any",
  "duration": "any",
  "sortBy": "relevance",
  "maxResultsPerQuery": 50,
  "startUrls": [
    "https://www.youtube.com/@3blue1brown"
  ],
  "channelTabs": [
    "videos"
  ],
  "maxVideosPerChannel": 50,
  "maxVideosPerPlaylist": 50,
  "includeChannelInfo": true,
  "includeVideoDetails": false,
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Videos, Shorts, channels, playlists and free status items (field "type").

## `allFields` (type: `string`):

Every field of every item.

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

Per source: items saved, pages, blocks, proxy escalations, status; totals by type; % missing per field; overall status.

# 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 = {
    "searchQueries": [
        "neural networks explained"
    ],
    "startUrls": [
        "https://www.youtube.com/@3blue1brown"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("zkill3r/youtube-scraper-channels-videos").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 = {
    "searchQueries": ["neural networks explained"],
    "startUrls": ["https://www.youtube.com/@3blue1brown"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("zkill3r/youtube-scraper-channels-videos").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 '{
  "searchQueries": [
    "neural networks explained"
  ],
  "startUrls": [
    "https://www.youtube.com/@3blue1brown"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call zkill3r/youtube-scraper-channels-videos --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zkill3r/youtube-scraper-channels-videos"
        }
    }
}
```

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/seuxcdOYAf5sQYM3s/builds/PlO7kgm378NmKiot5/openapi.json
