# YouTube Scraper (`s-r/youtube-scraper`) Actor

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

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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 - extract videos, channels, and search results without an API key

This YouTube scraper pulls structured video data straight from YouTube's InnerTube web API, so there is no API key, no OAuth, and no daily quota to burn through. Feed it a mix of search terms, video URLs, and channel handles, and get back one clean row per video with titles, view counts, likes, comment counts, subscriber numbers, and exact publish dates.

### What you get

Every result is one video, flattened into fields you can drop straight into a sheet or database:

- Core identity: `video_id`, `url`, `title`, `description`, and a short `description_snippet` for previews.
- Channel context: `channel_name`, `channel_id`, `channel_url`, and `channel_subscribers` so you know how big the uploader is.
- Timing: `published_text` ("3 weeks ago"), a normalized `published_date`, and the exact `upload_date` when full details are enabled.
- Engagement: `view_count` plus the raw `view_count_text`, `like_count`, and `comment_count`.
- Media details: `duration_seconds`, `duration_text`, `category`, `keywords`, `thumbnail_url`, and an `is_live` flag for streams.
- Provenance: `source` (search / video / channel), the original `input` that produced the row, and `fetched_in_seconds` for timing.

### Why scrape YouTube

The official YouTube Data API v3 runs on a quota system. Every project gets 10,000 units per day by default, and a single `search.list` call costs 100 units. That means roughly 100 searches a day before you are locked out until midnight Pacific time. Pulling video statistics, comment counts, and channel details each cost extra units on top, so a real research job burns the daily allowance in minutes.

Raising that quota means filling out a Google audit form and waiting for approval that often never comes. Even when it does, you are rate limited, key managed, and one policy change away from losing access.

This scraper skips that entirely. It talks to the same InnerTube endpoints the YouTube website itself uses, so there is no key to register, no quota meter, and no audit. You can pull thousands of videos in a single run, filter by upload date, sort by views, and enrich each row with the exact engagement numbers the Data API charges quota to return.

### Input

Provide a `queries` list and tune the rest. Only `queries` is required.

| Field | Type | Default | Description |
|---|---|---|---|
| `queries` | array | (required) | Mixed list: search keywords, video URLs (`watch?v=`, `youtu.be/`), channel URLs, or `@handles`. One entry per line. |
| `max_results` | integer | 20 | Maximum videos per search term or channel, from 1 to 500. |
| `sort_by` | string | `relevance` | Ordering for search inputs: `relevance`, `date`, `views`, or `rating`. |
| `upload_date` | string | `any` | Upload window for search inputs: `any`, `hour`, `today`, `week`, `month`, or `year`. |
| `fetch_details` | boolean | `true` | Enrich each video with likes, subscribers, comment count, full description, exact publish date, and category (2 extra requests per video). |
| `country` | string | `US` | Two-letter country code for region-specific results (the `gl` parameter). |
| `language` | string | `en` | Two-letter interface language code (the `hl` parameter) for localized text. |

### Output

Each dataset item is a single video. With `fetch_details` on, a row looks like this:

