# YouTube Scraper: Channel Videos, Search Results, Playlists (`fernandosord/youtube-channel-search-scraper`) Actor

Scrape YouTube channel videos, Shorts and live streams, search results (with date, duration and sort filters) and playlists. Get title, views, publish time, duration, thumbnail and channel details per video, plus optional channel stats. No login or API key.

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

## Pricing

from $3.00 / 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.

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

This YouTube scraper reads the public pages YouTube itself shows and returns one row per video from three places: the Videos, Shorts or Live tab of any channel, YouTube search results (with upload date, duration and sort filters), and playlists. Each row has the title, link, views, publish time, duration, thumbnail, badges and channel details. Turn on a channel info row to also get subscribers, total videos, total views, description, links, joined date and country. No YouTube login, cookie or API key, and no API quota to run out of.

- **Mix inputs in one run.** Channel URLs, `@handles` or channel IDs, search terms and playlist links can all go in the same input. Each row says which input it came from (`input`, `inputType`) and its place in that input (`position`).
- **Channels:** pick the Videos, Shorts or Live tab, and sort by latest, most popular or oldest.
- **Search:** filter by upload date (hour, today, week, month, year), duration (under 4, 4 to 20, over 20 minutes), sort (relevance, upload date, views, rating), and switch between video results and channel results.
- **Playlists:** videos come in playlist order, private and deleted entries are skipped.

### What data you get

| Field | What it holds |
|---|---|
| `videoId`, `url`, `title` | The video and its link (Shorts get a `/shorts/` link) |
| `channelName`, `channelId`, `channelUrl`, `channelHandle`, `channelVerified` | The channel that published it |
| `viewCount`, `viewCountText` | Views as a number and as YouTube shows them. The number is rounded when YouTube only shows "1.9B views" |
| `publishedTimeText`, `publishedAtApprox` | "2 weeks ago" as shown, and an ISO date worked out from it. The date is **approximate**: it is only as precise as the relative text |
| `durationSeconds`, `durationText` | Length of the video |
| `isShort`, `isLive`, `liveViewers`, `badges` | Short or stream flags, people watching a live stream, card badges such as LIVE |
| `thumbnailUrl`, `descriptionSnippet` | Thumbnail and the start of the description (search results only) |
| `input`, `inputType`, `position`, `scrapedAt` | Where the row came from, its rank there and when it was read |
| `playlistId`, `playlistTitle` | Added on playlist rows |
| Channel rows (`rowType: "channel"`) | `channelName`, `channelHandle`, `subscriberCount`, `totalVideos`, `totalViews`, `description`, `joinedDate`, `country`, `links`, `avatarUrl` |

### How to use it

1. Add channels (`@MrBeast`, a channel URL or a `UC...` ID), search terms and/or playlist links. At least one is needed; with none, the Actor runs an example (a channel and a search, 20 videos each) so you can see the output.
2. Set **Max results per input**. Use a large number to take a whole channel.
3. Optional: choose the channel tab and sort, the search filters, and **Add a channel info row**.
4. Run it and export to JSON, CSV or Excel, or call it from the API, Make, Zapier, n8n or an AI agent through the Apify MCP server.

#### Example input

```json
{
  "channels": ["@MrBeast"],
  "searchQueries": ["minecraft speedrun"],
  "maxResultsPerInput": 20,
  "channelContentType": "videos",
  "channelSort": "latest",
  "includeChannelInfo": false
}
```

#### Example output

A video from a channel (real row from an Apify run, thumbnail link shortened):

```json
{
  "rowType": "video",
  "videoId": "_c2e1NcI3Sc",
  "url": "https://www.youtube.com/watch?v=_c2e1NcI3Sc",
  "title": "Beat LeBron In Basketball, Win $100,000",
  "channelName": "MrBeast",
  "channelId": "UCX6OQ3DkcsbYNE6H8uQQuVA",
  "channelUrl": "https://www.youtube.com/channel/UCX6OQ3DkcsbYNE6H8uQQuVA",
  "channelHandle": "@MrBeast",
  "channelVerified": true,
  "viewCount": 46000000,
  "viewCountText": "46M views",
  "liveViewers": null,
  "publishedTimeText": "1 day ago",
  "publishedAtApprox": "2026-11-01T07:49:00.225Z",
  "durationSeconds": 1348,
  "durationText": "22:28",
  "isShort": false,
  "isLive": false,
  "thumbnailUrl": "https://i.ytimg.com/vi/_c2e1NcI3Sc/hq720.jpg",
  "descriptionSnippet": null,
  "badges": [],
  "input": "@MrBeast",
  "inputType": "channel",
  "position": 1,
  "scrapedAt": "2026-11-02T07:49:00.225Z"
}
```

