# YouTube Search Scraper: Videos & Channel Discovery (`deepmine/youtube-search-scraper`) Actor

YouTube search scraper: search by keyword and get videos, Shorts, channels, playlists or movies with views, age, length, channel, badges and chapters, in any country and language, with YouTube's filters. Full likes, comments and channel stats as an add-on. No login, no API key.

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

## Pricing

from $0.15 / 1,000 search results

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 Search Scraper

YouTube search scraper: type search terms and get one row per result, in the order YouTube ranks them: videos, Shorts, channels, playlists or movies, with views, age, length, the channel (name, handle, avatar, verified badge), badges, chapters and the description snippet. Search from any country and in any language, with YouTube's own filters. Exact likes, comments, publish time, tags and channel stats are an optional add-on. No login, no YouTube API key, no browser.

| # | 🎬 Video | 📺 Channel | 👀 Views | 📅 Age | ⏱️ Length | 🏅 Badges | 🔎 Search term |
|---|---|---|---|---|---|---|---|
| 1 | [Python Full Course for Beginners](https://www.youtube.com/watch?v=_uQrJ0TkZlc) | Programming with Mosh ✅ | 49,356,362 | 7 years ago | 06:14:07 | CC | python tutorial |
| 2 | [Python Full Course for free 🐍](https://www.youtube.com/watch?v=ix9cRaBkVe0) | Bro Code ✅ | 12,945,354 | 2 years ago | 12:00:00 | Fundraiser | python tutorial |
| 3 | [Python for Beginners - Learn Coding with Python in 1 Hour](https://www.youtube.com/watch?v=kqtD5dpn9C8) | Programming with Mosh ✅ | 25,645,192 | 6 years ago | 01:00:06 | – | python tutorial |
| 1 | [$100 Colombian Street Food Challenge!!](https://www.youtube.com/watch?v=zyX6HsdOwGU) | More Best Ever Food Review Show ✅ | 1,916,019 | 6 days ago | 00:25:59 | New, 4K | street food |
| 2 | [New York Street Food Marathon!! From $1 to $1000!!](https://www.youtube.com/watch?v=CfjWHzQX9Xk) | More Best Ever Food Review Show ✅ | 2,962,217 | 5 months ago | 01:24:34 | 4K | street food |
| 3 | [INDONESIA’S STREET FOOD HEAVEN! 🇮🇩 The Best Street Foods You Have to Try](https://www.youtube.com/watch?v=gN9mE002aSA) | Ice Tea Jay ✅ | 178,449 | 2 weeks ago | 00:50:23 | 4K | street food |

<sub>Collected on Apify 2026-10-17 with the prefilled input (the first 3 of 50 per search term).</sub>

**$0.20 per 1,000 results on Starter** ($0.24 Free, $0.17 Scale, $0.15 Business). The prefilled run (100 results) costs about **$0.02**. Nothing per run. Full details add $0.10 per 1,000 results, only when you turn them on.

| Plan | Per 1,000 results | With full details |
|---|---|---|
| Free | $0.24 | $0.34 |
| Starter | $0.20 | $0.30 |
| Scale | $0.17 | $0.27 |
| Business | $0.15 | $0.25 |

### What you type

| Input | Example | What it does |
|---|---|---|
| 🔎 Search terms | `python tutorial`, `street food`, or a link like `https://www.youtube.com/results?search_query=lofi+hip+hop&sp=CAMSAhAB` | One YouTube search per term (a link keeps its own filters) |
| 🏷️ Result type | Videos, Shorts, Channels, Playlists, Movies | YouTube's Type filter: one type per run |
| 🔢 Results per search term | `50` (100 when empty, up to 5,000) | How deep each search goes |
| ➕ Full details | on / off (off) | Adds the watch page's or the channel's About panel's fields (below) |
| 🎛️ Sort by, upload date, duration, features | Popularity, This week, Under 3 minutes, HD + Subtitles | YouTube's own search filters, with the same values as its filter dialog |
| 🌍 Country, 🗣️ Language | `MX`, `es` | Search as from that country in that language: YouTube returns different results (es-MX shared 5 to 7 of the first 20 with en-US in our tests) |

A result that several of your terms find is saved and charged once. Ages and counts are read in YouTube's languages (Spanish *hace 21 horas*, German *vor 5 Tagen*, Japanese *14 時間前*, Korean *구독자 177만명*, Hindi *17.7 लाख*...), so every row has numbers as numbers and the text as YouTube wrote it.

### What you get

| Result type | Fields |
|---|---|
| 🎬 Videos, Shorts, movies | `position` (rank in its search), `title`, `type` (`video`, `shorts`, `stream`, `movie`), `id`, `url`, `thumbnailUrl`, `thumbnails`, `previewUrl` (the moving preview YouTube plays on hover, a 6-second animated WebP), `richThumbnail` (its sizes), `viewCount` (exact), `viewCountText`, `date` (the day the age gives), `dateText` (the age as shown), `dateEstimated`, `duration`, `durationSeconds`, `text` (the description snippet), `badges` (New, 4K, CC, Free with ads...), `isLiveNow`, `streamType` (`live`, `scheduled`, `ended`), `scheduledStartAt`, `isMembersOnly`, `chapters` (`title`, `start`, `startSeconds`, `thumbnailUrl`), `channelName`, `channelId`, `channelUrl`, `channelUsername`, `channelAvatarUrl`, `isChannelVerified`, `isChannelArtist`; movies also `movieMetadata` (genre and year, actors, directors) |
| 📺 Channels | `position`, `title` (the channel's name), `id`, `url`, `thumbnailUrl` (avatar), `channelUsername` (handle), `numberOfSubscribers`, `subscribersText`, `text` (description), `isChannelVerified`, `isChannelArtist` |
| 📚 Playlists | `position`, `title`, `id`, `url`, `thumbnailUrl`, `playlistType` (`playlist`, `course`, `podcast`...), `videoCount`, `firstVideoId`, `firstVideos` (the videos the search lists under it), `text`, `channelName`, `channelUrl`, `channelUsername`, `isChannelVerified` |
| 🧾 Every row | `searchQuery`, `input`, `fromYTUrl` (the search with its filters), `country`, `language`, `scrapedAt` |

**➕ With full details**, video, Short and movie rows also get `likes` (exact), `commentsCount` (exact), `commentsTurnedOff`, the exact publish time in `date`, the full description in `text`, `descriptionLinks`, `hashtags`, `keywords` (tags), `category`, `originalLanguage` and `originalLanguageCode` (the language spoken in the video), `audioTracks` (dubbed videos: each audio track's language, and whether it's the original or YouTube's automatic dub), `location`, `isAgeRestricted`, `isUnlisted`, `isPaidContent` ("Includes paid promotion"), `isMonetized` (YouTube serves ads on it to a logged-out viewer; `null` on Shorts), `liveStartedAt`, `liveEndedAt`, Shorts' `soundTitle`, `musicTitle`, `musicArtist`, `collaborators`, and the channel's `numberOfSubscribers`, `channelDescription`, `channelDescriptionLinks`, `channelJoinedDate`, `channelCreatedAt` (when the run read the channel's feed for a publish time), `channelLocation`, `channelTotalVideos`, `channelTotalViews`. Channel rows get the About panel: `channelTotalViews`, `channelTotalVideos`, `channelJoinedDate`, `channelLocation`, `channelDescription`, `channelDescriptionLinks`, and `channelCreatedAt` (the channel's creation time to the second, from its RSS feed; `null` when YouTube's feed doesn't answer). Playlists are always saved as the search shows them.

The dataset has five views: Search results, Video details, Full details (videos), Channels and Playlists.

Measured on 16 runs on Apify on 2026-10-17 (4,135 video rows, 200 channel rows in es-MX, 60 playlists, 150 Shorts, 40 movies, 140 rows with full details):

| Field | Filled |
|---|---|
| `title`, `id`, `url`, `thumbnailUrl`, `viewCount`, `channelName`, `channelId` (videos) | 100% |
| `date`, `dateText`, `duration` (videos) | 100% |
| `text` (videos' snippet) | 100% |
| `badges` (videos) | 59% |
| `chapters` (videos) | 38% |
| `channelUsername` (videos) | 93% |
| `numberOfSubscribers` (channels) | 96% |
| `videoCount`, `firstVideos` (playlists) | 100% |
| `channelId`, `viewCount` (Shorts) | 100% |
| `likes`, `commentsCount`, `category` (full details, videos) | 100% |
| `keywords` (full details, videos) | 88% |
| `channelJoinedDate`, `channelTotalViews` (full details) | 97-100% |

`badges` and `chapters` are filled where YouTube shows them; `channelUsername` is empty for channels without a handle; a channel can hide its subscriber count. Most Shorts searches answer as YouTube's Shorts grid, which shows only the title, views (rounded, 1.2M) and the channel's id: turn on full details for a Short's channel name, exact views, likes, comments, date, length and sound. Movies show no views or age in search.

### Moving from another YouTube search Actor

Paste your saved input as it is: the fields below are read the way those Actors read them.

| Their input | Read here as |
|---|---|
| api-ninja: `query`, `maxResults`, `type`, `sortBy`, `duration`, `uploadDate`, `features`, `geo`, `lang`, `scrapeAllResults`, `videoDepthDetails` | the same search; `standard` / `detailed` / `complete` depth = full details |
| ninhothedev: `queries`, `query`, `maxItems`, `maxResults` | `maxItems` per query, `maxResults` as the total across queries, in input order (`{"queries": ["python tutorial", "javascript tutorial"], "maxItems": 10, "maxResults": 15}` saves 10 + 5); a non-empty `queries` wins over `query` |
| grow_media: `q`, `maxResults`, `order`, `videoDuration`, `regionCode`, `relevanceLanguage`, `useFilters` | the same search; with `useFilters: false` its filters are left out, as it does |
| grow_media: `publishedAfter`, `publishedBefore` | YouTube's `after:` / `before:` search operators, to the day (`fromYTUrl` shows them) |
| grow_media: `eventType` | `live`: YouTube's Live filter; `completed` and `upcoming`: YouTube's search has no filter for them, so streams with that label are kept from its results (upcoming streams are rarely in a search) |
| grow_media: `videoDefinition: high`, `videoLicense: creativeCommon`, `safeSearch: strict` | YouTube's HD and Creative Commons filters, Restricted Mode |

Not available on YouTube's search, so searched without them (the run's notices say so): `videoDefinition: standard`, `videoLicense: youtube`, `order: title` / `videoCount`, `channelType: show`; `safeSearch: moderate` is YouTube's normal search. Search links in `startUrls` keep their own filters. One difference: a video that several of your search terms find is saved and charged once (under the first term), where ninhothedev saves it once per query.

| Their field | Here |
|---|---|
| `videoId`, `video_id` | `id` |
| `channelTitle`, `channel` | `channelName` |
| `description` | `text` |
| `publishedTimeText`, `published_time` | `dateText` |
| `publishDate`, `publishedAt` | `date` |
| `lengthText`, `duration_seconds` | `duration`, `durationSeconds` |
| `thumbnail` | `thumbnails` (`thumbnailUrl` = the largest) |
| `richThumbnail` | `richThumbnail` (`previewUrl` = the largest) |
| `views`, `views_text` | `viewCount`, `viewCountText` |
| `rank`, `order` | `position` |
| `query` | `searchQuery` |
| `channelCreatedAt`, `channelVideoCount`, `channelViewCount` | `channelCreatedAt` (or the day in `channelJoinedDate`), `channelTotalVideos`, `channelTotalViews` (full details) |

| | api-ninja/youtube-search-scraper | grow_media/youtube-search-api | ninhothedev/youtube-search-scraper | This Actor |
|---|---|---|---|---|
| Price per 1,000 results, paid plans | $0.25 until 2026-10-26, then $0.50, plus $0.01 per run | $0.60 / $0.50 / $0.40 | $0.50 | $0.20 / $0.17 / $0.15, no start fee |
| Result types | videos, Shorts, channels, playlists, movies | videos, channels, playlists | videos | videos, Shorts, channels, playlists, movies |
| Country and language | yes | yes | no | yes |
| Likes, comments, channel stats | deeper modes | yes | no | full details (+$0.10 per 1,000) |
| Chapters | key moments in its deeper modes | no | no | yes, in search rows |
| Badges, live and upcoming streams | not declared | live/upcoming filter | no | yes |

Prices are from the Apify Store on 2026-10-16.

### Output

One row per result. A real video row, shortened:

```json
{
  "position": 5,
  "title": "iPhone 17 After 1 Year: Why I Still Love It",
  "type": "video",
  "id": "S71ljmbtERg",
  "url": "https://www.youtube.com/watch?v=S71ljmbtERg",
  "thumbnailUrl": "https://i.ytimg.com/vi/S71ljmbtERg/hq720.jpg",
  "viewCount": 71252,
  "viewCountText": "71,252 views",
  "date": "2026-10-03",
  "dateText": "2 weeks ago",
  "dateEstimated": true,
  "duration": "00:11:36",
  "durationSeconds": 696,
  "text": "iPhone 17 1 year review, iPhone 17 review, Apple iPhone 17 camera test, iPhone 17 battery life, iPhone 17 vs iPhone 17 Pro, ...",
  "badges": ["1 product", "Earns commission"],
  "isLiveNow": false,
  "isMembersOnly": false,
  "chapters": [
    {"title": "Design", "start": "00:00:00", "startSeconds": 0, "thumbnailUrl": "https://i.ytimg.com/vi/S71ljmbtERg/hqdefault_25233.jpg"},
    {"title": "Display", "start": "00:01:41", "startSeconds": 101, "thumbnailUrl": "https://i.ytimg.com/vi/S71ljmbtERg/hqdefault_102866.jpg"}
  ],
  "channelName": "Everyday Legends",
  "channelId": "UCbM-fdGZyGd-NNRpYscDeHA",
  "channelUrl": "https://www.youtube.com/@Everyday_Legends",
  "channelUsername": "Everyday_Legends",
  "isChannelVerified": false,
  "searchQuery": "iphone 17 review",
  "fromYTUrl": "https://www.youtube.com/results?search_query=iphone+17+review&sp=EgIQAQ%3D%3D",
  "country": "US",
  "language": "en",
  "scrapedAt": "2026-10-17T02:18:37Z"
}
```

A channel search in Mexico, in Spanish:

| # | 📺 Channel | 👤 Handle | 👥 Subscribers | ✅ Verified |
|---|---|---|---|---|
| 1 | [El Pan De Valdo](https://www.youtube.com/@ElPanDeValdo) | @ElPanDeValdo | 234,000 (234 K suscriptores) | yes |
| 2 | [COMO HACER PAN SV](https://www.youtube.com/@comohacerpanSV) | @comohacerpanSV | 59,000 (59 K suscriptores) | no |
| 3 | [Mirecetadepan.com](https://www.youtube.com/@Mirecetadepancom) | @Mirecetadepancom | 309,000 (309 K suscriptores) | no |

With full details:

| 🎬 Video | 👀 Views | ❤️ Likes | 💬 Comments | 📅 Published | 🗂️ Category | 👥 Subscribers | 📍 Country |
|---|---|---|---|---|---|---|---|
| [Learn Python - Full Course for Beginners \[Tutorial\]](https://www.youtube.com/watch?v=rfscVS0vtbw) | 49,468,302 | 1,123,445 | 46,093 | 2018-07-11T18:00:42Z | Education | 11,900,000 | United States |
| [Python Full Course for Beginners](https://www.youtube.com/watch?v=_uQrJ0TkZlc) | 49,373,083 | 1,273,475 | 62,928 | 2019-02-18T15:00:08Z | Education | 5,170,000 | United States |

The run's summary (key-value store record `OUTPUT`) lists every search term with how many results it gave and its status, the result type, country, language and filters, and repeats skipped.

### Did it help?

A short review helps others find it: https://apify.com/deepmine/youtube-search-scraper/reviews

# Actor input Schema

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

What to search on YouTube, one term per line (as you'd type it in YouTube's search box). YouTube search links (youtube.com/results?search_query=...) work too, with the filters in the link. Each result is saved and charged once per run, even when several terms find it. Required for API calls: searchQueries, or the same list as query, queries, q or startUrls.

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

What to find: videos, Shorts, channels, playlists or movies (YouTube's own Type filter). One type per run.

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

The most results to save for each search term (100 when left empty). YouTube stops a search after a few hundred results for most terms.

## `fullDetails` (type: `boolean`):

Off: each row is what YouTube's search page shows (fast, the lowest price). On: video, Short and movie rows also get exact likes, comments, the exact publish time, tags, category, the full description and the channel's subscribers, total views, country and join date; channel rows get the channel's About panel. Each such row costs a small add-on (see Pricing). Playlists are always saved as the search shows them.

## `sortBy` (type: `string`):

YouTube's 'Prioritize' order: relevance or popularity (most viewed). Upload date and rating also work.

## `uploadDate` (type: `string`):

Only results uploaded within this time (videos, Shorts and movies).

## `duration` (type: `string`):

Only videos of this length (YouTube's buckets).

## `searchFeatures` (type: `array`):

Only videos with all of these (YouTube's Features filter).

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

Search as from this country: a two-letter code such as US, GB, IN, DE, BR, JP (US when left empty). YouTube ranks results by country.

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

Search in this language: a code such as en, es, pt, fr, de, ja, ko, hi, ar, or pt-BR, zh-TW (en when left empty). YouTube returns different results per language, and writes ages and counts in it; rows keep the text as shown and the numbers as numbers.

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

Apify's datacenter proxy works for every call; there's no need to change it.

## `query` (type: `string`):

One search term, for saved inputs from other YouTube search Actors (query).

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

The same as searchQueries, for saved inputs from other YouTube search Actors (queries).

## `q` (type: `string`):

One search term, for saved inputs from other YouTube search Actors (q).

## `startUrls` (type: `array`):

YouTube search links (youtube.com/results?search_query=...), links or {url} objects.

## `maxItems` (type: `integer`):

The same as maxResults, for saved inputs from other YouTube search Actors (maxItems).

## `geo` (type: `string`):

The same as country (geo).

## `lang` (type: `string`):

The same as language (lang).

## `videoDepthDetails` (type: `string`):

basic = search rows; standard, detailed or complete = full details (the same as fullDetails on).

## `scrapeAllResults` (type: `boolean`):

Read every page YouTube has for each term (up to 5,000 results).

## Actor input object example

```json
{
  "searchQueries": [
    "python tutorial",
    "street food"
  ],
  "type": "video",
  "maxResults": 50,
  "fullDetails": false,
  "sortBy": "relevance",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "searchQueries": [
        "python tutorial",
        "street food"
    ],
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("deepmine/youtube-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 = {
    "searchQueries": [
        "python tutorial",
        "street food",
    ],
    "maxResults": 50,
}

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

```

## MCP server setup

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