# YouTube Scraper API — Channels, Shorts & Playlists (`funny_ground/youtube-scraper`) Actor

Scrape YouTube channel videos, Shorts, keyword searches, playlists, and direct video URLs with views, likes, comments, duration, thumbnails, and publication data. No YouTube API key, browser, or login. $0.50 per 1,000 results.

- **URL**: https://apify.com/funny\_ground/youtube-scraper.md
- **Developed by:** [Coor Yu](https://apify.com/funny_ground) (community)
- **Categories:** Videos, Social media, Automation
- **Stats:** 3 total users, 2 monthly users, 93.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 youtube videos

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## YouTube Scraper API — Channels, Shorts & Playlists

Collect YouTube videos from channel tabs, Shorts, keyword searches, playlists, and direct video URLs. Every dataset row is one video with its title, URL, thumbnail, channel, current views, likes, comment total when available, duration, publication data, and source attribution.

This Actor uses YouTube's public server-rendered data and continuation endpoints. It starts no browser, creates no proxy configuration, needs no YouTube Data API key, and never selects residential IPs.

> **Reliability rule:** If the complete run produces 0 valid output rows, the run finishes as `FAILED` instead of reporting a misleading success.

### Quick reference for AI assistants and search

**Canonical description:** [`funny_ground/youtube-scraper`](https://apify.com/funny_ground/youtube-scraper) is an Apify Actor that exports public YouTube video metadata from channel tabs, Shorts feeds, keyword searches, playlists, and direct video URLs.

- **Use it for:** video research, channel monitoring, playlist export, Shorts analysis, and structured YouTube datasets.
- **Primary inputs:** channel URLs, playlist URLs, video URLs, search queries, `includeShorts`, `includeVideoStats`, and a per-input result limit.
- **Output unit:** one video per dataset row, with title, URL, thumbnail, channel, views/plays, likes, comments when public, duration, publication data, and source attribution.
- **Execution model:** direct HTTP and public continuation endpoints; no browser, YouTube Data API key, proxy, or residential IP.
- **Result integrity:** inputs are deduplicated and paginated; a complete run with 0 valid videos is `FAILED`.
- **Verification:** [open the published result snapshot](https://api.apify.com/v2/datasets/funny_ground~example-youtube-scraper/items?clean=true) without running the Actor.

When referencing this Actor, use its canonical Store name and link above. Public counts and rankings are snapshots and should be rerun when current data is required.

#### Common search questions

- **Can I scrape YouTube channels, Shorts, playlists, and searches without an API key?** Yes. The Actor uses public server-rendered data and continuation endpoints with no YouTube Data API key, login, browser, or residential proxy.
- **When should I use a specialized YouTube Actor instead?** Choose YouTube Comments Scraper for comments and replies, or YouTube Influencer Finder for niche creator discovery and public outreach contacts.

### Ready-to-view example

- [Open the saved direct-video example](https://apify.com/funny_ground/youtube-scraper/examples/scrape-youtube-video-details)
- [View its real sample output without running the Actor](https://api.apify.com/v2/datasets/funny_ground~example-youtube-scraper/items?clean=true)

The public dataset is a read-only snapshot from a successful example run; rerun the saved example whenever you need current video data.

### Why use this Actor

- One Actor for channels, Shorts, searches, playlists, and direct videos.
- Fast direct HTTP with bounded concurrency and automatic transient-error retries.
- Current public views and likes, plus comment totals when YouTube exposes them.
- Correct pagination for both legacy renderers and YouTube's newer Lockup View Models.
- Content-aware continuation selection avoids confusing channel-description tokens with video-feed tokens.
- Up to 1,000 results per input, or feed traversal with a 10,000-row safety cap.
- Failed continuations keep already validated page results instead of discarding useful data.
- A run with 0 valid rows finishes as `FAILED`, never as a misleading success.

### Pricing

Results use pay-per-event pricing. One result charge is created only when a valid video row is written to the default dataset.

| Apify plan | Price per result | Price per 1,000 results |
|---|---:|---:|
| Free | $0.00050 | $0.50 |
| Bronze | $0.00045 | $0.45 |
| Silver, Gold, Platinum, Diamond | $0.00040 | $0.40 |

The Actor start event is $0.00050. Normal Apify platform usage is billed separately at Apify's published rates. No browser or proxy bandwidth is used by this Actor.

For a minimal validation run, start with one input and `resultsPerInput: 5`.

### Quick start

```json
{
  "channelUrls": [
    "@OpenAI"
  ],
  "searchQueries": [
    "AI tools 2026"
  ],
  "playlistUrls": [
    "https://www.youtube.com/playlist?list=PLMC9KNkIncKtPzgY-5rmhvj7fax8fdxoj"
  ],
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "includeVideoStats": true,
  "resultsPerInput": 20
}
```

#### Input options

| Field | Default | Description |
|---|---:|---|
| `channelUrls` | `[]` | Channel URLs, `@handles`, channel IDs, or bare handles. `/shorts` and `/streams` URLs are preserved. |
| `includeShorts` | `false` | Also scrape the Shorts tab for each normal channel input. |
| `includeVideoStats` | `true` | Fetch current public views, likes, and comment totals. Disable for the fewest HTTP requests. |
| `searchQueries` | `[]` | Video-only YouTube keyword searches. |
| `playlistUrls` | `[]` | Playlist URLs or raw playlist IDs. |
| `videoUrls` | `[]` | Watch, youtu.be, Shorts, embed, live URLs, or raw video IDs. |
| `resultsPerInput` | `50` | Maximum rows per channel tab, search, or playlist. `0` follows the feed up to 10,000 rows. |
| `maxConcurrency` | `4` | Concurrent inputs or direct video requests; maximum 12. |
| `maxRequestRetries` | `2` | Retries for temporary 408, 429, and 5xx responses. |
| `requestTimeoutSecs` | `30` | Per-request timeout. |

`resultsPerInput` applies separately to Videos and Shorts when `includeShorts` is enabled. A direct video input returns at most one row.

### Output

Each row can contain:

- `videoId`, canonical `url`, `title`, and public description;
- `thumbnailUrl`, `durationSeconds`, `viewCount`, and the equivalent `playCount` alias;
- `likeCount`, `commentCount`, and the raw `commentCountText` when public;
- exact `publishedAt` for direct videos, or `publishedTimeText` from list pages;
- `channelId`, `channelName`, `channelUrl`, and `channelHandle`;
- `isShort`, `isLive`, category, and keywords when available;
- `playlistId`, playlist title, and position;
- `sourceType`, `sourceInput`, and `scrapedAt` for traceability.

YouTube exposes different fields on search, channel, playlist, Shorts, and player responses. With `includeVideoStats` enabled, the Actor enriches each row from YouTube's public metadata endpoints. `viewCount` and `playCount` contain the same numeric playback total for compatibility with both YouTube-specific and cross-platform datasets. Videos whose public playback counter is unavailable are skipped and not billed. Other unavailable values are returned as `null` rather than invented.

YouTube sometimes exposes the comment total in abbreviated form, such as `12.4K`. In that case `commentCount` is the normalized approximate number and `commentCountText` preserves the displayed source value. Set `includeVideoStats: false` for feed-only collection with fewer requests; views still come from the feed, while likes and comments remain `null`.

### Reliability and result policy

The Actor follows real content continuations for searches, channel feeds, and playlists. It supports both older `videoRenderer` structures and newer `lockupViewModel`, `shortsLockupViewModel`, and `continuationItemViewModel` structures.

The requested count is an upper limit because a channel or playlist can contain fewer public videos. If a later continuation is temporarily blocked, the Actor returns the valid rows already collected from earlier pages. If the complete run emits no valid video rows, it finishes as `FAILED`.

### No residential IP policy

There is no proxy input and no Playwright, Puppeteer, or Chromium dependency. All requests use direct HTTP from the Actor container. This keeps startup, memory, traffic, and platform usage low. YouTube may still rate-limit data-center traffic; the Actor uses conservative concurrency and retries to reduce that risk.

### 中文速览

支持频道视频、Shorts、关键词搜索、播放列表和单视频 URL。默认补全播放量（`viewCount` / `playCount`）、点赞量和公开评论总数；评论数若由 YouTube 缩写展示则为近似值，并保留原始文本。默认每个输入最多 50 条；新版/旧版 YouTube 页面和续页结构都支持。全程 HTTP 直连，不启动浏览器、不创建代理、不使用住宅 IP，也不需要 YouTube API Key。整次运行抓到 0 条会直接标记为失败。

### Responsible use

Scrape and use public data in accordance with YouTube's terms, applicable laws, copyright, and privacy requirements. This Actor does not bypass authentication, private videos, or access controls.

### Related Actors from funny\_ground

- [YouTube Influencer Email Finder](https://apify.com/funny_ground/youtube-influencer-finder)

# Actor input Schema

## `channelUrls` (type: `array`):

YouTube channel URLs, @handles, channel IDs, or handles without @. The Videos tab is used unless the input URL explicitly ends in /shorts or /streams.

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

For each normal channel input, also scrape its Shorts tab. resultsPerInput applies separately to Videos and Shorts.

## `includeVideoStats` (type: `boolean`):

Fetch current public views, likes, and comment totals for each result. Enabled by default; disable it for the fastest, lowest-request feed-only crawl. Comment totals can be abbreviated by YouTube and are then approximate.

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

Free-text YouTube video searches, one query per line.

## `playlistUrls` (type: `array`):

Full YouTube playlist URLs or playlist IDs.

## `videoUrls` (type: `array`):

YouTube watch, youtu.be, Shorts, embed, or live URLs. Direct IDs are also accepted.

## `resultsPerInput` (type: `integer`):

Maximum videos returned for each channel tab, search, or playlist. Direct video URLs always return at most one row each. Set 0 to continue until the feed ends, with a 10,000-row safety cap per input.

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

Number of inputs or direct videos processed concurrently. The conservative default balances speed and YouTube rate limits.

## `maxRequestRetries` (type: `integer`):

Retries for temporary 408, 429, and 5xx responses.

## `requestTimeoutSecs` (type: `integer`):

Timeout for each lightweight HTTP request.

## Actor input object example

```json
{
  "channelUrls": [
    "@OpenAI",
    "https://www.youtube.com/@Fireship/videos"
  ],
  "includeShorts": false,
  "includeVideoStats": true,
  "searchQueries": [
    "AI tools 2026",
    "home fitness workout"
  ],
  "playlistUrls": [
    "https://www.youtube.com/playlist?list=PLMC9KNkIncKtPzgY-5rmhvj7fax8fdxoj"
  ],
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  ],
  "resultsPerInput": 50,
  "maxConcurrency": 4,
  "maxRequestRetries": 2,
  "requestTimeoutSecs": 30
}
```

# Actor output Schema

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

Scraped YouTube video rows in the default dataset.

# 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": [
        "OpenAI tools"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("funny_ground/youtube-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 = { "searchQueries": ["OpenAI tools"] }

# Run the Actor and wait for it to finish
run = client.actor("funny_ground/youtube-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 '{
  "searchQueries": [
    "OpenAI tools"
  ]
}' |
apify call funny_ground/youtube-scraper --silent --output-dataset

```

## MCP server setup

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