A video from a search (it also carries a description snippet):

```json
{
  "rowType": "video",
  "videoId": "pyV68KvUwlw",
  "url": "https://www.youtube.com/watch?v=pyV68KvUwlw",
  "title": "Minecraft Beaten In 53 Seconds [FWR]",
  "channelName": "HanabiYaki",
  "channelId": "UCBTvGJlfKvqrPkEReXO0TrA",
  "channelUrl": "https://www.youtube.com/channel/UCBTvGJlfKvqrPkEReXO0TrA",
  "channelHandle": "@HanabiYaki",
  "channelVerified": true,
  "viewCount": 5213373,
  "viewCountText": "5,213,373 views",
  "liveViewers": null,
  "publishedTimeText": "2 years ago",
  "publishedAtApprox": "2024-11-02T07:49:00.877Z",
  "durationSeconds": 89,
  "durationText": "1:29",
  "isShort": false,
  "isLive": false,
  "thumbnailUrl": "https://i.ytimg.com/vi/pyV68KvUwlw/hq720.jpg",
  "descriptionSnippet": "Working smarter not harder. This is getting beaten in a few days isn't it... HUGE HUGE thanks to @Curcuit for teaching me on how ...",
  "badges": [],
  "input": "minecraft speedrun",
  "inputType": "search",
  "position": 1,
  "scrapedAt": "2026-11-02T07:49:00.877Z"
}
```

A channel info row (with **Add a channel info row**, description and links shortened):

```json
{
  "rowType": "channel",
  "channelId": "UCLA_DiR1FfKNvjuUpBHmylQ",
  "channelName": "NASA",
  "channelHandle": "@NASA",
  "channelUrl": "https://www.youtube.com/channel/UCLA_DiR1FfKNvjuUpBHmylQ",
  "channelVerified": true,
  "subscriberCountText": "15.1M subscribers",
  "subscriberCount": 15100000,
  "totalVideosText": "6,195 videos",
  "totalVideos": 6195,
  "totalViewsText": "1,133,490,449 views",
  "totalViews": 1133490449,
  "description": "NASA's mission is to pioneer the future in space exploration, scientific discovery, and aeronautics research. ...",
  "joinedDateText": "Joined Jun 3, 2008",
  "joinedDate": "2008-06-03",
  "country": null,
  "links": [
    {
      "title": "nasa.gov",
      "url": "https://www.nasa.gov"
    },
    {
      "title": "X",
      "url": "https://x.com/nasa"
    }
  ],
  "avatarUrl": "https://yt3.googleusercontent.com/eIf5fNPcIcj9ig-wZBeq4stFy1lgjWTW1nLT5dYlFkHZprZ03QBiMcbpwNMB6XSBjrSFGtAGQg=s200-c-k-c0x00ffffff-no-rj",
  "input": "@NASA",
  "inputType": "channel",
  "position": null
}
```

### How much does it cost?

You pay per row saved: $0.003 per video, Short or stream, plus $0.0005 once per run. A channel info row or a channel search result counts as one row. Inputs that fail or find nothing cost nothing and are listed in the `SUMMARY` record of the run's key-value store.

1,000 rows cost about $3.00. Apify's free plan credit of $5 a month covers about 1,600 rows. A run of 40 rows takes a few seconds and uses well under 256 MB.

### Use cases

- **Competitor and creator tracking:** pull a channel's latest uploads on a schedule and watch views, upload rhythm and Shorts against long videos.
- **Topic research:** search a keyword with the last-month and over-20-minutes filters, sorted by views, to see what is working right now.
- **Lead lists:** search for channels on a topic and collect handle, subscribers and description for outreach (pair it with the contact extractor below).
- **Datasets and playlists:** export a playlist or a whole channel catalogue as a spreadsheet.

### FAQ

**Does it need a YouTube API key or login?**
No. It reads the same public data your browser loads. There is no daily quota.

**Why do Shorts rows have no date or duration?**
YouTube's channel Shorts tab shows only the title and view count. Those fields are empty (`null`) for Shorts taken from a channel, and Shorts inside search results show the same limited card.

**How exact is the publish date?**
`publishedTimeText` is what YouTube shows ("3 weeks ago"). `publishedAtApprox` is that text turned into a date, so it can be off by days for "weeks ago" and by months for "years ago". YouTube does not show the exact date on these lists.

**How exact are the view counts?**
Search results show full numbers. Channel and playlist lists show abbreviations such as "46M views", so `viewCount` is rounded there. `viewCountText` always has YouTube's own wording.

