# YouTube Scraper - Search, Channels, Playlists, Shorts, No Key (`benthepythondev/youtube-scraper`) Actor

Returns YouTube videos from search terms, channels, playlists and video links in one run: title, exact views, likes, upload date, length, description, channel and subscribers. Whole channel histories, Shorts and live streams, exact date ranges. No API key, no login, no browser.

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

## Pricing

from $1.20 / 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

Returns YouTube videos from search terms, channels, playlists and video links in one run, without an API key, a login or a browser. One row per video: title, exact views, likes, upload date, length, description, channel and its subscribers. It reads a channel's whole history, its Shorts and live streams, and cuts out an exact date range.

**Price:** $1.50 per 1,000 videos on the Apify Free plan, down to $1.20 from the Gold plan up. A channel, playlist or video that does not exist costs nothing. Export to JSON, CSV or Excel, run on a schedule, call via API, or connect to Make, Zapier or n8n.

### 🔎 What is the YouTube Scraper?

YouTube's own pages load their lists from a few data endpoints: one for a channel's tabs and playlists, one for search, one for a single video. This Actor calls those endpoints directly. There is no quota as with the official YouTube Data API, and no browser to pay for: a run needs 512 MB of memory.

#### What data does it extract?

- **Video:** id, link, title, type (video, Short or live), length, preview picture
- **Numbers:** views and likes; the number of comments for videos given by link
- **Dates:** the exact upload day, and the age the list shows ("3 weeks ago")
- **Text:** the complete description
- **Channel:** name, id, link, @handle, verified badge, subscribers
- **Source:** the search term or link that led to the row, its type and the video's place in that list

#### What users of YouTube scrapers ask for, and what this Actor does

The issue pages of the two most used general YouTube Actors on Apify were read on October 4, 2026. These requests repeat:

| Asked for there | Here |
|---|---|
| A real date range, and date filters that work | `publishedAfter` and `publishedBefore` are applied to the exact upload day. One channel's videos from September 1 to 15 came back as 5 rows in 4 seconds |
| More than the first 200 videos of a channel | A tab is read to its end: 5,304 videos of one channel in 53 seconds |
| Shorts and live streams | Channel tabs you choose, or a link that ends in `/shorts` or `/streams`; every row says which type it is |
| Correct view counts | Exact views, likes and dates come from each video's own data, not from the rounded list |
| Playlists that return nothing | Playlists are read from YouTube's list endpoint, 100 videos a request; a playlist that does not exist is named in the status message |
| Charges without rows | Only saved rows are charged |

### ⬇️ Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `queries` | array | | Search terms |
| `urls` | array | | Channels (link, `@handle` or `UC…` id), playlists, videos, Shorts and search result pages, in any mix |
| `maxResults` | integer | 20 | Videos to save per search term, channel tab and playlist, up to 20,000 |
| `contentTypes` | array | videos | Channel tabs to read: `videos`, `shorts`, `streams` |
| `includeDetails` | boolean | true | Exact views, likes, upload day, full description and subscribers for every video. Off: list values only, several times faster |
| `publishedAfter` | string | | A day (YYYY-MM-DD) or a period back from now (`7 days`, `2 months`) |
| `publishedBefore` | string | | Upper end of a date range (YYYY-MM-DD) |
| `channelSort` | string | `latest` | `latest`, `popular` or `oldest` |
| `uploadedWithin` | string | any | Search filter: `today`, `week`, `month`, `year` |
| `videoLength` | string | any | Search filter: `short` (under 3 minutes), `medium` (3 to 20), `long` (over 20) |
| `searchSort` | string | `relevance` | `relevance` or `popularity` |
| `minViews` | integer | | Keep videos with at least this many views |

An empty input runs a sample search (python tutorial).

#### Example input

A search and two channels:

```json
{
  "queries": ["home workout"],
  "urls": ["https://www.youtube.com/@NASA", "@veritasium"],
  "maxResults": 100
}
```

Everything a channel uploaded in September, with its Shorts:

```json
{
  "urls": ["https://www.youtube.com/@NASA"],
  "contentTypes": ["videos", "shorts"],
  "publishedAfter": "2026-09-01",
  "publishedBefore": "2026-09-30",
  "maxResults": 500
}
```

A channel's whole video list, fast, without exact values:

```json
{
  "urls": ["https://www.youtube.com/@TED"],
  "includeDetails": false,
  "maxResults": 20000
}
```

The most viewed videos about a topic from this week:

```json
{
  "queries": ["openai"],
  "uploadedWithin": "week",
  "searchSort": "popularity",
  "maxResults": 30
}
```

#### Coming from another YouTube Actor?

