# YouTube Scraper Pro (`sajjadstack/youtube-scraper`) Actor

Scrape YouTube videos, channels, playlists & search results
without API limits. Extract title, views, likes, subscribers,
subtitles & more. Export to JSON, CSV or Excel. No quotas.
Powered by Crawlee & Playwright.

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

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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 — Apify Actor

A high‑performance Apify Actor built with **Apify SDK v3**, **Crawlee**, and
**TypeScript** that scrapes YouTube search results, video pages, channels, and
playlists.

***

### Features

| Capability | Details |
|---|---|
| **Search scraping** | Enter keywords → get structured video data |
| **Direct URL scraping** | Pass video, channel, or playlist URLs |
| **Pagination** | Automatically follows YouTube continuation tokens |
| **Search filters** | Filter by upload date and video type (videos / shorts / streams) |
| **Subtitle extraction** | Optionally download and parse video captions |
| **Anti‑blocking** | Uses Apify datacenter proxy with session rotation |
| **Typed output** | Every record matches the `VideoData` TypeScript interface |

***

### Input

The Actor accepts JSON input conforming to [`INPUT_SCHEMA.json`](INPUT_SCHEMA.json).

| Field | Type | Default | Description |
|---|---|---|---|
| `searchTerms` | `string[]` | `[]` | YouTube search keywords |
| `youtubeUrls` | `string[]` | `[]` | Direct video / channel / playlist URLs |
| `maxResults` | `number` | `50` | Maximum videos to scrape |
| `scrapeSubtitles` | `boolean` | `false` | Extract subtitles / captions |
| `videoType` | `enum` | `"all"` | `"videos"` · `"shorts"` · `"streams"` · `"all"` |
| `dateFilter` | `enum` | `"all"` | `"hour"` · `"day"` · `"week"` · `"month"` · `"year"` · `"all"` |

#### Example input

```json
{
    "searchTerms": ["web scraping tutorial", "node.js"],
    "youtubeUrls": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "https://www.youtube.com/@Google/videos"
    ],
    "maxResults": 100,
    "scrapeSubtitles": true,
    "videoType": "videos",
    "dateFilter": "month"
}
```

***

### Output

Each video is pushed to the default **Apify Dataset** as a JSON record:

```json
{
    "title": "Learn Web Scraping in 20 Minutes",
    "videoId": "abc123xyz",
    "url": "https://www.youtube.com/watch?v=abc123xyz",
    "thumbnailUrl": "https://i.ytimg.com/vi/abc123xyz/maxresdefault.jpg",
    "viewCount": 152340,
    "likeCount": 4200,
    "commentsCount": 312,
    "duration": "20:15",
    "uploadDate": "2025-12-01",
    "channelName": "Code Academy",
    "channelUrl": "https://www.youtube.com/channel/UC1234567890",
    "subscriberCount": "1.2M subscribers",
    "description": "In this tutorial we cover ...",
    "hashtags": ["#webscraping", "#nodejs"],
    "subtitles": "Hi everyone, welcome to this tutorial ...",
    "scrapedAt": "2026-03-06T12:00:00.000Z"
}
```

***

### Tech Stack

- **[Apify SDK v3](https://docs.apify.com/sdk/js/)** — Actor lifecycle, dataset, proxy
- **[Crawlee](https://crawlee.dev/)** — `CheerioCrawler` with labeled routing
- **TypeScript 5** — strict mode, ESM
- **Node.js 20**

***

### Project Structure

```
├── .actor/
│   └── actor.json          # Actor metadata
├── src/
│   ├── main.ts             # Entry point — input parsing, crawler setup
│   ├── scraper.ts           # Crawlee router & request handlers
│   ├── types.ts             # TypeScript interfaces & enums
│   └── utils.ts             # JSON extraction, URL helpers, parsers
├── Dockerfile               # Docker image definition
├── INPUT_SCHEMA.json        # Apify input schema
├── package.json             # Dependencies & scripts
├── tsconfig.json            # TypeScript config
└── README.md                # This file
```

***

### Local Development

```bash
## Install dependencies
npm install

## Create an input file
mkdir -p storage/key_value_stores/default
echo '{ "searchTerms": ["apify tutorial"], "maxResults": 5 }' \
  > storage/key_value_stores/default/INPUT.json

## Run in development mode (tsx — no build step)
npm run dev

## Or build & run
npm start
```

> **Note:** Proxy is only available when running on the Apify platform. Local
> runs execute without proxy and may be rate‑limited by YouTube.

***

### Deploying to Apify

```bash
## Install the Apify CLI
npm install -g apify-cli

## Log in
apify login

## Push the Actor to Apify
apify push
```

***

### How It Works

1. **Search URLs** are built from `searchTerms` with optional `sp` protobuf
   filters for date and video type.
2. **CheerioCrawler** fetches each page and the embedded `ytInitialData` /
   `ytInitialPlayerResponse` JSON blobs are extracted from `<script>` tags —
   no browser needed.
3. Search results are parsed and individual **video page requests** are
   enqueued (up to `maxResults`).
4. **Pagination** uses YouTube's innertube continuation API via POST requests
   with the continuation token.
5. Each video page handler extracts detailed metadata (likes, comments,
   subscribers, subtitles) and pushes a `VideoData` record to the Apify
   Dataset.

***

### License

ISC

# Actor input Schema

## `searchTerms` (type: `array`):

List of YouTube search keywords to scrape results for.

## `youtubeUrls` (type: `array`):

Direct YouTube video, channel, or playlist URLs to scrape.

## `maxResults` (type: `integer`):

Maximum number of videos to scrape across all search terms and URLs.

## `scrapeSubtitles` (type: `boolean`):

Whether to extract video subtitles/captions (increases runtime).

## `videoType` (type: `string`):

Filter search results by video type.

## `dateFilter` (type: `string`):

Filter search results by upload date.

## Actor input object example

```json
{
  "searchTerms": [
    "web scraping tutorial",
    "node.js crash course"
  ],
  "youtubeUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://www.youtube.com/@apaborern/videos",
    "https://www.youtube.com/playlist?list=PLRqwX-V7Uu6ZiZxtDDRCi6uhfTH4FilpH"
  ],
  "maxResults": 50,
  "scrapeSubtitles": false,
  "videoType": "all",
  "dateFilter": "all"
}
```

# Actor output Schema

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

Dataset containing all scraped YouTube video records with metadata, statistics, and optionally subtitles.

# 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 = {
    "searchTerms": [
        "web scraping tutorial"
    ],
    "youtubeUrls": [],
    "maxResults": 50,
    "scrapeSubtitles": false,
    "videoType": "all",
    "dateFilter": "all"
};

// Run the Actor and wait for it to finish
const run = await client.actor("sajjadstack/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 = {
    "searchTerms": ["web scraping tutorial"],
    "youtubeUrls": [],
    "maxResults": 50,
    "scrapeSubtitles": False,
    "videoType": "all",
    "dateFilter": "all",
}

# Run the Actor and wait for it to finish
run = client.actor("sajjadstack/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 '{
  "searchTerms": [
    "web scraping tutorial"
  ],
  "youtubeUrls": [],
  "maxResults": 50,
  "scrapeSubtitles": false,
  "videoType": "all",
  "dateFilter": "all"
}' |
apify call sajjadstack/youtube-scraper --silent --output-dataset

```

## MCP server setup

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