**Can it get transcripts or comments?**
Not here. This Actor lists videos. For subtitles use the YouTube Transcript Scraper linked below.

**How many results can I get?**
A whole channel or playlist, until YouTube stops listing. Searches end where YouTube ends the results, often a few hundred. Tested up to 102 rows per input on Apify for a channel, a search and a playlist, and 197 playlist videos in a local run.

**What if YouTube blocks the request?**
In testing on Apify, requests worked both without a proxy and with the default Apify Proxy. If YouTube answers with a refusal (HTTP 403 or 429) the Actor does not try to get around it: it stops, says so in the log and in `SUMMARY`, and you can pick another proxy in the **Proxy** field and run again. Rows already saved stay in the dataset.

**Why is a channel's Live tab empty?**
Only channels that have streamed have a Live tab. The run notes it in `SUMMARY` and moves on.

**Which language and region?**
Text is read in English with a US region, so counts and dates come as "46M views" and "2 weeks ago".

**Duplicates?**
A video is listed once per input. If you give a channel and a search that both contain it, it appears once for each, with a different `input`.

**Is this legal?**
It only reads what YouTube shows publicly. You are responsible for how you use the data and for following YouTube's terms and laws like GDPR when it includes personal data.

### Other Actors by this developer

- [Website Contact Extractor](https://apify.com/fernandosord/website-contact-extractor): emails, phone numbers and social links from the websites you find in channel descriptions.
- [Google Ads Transparency Scraper](https://apify.com/fernandosord/google-ads-transparency-scraper): the ads any advertiser runs on Google, including on YouTube.
- [Craigslist Scraper](https://apify.com/fernandosord/craigslist-scraper): listings from any Craigslist city and category.
- [Y Combinator Companies Scraper](https://apify.com/fernandosord/y-combinator-companies-scraper): YC startups by batch, industry and status, with founders.

# Actor input Schema

## `channels` (type: `array`):

Channel URLs, @handles or channel IDs, for example @MrBeast, https://www.youtube.com/@MrBeast/videos or UCX6OQ3DkcsbYNE6H8uQQuVA. One run can mix channels, searches and playlists.

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

Words to search for on YouTube, one per line. A youtube.com/results?search_query=... link also works and keeps the filters from its sp= parameter.

## `playlists` (type: `array`):

Playlist URLs (youtube.com/playlist?list=...) or playlist IDs (PL...). Videos come in playlist order.

## `maxResultsPerInput` (type: `integer`):

Stop after this many rows for each channel, search term or playlist. The optional channel info row is not counted. Set it high to get a whole channel.

## `channelContentType` (type: `string`):

Which tab of each channel to read. Shorts rows have no duration or publish time, because YouTube does not show them on that tab. Live lists current and past streams.

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

Order of the videos taken from each channel tab.

## `includeChannelInfo` (type: `boolean`):

Adds one extra row per channel with subscribers, total videos, total views, description, links, joined date and country. It is charged like any other row.

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

Videos returns video rows. Channels returns one row per channel found (name, handle, subscribers, description).

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

Order of the search results.

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

Only videos uploaded within this period.

## `searchDuration` (type: `string`):

Only videos of this length. Applies to video searches.

## `searchIncludeShorts` (type: `boolean`):

YouTube mixes Shorts into video search results. Turn off to keep only regular videos.

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

Optional. YouTube's channel, search and playlist pages worked without a proxy in testing. If YouTube refuses your IP the run reports it and stops; then pick Apify Proxy here.

## Actor input object example

```json
{
  "channels": [
    "@MrBeast"
  ],
  "searchQueries": [
    "minecraft speedrun"
  ],
  "maxResultsPerInput": 20,
  "channelContentType": "videos",
  "channelSort": "latest",
  "includeChannelInfo": false,
  "searchType": "video",
  "searchSort": "relevance",
  "searchUploadDate": "any",
  "searchDuration": "any",
  "searchIncludeShorts": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One row per video, Short or live stream, plus optional channel rows.

# 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 = {
    "channels": [
        "@MrBeast"
    ],
    "searchQueries": [
        "minecraft speedrun"
    ],
    "maxResultsPerInput": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fernandosord/youtube-channel-search-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 = {
    "channels": ["@MrBeast"],
    "searchQueries": ["minecraft speedrun"],
    "maxResultsPerInput": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("fernandosord/youtube-channel-search-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 '{
  "channels": [
    "@MrBeast"
  ],
  "searchQueries": [
    "minecraft speedrun"
  ],
  "maxResultsPerInput": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call fernandosord/youtube-channel-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fernandosord/youtube-channel-search-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/Z5AvyCXZZj4h90l9i/builds/nfsT1KhtjZa319cOR/openapi.json
