# YouTube Data Scraper - Video Search, Channels, Views & Likes (`s-r/youtube-scraper`) Actor

Scrape YouTube videos with this YouTube video scraper: search terms, channel handles and video links return video data — title, views, likes, comment count, duration, tags and date, one row per video as JSON or CSV. No API key or quota. For research, marketing and AI.

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

## Pricing

from $0.90 / 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 Scraper: search results, channel videos and video details

This YouTube scraper collects public video data from search terms, channel
handles, channel URLs and individual video links, without a YouTube API key or
daily quota. Use it as a YouTube video scraper for marketing research, competitor
tracking or building datasets: you can mix all input types in one run.
Each result is a structured video row with its original input, canonical URL
and available metadata. Detail enrichment is enabled by default and adds the
statistics and description YouTube currently exposes for each video.

### YouTube scraper input

Provide queries as a list of search terms, video URLs or channels. The default
prefill is web scraping tutorial. A multiline string is also accepted by the
scraper. Blank entries are removed and the first fifty nonempty entries are
processed in their original order. Videos repeated across inputs appear once;
the first input that found the video determines its source and input fields.

max_results defaults to 20 videos per search term or channel, with a range of
1 to 500. A specific video URL always addresses that single video. Supported
links include regular watch URLs, youtu.be links, Shorts, embed and live URLs.
Channels can be supplied as @handles, UC identifiers or channel URLs. Bare
eleven-character video identifiers keep their existing interpretation.

sort_by supports relevance, date, views and rating; relevance is the default.
upload_date supports any, hour, today, week, month and year; any is the default.
These settings affect keyword searches. They do not reorder channel uploads
or filter a specific video URL. country defaults to US and language defaults
to en. Set these to the region and interface language needed for your research.
YouTube can change the result order and localized labels between runs.

The eleven optional feature filters all default to false: is_hd,
has_subtitles, has_cc, is_3d, is_live, is_bought, is_4k, is_360, has_location,
is_hdr and is_vr180. They can be combined for keyword searches. has_subtitles
means subtitles or closed captions; has_cc means the Creative Commons licence.
is_bought requires a signed-in purchase context to return purchased videos;
this public scraper does not supply that context. Keep it off for public searches.

fetch_details defaults to true. Disable it when search or channel metadata is
enough. In that mode, direct video URLs return the original minimal identity
row, while search and channel rows retain their available list-page metadata.

### YouTube scraper output and available fields

The default dataset contains one row per unique video. video_id and url identify
the video. title, description_snippet, channel_name, channel_id, channel_url,
published_text, view_count_text, duration_text, thumbnail_url and is_live come
from the available list metadata. source is search, channel or video_url;
input identifies the entry that produced the row. fetched_in_seconds measures
the collection duration and remains a JSON number.

With details enabled, available enrichment includes description, keywords,
duration_seconds, published_date, upload_date, category, like_count,
channel_subscribers and comment_count. keywords is an array of strings.
view_count is an integer or null; other numeric detail fields are omitted when
unavailable. published_date and upload_date retain the full ISO datetime and
timezone offset YouTube supplies. Counters may move between the list response
and the detail response, so view_count can differ from view_count_text.

The output also includes fetched_at in UTC and applicable common social fields,
including platform, post_id, post_url, author_id, author_handle, text, posted_at,
views, likes and comments_count. Original field names remain available.
The summary and any coded errors are stored in the run's key-value store.

This is a selection of fields from a real response collected on 2 October 2026:

```json
{
  "video_id": "XVv6mJpFOb0",
  "url": "https://www.youtube.com/watch?v=XVv6mJpFOb0",
  "title": "Web Scraping with Python - Beautiful Soup Crash Course",
  "channel_name": "freeCodeCamp.org",
  "channel_id": "UC8butISFwT-Wl7EV0hUK0BQ",
  "published_date": "2020-11-18T08:05:43-08:00",
  "upload_date": "2020-11-18T08:05:43-08:00",
  "view_count": 1823734,
  "like_count": 39409,
  "comment_count": 1100,
  "duration_seconds": 4103,
  "keywords": [],
  "source": "search",
  "input": "web scraping tutorial",
  "fetched_in_seconds": 54.32,
  "fetched_at": "2026-10-02T17:11:50.400Z"
}
```

### Use cases for a YouTube video scraper

- **Marketing and influencer research.** Search a topic and collect which channels
  publish about it, how many views and likes their videos get and how recent they are.
- **Competitor tracking.** Put competitor channel handles in queries and run on a
  schedule to follow their new uploads, view counts and comment counts over time.
- **Content and SEO planning.** Collect titles, keyword tags, durations and publish
  dates for a search term to see which formats rank and what the top videos cover.
- **Datasets for analysis and AI.** Export video metadata as JSON, CSV or Excel for
  dashboards, notebooks or as structured input for language-model workflows.
- **Checking specific videos.** Paste a list of video links to refresh their view,
  like and comment counts without opening each page.

### How this YouTube scraper compares

The official YouTube Data API requires a Google Cloud project, an API key and a
daily quota in which each search request uses a large share of the allowance.
This actor needs none of that: you pay per delivered video and the input is a
plain list of search terms, channels and links.

