# YouTube Scraper: Search, Channels, Playlists & Video Details (`pulsedata/youtube-scraper`) Actor

Scrape YouTube without the API or quotas: keyword search with filters, all videos/Shorts/streams of a channel, playlists, and video details (views, likes, duration, publish date, description, tags, subscribers). Export as JSON, CSV or Excel.

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

## Pricing

from $1.50 / 1,000 video listeds

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/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

YouTube Scraper collects YouTube search results, every video of a channel (Videos, Shorts and Live tabs), every video of a playlist, and full details for single videos. It returns one JSON item per video, channel or playlist, with optional full video details. It costs $1.50 per 1,000 listed items and $3 per 1,000 detailed videos, plus $0.00005 per run.

No YouTube Data API key is needed and there is no daily quota: the actor reads YouTube's public pages.

### Features

- **Scrape YouTube search results** for any keyword, as videos, channels or playlists, sorted by relevance, upload date, view count or rating, and filtered by upload date (last hour, today, this week, this month, this year).
- **Export all videos of a YouTube channel**, including the Shorts and Live tabs, with a channel profile item (subscribers, video count, description, handle, avatar, RSS URL).
- **Export a YouTube playlist to CSV or Excel**, every video with its position in the list.
- **Get YouTube video views, likes and tags without the API**: exact counts, publish date, description, category and subscriber count for a list of video URLs.
- **Find YouTube channels in a niche** with `searchType: "channel"`, with subscriber counts.
- **Get new uploads of a YouTube channel**: with `onlyNewVideos` a scheduled run returns and charges only videos it has not delivered before.
- Accepts channel URLs or `@handles`, playlist URLs or IDs, and watch, `youtu.be`, Shorts, embed and live video URLs.

### Use cases

- **Keyword and SEO research**: see which videos and channels rank for a search term, with their views and upload dates.
- **Competitor tracking and influencer discovery**: record a competitor's new uploads and view counts, or list the channels on a topic.
- **Content audits**: pull every video of a channel, sort by views, and compare Shorts against long-form uploads.
- **Datasets for AI and analytics**: collect video metadata at scale and pass the URLs to the transcript and comments actors listed below.

### Input

Search queries, channels, playlists and single videos can be combined in one run.

```json
{
  "searchQueries": ["python tutorial"],
  "searchType": "video",
  "searchSort": "view_count",
  "searchUploadDate": "year",
  "maxResultsPerQuery": 100,
  "channelUrls": ["https://www.youtube.com/@3blue1brown"],
  "channelTabs": ["videos", "shorts"],
  "maxVideosPerChannel": 0,
  "playlistUrls": ["https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi"],
  "maxVideosPerPlaylist": 0,
  "videoUrls": ["https://www.youtube.com/watch?v=aircAruvnKk"],
  "fetchDetailsForListedVideos": false
}
```

| Field | Type | Default | What it does |
|---|---|---|---|
| `searchQueries` | array | `[]` | Keywords to search, one per line. |
| `searchType` | string | `video` | `video`, `channel` or `playlist`. |
| `searchSort` | string | `relevance` | `relevance`, `upload_date`, `view_count` or `rating`. |
| `searchUploadDate` | string | `any` | `any`, `hour`, `today`, `week`, `month` or `year`. |
| `maxResultsPerQuery` | integer | `50` | Results per query; 0 means as many as YouTube returns. |
| `channelUrls` | array | `[]` | Channel URLs or handles. |
| `channelTabs` | array | `["videos"]` | Any of `videos`, `shorts`, `streams`. |
| `maxVideosPerChannel` | integer | `100` | Per channel and per tab; 0 means all. |
| `playlistUrls` | array | `[]` | Playlist URLs or IDs. |
| `maxVideosPerPlaylist` | integer | `0` | 0 means all. |
| `videoUrls` | array | `[]` | Videos to fetch full details for. |
| `fetchDetailsForListedVideos` | boolean | `false` | Fetch full details for every video found via search, channels and playlists (one extra request per video). |
| `concurrency` | integer | `5` | Parallel detail requests, 1 to 20. |
| `proxyConfiguration` | object | no proxy | Optional Apify Proxy settings. |
| `onlyNewVideos` | boolean | `false` | Monitor mode: output and charge only videos not delivered on an earlier run. |
| `monitorStoreName` | string | empty | Key-value store that remembers delivered videos. Empty means a name derived from the targets and filters. |