These input names of the two most used YouTube Actors are read as they are: `searchQueries`, `startUrls`, `maxResults`, `maxResultsShorts`, `maxResultStreams`, `sortVideosBy`, `dateFilter`, `lengthFilter`, `sortingOrder`, `oldestPostDate`, and `keywords`, `youtubeHandles`, `maxItems`. An input like this one runs here unchanged:

```json
{
  "searchQueries": ["Crawlee"],
  "maxResults": 10,
  "maxResultsShorts": 5,
  "startUrls": [{ "url": "https://www.youtube.com/@LofiGirl" }],
  "sortVideosBy": "POPULAR"
}
```

### ⬆️ Output

One row per video, the same columns in every row. A video given by link (the description is shortened here):

```json
{
  "id": "jNQXAC9IVRw",
  "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
  "title": "Me at the zoo",
  "type": "video",
  "viewCount": 439934381,
  "likes": 19992291,
  "commentsCount": 10633160,
  "date": "2005-04-23",
  "publishedText": null,
  "duration": null,
  "durationSeconds": null,
  "thumbnailUrl": "https://i.ytimg.com/vi/jNQXAC9IVRw/hqdefault.jpg",
  "channelName": "jawed",
  "channelId": "UC4QobU6STFB0P71PMvOGN5A",
  "channelUrl": "https://www.youtube.com/channel/UC4QobU6STFB0P71PMvOGN5A",
  "channelHandle": "@jawed",
  "isChannelVerified": true,
  "numberOfSubscribers": 6650000,
  "text": "Microplastics are accumulating in human brains at an alarming rate …",
  "playlistId": null,
  "playlistTitle": null,
  "position": null,
  "input": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
  "inputType": "video",
  "scrapedAt": "2026-10-04T14:02:41.600753+00:00"
}
```

A row from a search, a channel or a playlist also carries `publishedText`, `duration`, `durationSeconds` and its `position` in that list; a playlist row carries `playlistId` and `playlistTitle`. The names `id`, `url`, `title`, `viewCount`, `likes`, `commentsCount`, `date`, `duration`, `thumbnailUrl`, `channelName`, `channelUrl`, `numberOfSubscribers` and `text` are those of the most used YouTube Actor, so code written for it reads these rows. The run also writes a `SUMMARY` record that names the inputs that were not found and the reason a run stopped.

### 💰 What a run costs

| Apify plan | Per 1,000 videos |
|---|---|
| Free | $1.50 |
| Bronze | $1.40 |
| Silver | $1.30 |
| Gold, Platinum, Diamond | $1.20 |

Apify's standard start event ($0.00005) is the only other charge; proxies are included. The price is the same with and without exact values. Not charged: an input that does not exist, a video outside your date limits or below `minViews`. Set the run's maximum charge and the Actor stops at it with the rows it has saved.

### ⏱️ Measured (October 4, 2026)

| Run | Videos | Time |
|---|---|---|
| Empty input (sample search, exact values) | 20 | 6 s |
| Two searches, a channel, its Shorts tab, a playlist and a video link | 51 | 14 s |
| 300 videos of one channel with exact values | 300 | 49 s |
| One channel's whole video tab, list values only | 5,304 | 53 s |
| A channel's videos and Shorts, list values only | 501 | 5 s |
| A channel's uploads of September 1 to 15 | 5 | 4 s |
| This week's most viewed videos for a search term | 30 | 9 s |

### 🤖 For AI agents

Smallest useful call:

```json
{"queries": ["home workout"], "maxResults": 20}
```

Each row is one video with `title`, `url`, `viewCount`, `likes`, `date`, `duration`, `text`, `channelName` and `numberOfSubscribers`. Put channel, playlist or video links into `urls`; both fields take several entries. Add `"publishedAfter": "7 days"` for recent uploads. An input that does not exist returns no rows; the status message and the `SUMMARY` record name it. No credentials are needed.

### 💡 Use cases

- 📊 **Channel and competitor analysis:** every upload of a channel with views, likes and dates, to see what works.
- 🔎 **Topic and trend research:** what ranks for a keyword, and what was uploaded about it this week.
- 🤝 **Creator sourcing:** channels behind the top videos of a niche, with subscribers and handles.
- 🧠 **Datasets for models:** titles and full descriptions of thousands of videos, with their numbers.

### ⚠️ Limits, stated plainly