Other YouTube scrapers in the Store charge between roughly $0.0005 and $0.004 per
video on the free plan, and some add separate events for date filters or extras.
This actor has a single video event ($0.0028 on the free plan, down to $0.0009 on
higher plans) and no extra charge for sorting, upload-date filters, feature filters
or detail enrichment. It focuses on video metadata: it does not download video
files, transcribe audio or collect the text of individual comments; comment_count
gives the number of comments per video.

### Pricing

The existing pay-per-event model charges one video event per delivered dataset
row. The price per video is $0.0028 on FREE, $0.00191802 on BRONZE,
$0.00131386 on SILVER and $0.0009 on GOLD, PLATINUM and DIAMOND.
Apify's actor-start event costs $0.0002 per GB of configured memory, with a
minimum of one event. A run with up to 1 GB of memory, as this actor uses, incurs one start event.
The Apify pricing panel remains the source for your plan's applicable rate.

Sorting, date filters, quality filters and detail enrichment have no additional
result events. A delivered minimal video-URL row also counts as one video.
An empty dataset has no video charge; the platform start event still applies.
Free-plan users receive at most ten videos per run, across all inputs combined.
Paid users retain the configured per-input volume within the run time available.

### Limits and result quality

Larger requests are collected in successive pages automatically. Search results
and channel uploads depend on public availability and YouTube's current order.
A missing channel produces an error entry and no video row. An error in one
input does not remove successful results from another. When a requested detail
cannot be obtained, the video remains available with the fields that were
retrieved and the run output reports the incomplete work.

Localized display strings should be stored alongside numeric values if your
workflow needs the exact text YouTube showed. Channel list parsing retains its
existing English label behavior: some other-language counts can be null unless
detail enrichment supplies the numeric value. Unavailable values are never
invented. Exact counters, titles and dates can change as the source changes.

### FAQ

#### Can I mix search terms, video links and channels?

Yes. Put each entry in queries. The actor processes them in order, removes
duplicate videos and keeps the first matching input as the row's provenance.

#### Does the YouTube scraper require a YouTube API account?

No. You do not need to provide a Google Cloud key or OAuth credentials to collect
these public videos. The actor uses public video metadata available on YouTube.

#### How do I collect recent videos?

For keyword searches, set upload_date to a recent window such as week or month,
and optionally sort_by to date. These filters apply to searches, not channel
inputs or specific video links.

#### Why is a detail field missing?

YouTube may hide a counter or omit metadata for an unavailable video. Detail
fields are optional. Turn fetch_details on to request them; the scraper returns
the values the source actually provides, with incomplete work reported in the
run output when a detail request fails.

#### Is this a YouTube API alternative?

For video metadata, yes. It returns titles, channels, views, likes, comment counts,
tags, durations and dates for search results, channel uploads and single videos,
without a quota or an API key. It does not upload videos or manage accounts, which
only the official API can do.

#### How many videos can I scrape per search term?

max_results sets the number per search term or channel, from 1 to 500 (default 20).
Free-plan runs stop at ten videos in total; paid plans get the full number when
YouTube has that many results.

#### Where do the results and errors go?

Video rows go to the default dataset. The key-value store contains the summary,
OUTPUT record and an errors record when an input failed. Use source and input
to trace dataset rows back to the submitted entry.

# 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.

## `is_hd` (type: `boolean`):

Only HD videos. YouTube's HD feature filter. Applies to search-term inputs.

## `has_subtitles` (type: `boolean`):

Only videos with subtitles or closed captions. YouTube's Subtitles/CC filter. Applies to search-term inputs.

## `has_cc` (type: `boolean`):

Only Creative Commons licensed videos. This is a licence filter, not closed captions. Applies to search-term inputs.

## `is_3d` (type: `boolean`):

Only 3D videos. YouTube's 3D feature filter. Applies to search-term inputs.

## `is_live` (type: `boolean`):

Only live streams. YouTube's Live feature filter. Applies to search-term inputs.

## `is_bought` (type: `boolean`):

Only videos you have bought. YouTube's Purchased filter needs a signed-in account to return anything. Search-term inputs only.

## `is_4k` (type: `boolean`):

Only 4K videos. YouTube's 4K feature filter. Applies to search-term inputs.

## `is_360` (type: `boolean`):

Only 360-degree videos. YouTube's 360 feature filter. Applies to search-term inputs.

## `has_location` (type: `boolean`):

Only videos tagged with a filming location. YouTube's Location filter. Applies to search-term inputs.

## `is_hdr` (type: `boolean`):

Only HDR videos. YouTube's HDR feature filter. Applies to search-term inputs.

## `is_vr180` (type: `boolean`):

Only VR180 videos. YouTube's VR180 feature filter. Applies to search-term inputs.

## 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",
  "is_hd": false,
  "has_subtitles": false,
  "has_cc": false,
  "is_3d": false,
  "is_live": false,
  "is_bought": false,
  "is_4k": false,
  "is_360": false,
  "has_location": false,
  "is_hdr": false,
  "is_vr180": false
}
```

# Actor output Schema

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

One row per YouTube video found for the given search terms, video URLs, or channels.

## `output` (type: `string`):

OUTPUT record with the run's counts and status flags.

## `errors` (type: `string`):

Failures with a code and a redacted message. Absent when the run had none.

# 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(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 '{
  "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": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/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/c3Kr0bMgUnDbQTtKu/builds/Gd01SbWYWKWXjMdAM/openapi.json