### Get new uploads of a YouTube channel

Turn on `onlyNewVideos` to get only the videos a channel uploaded since your last run:

```json
{ "channelUrls": ["https://www.youtube.com/@3blue1brown"], "channelTabs": ["videos", "shorts"], "maxVideosPerChannel": 0, "onlyNewVideos": true }
```

The actor remembers delivered video IDs in a named key-value store in your Apify account and skips them on the next run, so they are neither output nor charged. The first run returns every video up to the limits and fills the store.

How to set up new-upload alerts (a ready task is on the example page [Get new uploads of a YouTube channel](https://apify.com/pulsedata/youtube-scraper/examples/competitor-channel-upload-tracker)):

1. Save the input above as an Apify task.
2. Add an [Apify schedule](https://docs.apify.com/platform/schedules) for the task, daily or weekly.
3. Add an integration on the task (email, Slack, Google Sheets, Make, Zapier or a webhook) that fires when a run succeeds. Each run's dataset then holds only the new videos.

Details:

- A channel tab lists newest first, so a run stops reading it at the first video it already knows. The channel row is returned once, on the first run.
- Known videos still count towards `maxVideosPerChannel`, `maxVideosPerPlaylist` and `maxResultsPerQuery`. Set them to 0 to watch everything; older videos the first run did not reach are not picked up later.
- Video URLs in `videoUrls` are always returned and charged.
- Without `monitorStoreName` each different input keeps its own history; the run log names the store. Schedule one run per store.

### Output

A listed video from a search:

```json
{
  "type": "video",
  "videoId": "lIId8IDP6TU",
  "url": "https://www.youtube.com/watch?v=lIId8IDP6TU",
  "title": "Lecture 2 : Strings & Conditional Statements | Python Full Course",
  "description": "This lecture was made with a lot of love …",
  "channelName": "Shradha Khapra",
  "channelId": "UC1XBh-m27kkgwLAwu_SRJBg",
  "channelUrl": "https://www.youtube.com/@shradhaKD",
  "channelIsVerified": false,
  "publishedTimeText": "2 years ago",
  "publishedAt": "2024-08-19T14:10:45.184Z",
  "durationText": "55:41",
  "durationSeconds": 3341,
  "viewCountText": "6,255,142 views",
  "viewCount": 6255142,
  "thumbnailUrl": "https://i.ytimg.com/vi/lIId8IDP6TU/hq720.jpg",
  "isLive": false,
  "badges": [],
  "source": "search:python tutorial",
  "position": 1
}
```

A detailed video (from `videoUrls` or with `fetchDetailsForListedVideos`) adds `likeCount`, `likeCountText`, the full `description`, `keywords`, `category`, `uploadDate`, `isFamilySafe`, `channelSubscriberCount`, `channelSubscriberCountText` and `detailed: true`, and its `publishedAt` is the exact publish date.

A channel item (first item for each channel URL):

```json
{
  "type": "channel",
  "channelId": "UCYO_jab_esuFRV4b17AJtAw",
  "url": "https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw",
  "handle": "@3blue1brown",
  "handleUrl": "https://www.youtube.com/@3blue1brown",
  "title": "3Blue1Brown",
  "description": "…",
  "subscriberCountText": "8.55M subscribers",
  "subscriberCount": 8550000,
  "videoCountText": "242 videos",
  "videoCount": 242,
  "avatarUrl": "…",
  "rssUrl": "…",
  "source": "https://www.youtube.com/@3blue1brown"
}
```

Notes on the data:

- `publishedAt` on listed videos is computed from YouTube's relative text ("2 years ago"), so it is approximate.
- Items from a channel's Shorts tab contain the title, view count, thumbnail and URL only.
- Channel fields on items from channel tabs may be empty; the channel item has them.
- If a search, channel or playlist fails, the dataset gets an item with `type: "error"` or an `error` field explaining why.

### Pricing

Pay per event. Current prices:

| Event | Price | Per 1,000 |
|---|---|---|
| `video-listed` (a video from search, channel or playlist) | $0.0015 | $1.50 |
| `item-listed` (a channel or playlist item, including the channel profile item) | $0.0015 | $1.50 |
| `video-detail` (a video with full details) | $0.003 | $3 |
| `apify-actor-start` (once per run) | $0.00005 | |

Worked example: one channel with 500 videos in the Videos tab, listed without details, is 1 channel item plus 500 listed videos: 501 x $0.0015 + $0.00005 = $0.75 (rounded). The same channel with `fetchDetailsForListedVideos` on is 500 detailed videos plus the channel item: 500 x $0.003 + $0.0015 + $0.00005 = $1.50 (rounded). With details on, a video is charged only the detailed price.

In monitor mode only new videos and the first run's channel item are charged. A daily run on one channel that finds 3 new videos costs 3 x $0.0015 + $0.00005 = $0.00455; a run with nothing new costs only the $0.00005 start event.

### FAQ

**Do I need a YouTube Data API key?**
No. The actor reads YouTube's public pages, so there is no key and no daily quota.

**How many search results can I get per query?**
Usually several hundred with `maxResultsPerQuery` at 0. For broad terms, combine `searchUploadDate` and `searchSort` or run several related queries.

**What is the difference between listed and detailed videos?**
Listed items come from search, channel or playlist pages with an approximate date. Details add the exact date, likes and the other fields above, at the detailed price.

**Do I need proxies?**
Usually not. If YouTube starts returning errors and you have not set a proxy, the actor retries through Apify residential proxy.

**What can it not do?**
It does not download video files, and it does not return transcripts or comments (use the sister actors below). Private and members-only videos are out of reach.

**How do I export or automate it?**
Download the dataset as JSON, CSV or Excel, call the actor through the Apify API or SDKs, schedule runs, or connect it to Google Sheets, Make, Zapier or n8n.

### Use it from Claude, ChatGPT or Cursor (Apify MCP server)

The actor can be called as a tool by any AI assistant that speaks the Model Context Protocol. Add the Apify MCP server to your client with this URL, which loads only this actor as a tool:

```text
https://mcp.apify.com?tools=pulsedata/youtube-scraper
```

You sign in to Apify on first connection, then ask in plain language, for example "find the 50 most viewed videos about home espresso uploaded this month". Billing is the same as a normal run.

### Paying from an AI agent without an Apify account (x402 and Skyfire)

An agent can buy a prepaid, spend-capped Apify token at [Apify AGI](https://agi.apify.com), paid in USDC through [x402](https://docs.apify.com/platform/integrations/x402) or from a [Skyfire](https://docs.apify.com/platform/integrations/skyfire) wallet, and use it for both the API and the MCP server. This actor runs with limited permissions, so it works with these tokens. The smallest token is $1, tokens expire 14 days after purchase, and Apify marks agentic payments as experimental.

### Example pages

- [Find this week's most viewed videos on a topic](https://apify.com/pulsedata/youtube-scraper/examples/trending-videos-this-week-by-topic)
- [Find YouTube channels in a niche](https://apify.com/pulsedata/youtube-scraper/examples/find-youtube-channels-in-a-niche)
- [Get new uploads of a YouTube channel](https://apify.com/pulsedata/youtube-scraper/examples/competitor-channel-upload-tracker)

### Related actors

- [YouTube Channel Videos Scraper](https://apify.com/pulsedata/youtube-channel-videos-scraper): a channel-only version of this actor with a shorter input form.
- [YouTube Transcript Scraper](https://apify.com/pulsedata/youtube-transcript-scraper): transcripts and subtitles for the video URLs this actor returns.
- [YouTube Comments Scraper](https://apify.com/pulsedata/youtube-comments-scraper): comments and replies for the same videos.
- [Google Ads Transparency Center Scraper](https://apify.com/pulsedata/google-ads-transparency-scraper): see a brand's YouTube video ads alongside its organic uploads.

# Actor input Schema

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

Keywords to search on YouTube, one per line (e.g. `python tutorial`).

## `searchType` (type: `string`):

What to return for search queries.

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

How search results are ordered.

## `searchUploadDate` (type: `string`):

Filter search results by upload date.

## `maxResultsPerQuery` (type: `integer`):

Search results to collect per query (0 = as many as YouTube returns, usually several hundred).

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

Channel URLs (`https://www.youtube.com/@3blue1brown`, `/channel/UC…`, `/c/name`) or handles (`@3blue1brown`). All videos of the Videos tab are scraped (optionally Shorts and live streams).

## `channelTabs` (type: `array`):

Which channel tabs to scrape.

## `maxVideosPerChannel` (type: `integer`):

0 = all videos.

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

Playlist URLs or IDs – all videos are listed.

## `maxVideosPerPlaylist` (type: `integer`):

0 = all.

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

Videos to fetch full details for (exact view/like counts, publish date, description, tags, category, channel subscriber count).

## `fetchDetailsForListedVideos` (type: `boolean`):

Also fetch full details (likes, exact date, description, tags) for videos found via search, channels and playlists. One extra request per video.

## `concurrency` (type: `integer`):

Parallel requests.

## `onlyNewVideos` (type: `boolean`):

Output and charge only videos this monitor has not delivered on an earlier run. The video IDs are remembered in a named key-value store in your account, so a scheduled daily or weekly run returns just the videos uploaded since the last run. Known videos still count towards the per-channel, per-playlist and per-search limits, which set how far down each list a run looks; set them to 0 to watch everything. A channel tab stops at the first video it already knows, and the channel row comes once. Video URLs given directly are always returned. The first run returns everything and fills the store.

## `monitorStoreName` (type: `string`):

Name of the key-value store that remembers delivered videos. Leave empty to name it after the run's targets and filters, so each different input keeps its own history. Set a name to share one history between inputs, or to start over by picking a new one. Letters, digits and hyphens.

## `proxyConfiguration` (type: `object`):

Usually not needed; enable Apify Proxy if YouTube rate-limits your runs.

## Actor input object example

```json
{
  "searchQueries": [
    "best mechanical keyboard 2026"
  ],
  "searchType": "video",
  "searchSort": "relevance",
  "searchUploadDate": "any",
  "maxResultsPerQuery": 50,
  "channelUrls": [
    "https://www.youtube.com/@veritasium"
  ],
  "channelTabs": [
    "videos"
  ],
  "maxVideosPerChannel": 100,
  "playlistUrls": [],
  "maxVideosPerPlaylist": 0,
  "videoUrls": [],
  "fetchDetailsForListedVideos": false,
  "concurrency": 5,
  "onlyNewVideos": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Videos, channels and playlists stored in the default dataset (JSON/CSV/Excel via the dataset API).

# 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": [
        "best mechanical keyboard 2026"
    ],
    "channelUrls": [
        "https://www.youtube.com/@veritasium"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pulsedata/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": ["best mechanical keyboard 2026"],
    "channelUrls": ["https://www.youtube.com/@veritasium"],
}

# Run the Actor and wait for it to finish
run = client.actor("pulsedata/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": [
    "best mechanical keyboard 2026"
  ],
  "channelUrls": [
    "https://www.youtube.com/@veritasium"
  ]
}' |
apify call pulsedata/youtube-scraper --silent --output-dataset

```

## MCP server setup

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