```json
{
  "video_id": "dQw4w9WgXcQ",
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "title": "Full web scraping tutorial for beginners",
  "description": "In this video we cover selectors, pagination, and proxies...",
  "description_snippet": "In this video we cover selectors, pagination, and...",
  "channel_name": "Dev Tutorials",
  "channel_id": "UC1a2b3c4d5e6f7g8h9",
  "channel_url": "https://www.youtube.com/channel/UC1a2b3c4d5e6f7g8h9",
  "channel_subscribers": 482000,
  "published_text": "3 weeks ago",
  "published_date": "2026-06-21",
  "upload_date": "2026-06-21",
  "view_count": 154302,
  "view_count_text": "154K views",
  "like_count": 8120,
  "comment_count": 412,
  "duration_seconds": 1284,
  "duration_text": "21:24",
  "category": "Education",
  "keywords": ["web scraping", "python", "tutorial"],
  "thumbnail_url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
  "is_live": false,
  "source": "search",
  "input": "web scraping tutorial",
  "fetched_in_seconds": 1.83
}
````

Turn `fetch_details` off and you still get the core fields (title, channel, view count, duration, thumbnail) at roughly a third of the requests, with the enrichment fields left empty.

### Use cases

Market researchers use it to size demand around a topic. Run a batch of search terms with `upload_date` set to `month`, sort by `views`, and you get a ranked snapshot of what is actually being watched right now, complete with `view_count` and `channel_subscribers` so you can separate genuine traction from noise. Because there is no quota ceiling, you can widen the keyword set as far as the research needs to go.

Content strategists mine the data for format and timing signals. Pull a competitor's channel URL, collect the last few hundred uploads, and compare `duration_seconds`, `category`, and `keywords` against `view_count` and `like_count` to see which lengths and topics land. The `published_date` field lets you map posting cadence against engagement, so you can spend more time making the videos that work.

Competitor analysts track rivals over time. Schedule a run against a list of channel handles and store the dataset each week. Movements in `channel_subscribers`, `view_count`, and `comment_count` become a time series you can chart, and the `is_live` flag flags when a competitor is running streams. No manual checking, no logging into anything.

Data teams treat it as a clean ingestion source. The flat schema (one row per video, consistent field names, numeric counts already parsed out of their display text) drops straight into a warehouse or a pandas frame. The `source` and `input` fields keep every row traceable back to the query that produced it, which matters when you are joining several batches into one table.

### How it compares

| | This scraper | streamers/youtube-scraper | apidojo/youtube-scraper |
|---|---|---|---|
| Price per 1,000 videos | $3.20 | $4.00 | $0.50 |
| Date-filter add-on fee | none | $0.0013 per video | n/a |
| Comment count | yes | yes | no |
| Exact publish date | yes | yes | no |
| Channel subscribers | yes | yes | no |
| No API key required | yes | yes | yes |

We undercut streamers by 20 percent on the base rate and charge nothing extra for date filtering, where streamers adds $0.0013 per video for the same feature. apidojo is cheaper per thousand, but the rows come back thinner: no comment count, no exact publish date, and no subscriber count. If those three numbers matter to your analysis, this scraper returns all of them at the base price.

### Pricing

Pay-per-event, so you only pay for the results you actually receive:

- $0.0032 per video ($3.20 per 1,000 videos).
- $0.002 per-run actor-start fee.

There are no separate charges for date filtering, sorting, or detail enrichment. The per-video rate covers the full row.

### Limits and gotchas

- `sort_by` and `upload_date` only apply to search-term inputs. A video URL returns that one video, and a channel URL returns that channel's uploads in YouTube's native order, so the sort and date filters are ignored for both.
- `fetch_details` adds 2 requests per video (the watch page plus a detail call). Leaving it on is what fills in `like_count`, `comment_count`, `channel_subscribers`, `upload_date`, and `category`. Turn it off for faster, lighter runs when you only need core fields.
- Region is set with the `country` code (`gl`). Search results, availability, and localized text shift by region, so set it to match the market you care about.
- `language` (`hl`) changes localized strings like `view_count_text` and `published_text`, not the underlying numbers.
- Free-tier Apify users are capped at 10 results per run. Paid users have no cap and can pull up to `max_results` (500) per query or channel.
- Very large channels return uploads in pages. Set `max_results` to how deep you want to go; higher values mean more pagination requests and longer runs.
- `comment_count` and `like_count` can be hidden by the uploader. When YouTube does not expose them, those fields come back empty rather than guessed.

### FAQ

**Can I scrape YouTube without an API key?** Yes. This actor uses YouTube's internal InnerTube web API, the same one the site loads in your browser, so there is no Google Cloud project, no API key, no OAuth, and no daily quota. You just give it search terms or URLs and run it.

**How do I scrape all videos from a channel?** Put the channel URL or its `@handle` in the `queries` list and set `max_results` to how many videos you want (up to 500). The actor walks the channel's uploads and returns one row per video. The `sort_by` and `upload_date` filters do not apply to channel inputs, so you get the channel's native ordering.

**Does it get comment counts?** Yes, as long as `fetch_details` is enabled (it is on by default). Each video row includes `comment_count`, plus `like_count` and `channel_subscribers`. If the uploader has hidden a count, that field is returned empty instead of estimated.

**Can I mix search terms, video links, and channels in one run?** Yes. The `queries` list accepts all three at once. Each entry is detected automatically, and the `source` field on every result tells you whether it came from a search, a single video, or a channel.

**How do I get only recent videos?** For search inputs, set `upload_date` to `hour`, `today`, `week`, `month`, or `year`, and optionally set `sort_by` to `date` to get the newest first. These filters apply to search terms only, not to specific video or channel URLs.

### Related Actors

- [Youtube Shorts Scraper](https://apify.com/s-r/youtube-shorts-scraper) - Scrape YouTube Shorts from any channel with full engagement data.
- [Youtube Comments](https://apify.com/s-r/youtube-comments) - Scrape all comments from any YouTube video.
- [Free Youtube Transcript](https://apify.com/s-r/free-youtube-transcript) - Get the full transcript of any YouTube video.

# Actor input Schema

## `queries` (type: `array`):

Mix freely: search keywords (e.g. 'web scraping tutorial'), video URLs (watch?v=…, youtu.be/…), channel URLs or @handles. One entry per line.

## `max_results` (type: `integer`):

Maximum videos to collect per search term or channel (1–500).

## `sort_by` (type: `string`):

Ordering for search-term inputs. Ignored for video/channel URLs.

## `upload_date` (type: `string`):

Only return videos uploaded within this window. Applies to search-term inputs.

## `fetch_details` (type: `boolean`):

Enrich every video with likes, channel subscribers, comment count, full description, exact publish date and category (2 extra requests per video).

## `country` (type: `string`):

Two-letter country code for region-specific results (gl).

## `language` (type: `string`):

Two-letter interface language code (hl) — affects localized texts.

## Actor input object example

```json
{
  "queries": [
    "web scraping tutorial"
  ],
  "max_results": 20,
  "sort_by": "relevance",
  "upload_date": "any",
  "fetch_details": true,
  "country": "US",
  "language": "en"
}
```

# 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 = {
    "queries": [
        "web scraping tutorial"
    ],
    "max_results": 20,
    "country": "US",
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/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 = {
    "queries": ["web scraping tutorial"],
    "max_results": 20,
    "country": "US",
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("s-r/youtube-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "queries": [
    "web scraping tutorial"
  ],
  "max_results": 20,
  "country": "US",
  "language": "en"
}' |
apify call s-r/youtube-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=s-r/youtube-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "YouTube Scraper",
        "description": "",
        "version": "0.1",
        "x-build-id": "SmeaaHFiqHweAQEHc"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/s-r~youtube-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-s-r-youtube-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/s-r~youtube-scraper/runs": {
            "post": {
                "operationId": "runs-sync-s-r-youtube-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/s-r~youtube-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-s-r-youtube-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "queries"
                ],
                "properties": {
                    "queries": {
                        "title": "Search terms, video URLs, or channel URLs",
                        "type": "array",
                        "description": "Mix freely: search keywords (e.g. 'web scraping tutorial'), video URLs (watch?v=…, youtu.be/…), channel URLs or @handles. One entry per line.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "max_results": {
                        "title": "Max videos per query/channel",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum videos to collect per search term or channel (1–500).",
                        "default": 20
                    },
                    "sort_by": {
                        "title": "Sort search results by",
                        "enum": [
                            "relevance",
                            "date",
                            "views",
                            "rating"
                        ],
                        "type": "string",
                        "description": "Ordering for search-term inputs. Ignored for video/channel URLs.",
                        "default": "relevance"
                    },
                    "upload_date": {
                        "title": "Upload date filter",
                        "enum": [
                            "any",
                            "hour",
                            "today",
                            "week",
                            "month",
                            "year"
                        ],
                        "type": "string",
                        "description": "Only return videos uploaded within this window. Applies to search-term inputs.",
                        "default": "any"
                    },
                    "fetch_details": {
                        "title": "Fetch full video details",
                        "type": "boolean",
                        "description": "Enrich every video with likes, channel subscribers, comment count, full description, exact publish date and category (2 extra requests per video).",
                        "default": true
                    },
                    "country": {
                        "title": "Country",
                        "type": "string",
                        "description": "Two-letter country code for region-specific results (gl).",
                        "default": "US"
                    },
                    "language": {
                        "title": "Language",
                        "type": "string",
                        "description": "Two-letter interface language code (hl) — affects localized texts.",
                        "default": "en"
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