- **A search ends after roughly 150 to 250 results.** YouTube stops there. More terms and filters reach further, and the status message says when a search ended early.
- **No transcripts and no comment texts.** The [YouTube Transcript Scraper](https://apify.com/benthepythondev/youtube-transcript-scraper) and the [YouTube Comments Scraper](https://apify.com/benthepythondev/youtube-comments-scraper) return those.
- **Without exact values a row carries what the list shows:** views rounded by YouTube and an age instead of a date, no likes and no description. `publishedBefore` needs exact values.
- **A video given by link comes without its length.** The length is part of a list, not of the video's own data.
- **The number of comments is filled for video links only.**
- **A date limit on a channel needs the order "latest".** With "popular" or "oldest" the whole tab is read and filtered.
- **Subscriber counts are rounded by YouTube** ("6.65M").
- **No dislikes, no video files, no channel "about" page.**
- **A video link that leads nowhere** is reported as not found and costs nothing.

### ❓ FAQ

**Do I need a YouTube API key or an account?** No. The Actor reads what YouTube shows a visitor.

**How many videos can I get from a channel?** All of them. A tab is read 30 videos per request to its end; 5,304 videos took 53 seconds without exact values, 300 videos with exact values 49 seconds.

**How do I get only recent uploads?** Set `publishedAfter` to a day or to a period such as `7 days`. Put the run on a schedule for a daily list of new videos.

**Can I mix searches, channels and playlists?** Yes. Every row says in `input` and `inputType` where it came from.

**Why are views in some rows rounded?** With `includeDetails` off a row carries the list's values. Turn it on for exact numbers.

**Does it return Shorts?** Yes: choose `shorts` in `contentTypes`, or give a channel link that ends in `/shorts`. Searches return Shorts mixed in, marked by `type`.

**What happens when a channel or video does not exist?** It is named in the status message and costs nothing; the other inputs are read.

**How do I call it from code?** With the Apify API or the Python and JavaScript clients; every run returns a dataset you can fetch as JSON or CSV. It also works as a tool through Apify's MCP server.

**Is it legal?** The Actor reads public video data that YouTube shows to everyone without a login. Descriptions can contain personal data: GDPR, CCPA and similar rules apply to how you store and use it, and YouTube's terms apply to you as well.

### 🔗 You might also like

- [YouTube Comments Scraper](https://apify.com/benthepythondev/youtube-comments-scraper): comments and replies of videos
- [YouTube Transcript Scraper](https://apify.com/benthepythondev/youtube-transcript-scraper): what is said in a video, as text
- [YouTube Search Results Scraper](https://apify.com/benthepythondev/youtube-search-results-scraper): keyword rankings with rank and filters
- [TikTok Profile Videos Scraper](https://apify.com/benthepythondev/tiktok-profile-videos-scraper): every video of a TikTok profile with its numbers
- [Instagram Reels Scraper](https://apify.com/benthepythondev/instagram-reels-scraper): reels of public Instagram accounts

**Keywords:** youtube scraper, youtube video scraper, youtube channel scraper, youtube search scraper, youtube playlist scraper, youtube shorts scraper, youtube data api alternative, youtube views and likes export, youtube channel videos csv, youtube video metadata, youtube date range, youtube trending videos by keyword, no api key youtube scraper, youtube competitor analysis, youtube data for ai

# Actor input Schema

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

Each term is searched on YouTube like in the search box. YouTube ends a search after roughly 150 to 250 results; more terms reach further.

## `urls` (type: `array`):

Channels (link, @handle or UC… id), playlists, single videos or Shorts, and search result pages, in any mix. A channel link that ends in /shorts or /streams reads that tab.

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

Rows to save for each search term, each channel tab and each playlist. A video link is one row.

## `contentTypes` (type: `array`):

Which tabs of a channel to read. Videos if nothing is chosen. The limit above applies to each tab.

## `includeDetails` (type: `boolean`):

Opens each video's watch page data for exact views, likes, the upload date, the full description and the channel's subscribers. Without it a row carries what the list shows: rounded views and an age such as "3 weeks ago", and a run is several times faster.

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

A day (YYYY-MM-DD) or a period back from now (7 days, 2 months). Channels are read newest first and left at the first page of older videos; searches use YouTube's own date filter. With exact values on, the limit is applied to the exact upload date.

## `publishedBefore` (type: `string`):

Upper end of a date range (YYYY-MM-DD). Needs exact values, because a list only shows an age.

## `channelSort` (type: `string`):

YouTube's own orders of a channel tab. Date limits need latest first.

## `uploadedWithin` (type: `string`):

YouTube's upload date filter for searches. YouTube mixes a few older videos in; the Actor drops them.

## `videoLength` (type: `string`):

YouTube's length filter for searches.

## `searchSort` (type: `string`):

The two orders YouTube offers for search results.

## `minViews` (type: `integer`):

Keeps videos with at least this many views. Videos below it are not saved and not charged.

## Actor input object example

```json
{
  "queries": [
    "python tutorial"
  ],
  "maxResults": 20,
  "includeDetails": true,
  "channelSort": "latest",
  "uploadedWithin": "any",
  "videoLength": "any",
  "searchSort": "relevance"
}
```

# Actor output Schema

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

No description

## `summary` (type: `string`):

No description

# 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": [
        "python tutorial"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("benthepythondev/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": ["python tutorial"] }

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

```

## MCP server setup

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