# YouTube Search Scraper — Results, Ranks & Filters (No API Key) (`fabrikit/youtube-search-scraper`) Actor

Scrape YouTube search results for any keyword or search URL: videos, Shorts, channels and playlists with rank, views, publish date, duration, channel and snippet. Same filters as YouTube (type, upload date, duration, sort, features), any region. No API key, no login. From US$0.45 per 1,000 results.

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

## Pricing

from $0.45 / 1,000 search result scrapeds

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 Search Scraper — Results, Ranks & Filters (No API Key)

**YouTube Search Scraper extracts search results from youtube.com** for any keyword or search-page URL: the videos, Shorts, channels and playlists YouTube lists for that query, in the order YouTube shows them, with rank, views, publish date, duration, channel, badges and description snippet. It uses the same filters as the YouTube search page (result type, upload date, duration, sort order, features such as live, 4K or subtitles), works for any region, and needs no YouTube API key, no Google account and no browser. You pay per result row.

This Actor is the search-only edition of our [YouTube Videos Scraper](https://apify.com/fabrikit/youtube-videos-scraper), which also reads channels, playlists and single videos with per-video details. Use this one when the **search result page is what you care about**: keyword rankings, what competes for a query, which channels and playlists appear, and how that changes over time. For channel-centric data see our [YouTube Channel Scraper](https://apify.com/fabrikit/youtube-channel-scraper), for Shorts feeds the [YouTube Shorts Scraper](https://apify.com/fabrikit/youtube-shorts-scraper) and for comment threads the [YouTube Comments Scraper](https://apify.com/fabrikit/youtube-comments-scraper).

### What you get

One flat row per search result, all types in the same table:

| Field | Example | Notes |
|---|---|---|
| `resultType` | `video`, `short`, `channel`, `playlist` | what the row is |
| `position`, `page` | `1`, `1` | rank in YouTube's list for that search and the page it came from |
| `searchQuery`, `searchUrl` | `espresso machine review`, `https://www.youtube.com/results?search_query=…` | the search that produced the row |
| `id`, `url`, `title` | `mAYbmcqPphc`, `https://www.youtube.com/watch?v=mAYbmcqPphc` | video, Short, channel or playlist id and link |
| `channelName`, `channelId`, `channelHandle`, `channelUrl` | `James Hoffmann`, `UCMb0O…`, `@jameshoffmann` | owner of the video or playlist; the channel itself for channel rows |
| `viewCount`, `viewCountText` | `830643`, `830,643 views` | exact for videos, rounded for Shorts (as YouTube shows them) |
| `liveViewers`, `isLive`, `isUpcoming` | `430`, `true`, `false` | live streams and premieres |
| `publishedText`, `publishedAt` | `2 months ago`, `2026-08-21T00:00:00.000Z` | the relative text and an approximate ISO date derived from it |
| `duration`, `durationSeconds` | `34:16`, `2056` | videos only |
| `badges`, `isVerified` | `["4K", "CC"]`, `true` | YouTube badges (New, 4K, CC, LIVE, products…) and the channel's verification mark |
| `descriptionSnippet` | `Join The Drip Feed Newsletter…` | the snippet YouTube shows; e-mails and phone numbers are hidden |
| `thumbnailUrl` | `https://i.ytimg.com/vi/…` | |
| `subscriberCount`, `subscriberCountText` | `53600`, `53.6K subscribers` | channel rows |
| `videoCount` | `17` | playlist rows |
| `shelfTitle` | `Shorts`, `Ultimate Food Hacks` | Shorts that came from a titled shelf on the page |
| `estimatedResults` | `8157369` | YouTube's total estimate for the query |
| `scrapedAt` | ISO time | |

A `SUMMARY` record in the key-value store lists, per search, the estimated total, pages read, rows listed and saved, any query correction YouTube applied ("showing results for…") and errors.

### Use cases

- **YouTube SEO and rank tracking** — schedule a daily run for your target keywords and see which videos, channels and Shorts hold the top positions and how your own content moves.
- **Competitor and niche research** — list the top results for "best budget 3D printer" or "recetas veganas" with views, dates and lengths to see what works in a niche.
- **Channel discovery and lead lists** — `resultType: channel` returns the channels YouTube ranks for a topic with subscriber counts, handles and snippets.
- **Content and playlist research** — playlists per keyword with their video counts and owners; long or recent videos only with the duration and upload-date filters.
- **Datasets for analytics and AI** — titles, snippets, ranks and engagement numbers as JSON, CSV or Excel for dashboards, LLM pipelines or model training on public metadata.

### How to use it

1. Enter one or more **search keywords** (or paste **YouTube search URLs** copied from your browser; their filters are kept).
2. Pick the **result type** (all, videos, Shorts, channels, playlists, live) and, if you want, **sort order**, **upload date**, **duration** and **features**.
3. Set **max results per search** and **max results (total)**, optionally the **region**.
4. Run it and download the dataset as JSON, CSV, Excel or HTML, or read it through the API.

#### Input example: top results for two keywords

```json
{
  "searchQueries": ["espresso machine review", "best espresso machine under 500"],
  "resultType": "all",
  "maxResultsPerQuery": 50,
  "maxItems": 100
}
```

#### Input example: most viewed long videos of the last month, UK region

```json
{
  "searchQueries": ["react tutorial"],
  "resultType": "video",
  "sortBy": "views",
  "uploadDate": "month",
  "duration": "long",
  "region": "GB",
  "maxItems": 50
}
```

#### Input example: channels for a topic, plus a search URL with its own filters

```json
{
  "searchQueries": ["space agency"],
  "searchUrls": ["https://www.youtube.com/results?search_query=nasa+artemis&sp=CAISBAgCEAE%253D"],
  "resultType": "channel",
  "maxResultsPerQuery": 20
}
```

The `sp` part of a search URL is YouTube's own filter code: a URL keeps it, so you can set up a search on youtube.com, copy the address and paste it here. (In this example the URL asks for today's videos sorted by upload date, while the keyword uses the input filters.)

### Output example

A real video row from a local test run on 19 October 2026:

```json
{
  "resultType": "video",
  "position": 1,
  "page": 1,
  "searchQuery": "espresso machine review",
  "searchUrl": "https://www.youtube.com/results?search_query=espresso+machine+review",
  "id": "mAYbmcqPphc",
  "url": "https://www.youtube.com/watch?v=mAYbmcqPphc",
  "title": "The Fellow ES1 Espresso Machine Review",
  "channelName": "James Hoffmann",
  "channelId": "UCMb0O2CdPBNi-QqPk5T3gsQ",
  "channelHandle": "@jameshoffmann",
  "channelUrl": "https://www.youtube.com/@jameshoffmann",
  "viewCount": 830643,
  "viewCountText": "830,643 views",
  "liveViewers": null,
  "publishedText": "2 months ago",
  "publishedAt": "2026-08-21T00:00:00.000Z",
  "duration": "34:16",
  "durationSeconds": 2056,
  "isLive": false,
  "isUpcoming": false,
  "isVerified": true,
  "badges": ["4K", "CC"],
  "descriptionSnippet": "Join The Drip Feed Newsletter (and check out the first issue) here: https://thedripfeed.coffee/ Our video which explains what a PID ...",
  "thumbnailUrl": "https://i.ytimg.com/vi/mAYbmcqPphc/hq720.jpg?sqp=…",
  "subscriberCount": null,
  "subscriberCountText": null,
  "videoCount": null,
  "shelfTitle": null,
  "estimatedResults": 8157369,
  "scrapedAt": "2026-10-20T01:23:32.414Z"
}
```

Channel rows fill `subscriberCount` and `descriptionSnippet`; playlist rows fill `videoCount` and the owner channel; Short rows carry the rounded views and the shelf they came from.

### Pricing

Pay per event: **US$0.45 per 1,000 results** saved (US$0.00045 per row), proxy and compute included.

- 100 results ≈ US$0.05
- 1,000 results = US$0.45
- 10,000 results = US$4.50

Rows are charged only when saved; duplicates within a search are not. If you set a maximum cost per run, the Actor stops cleanly when it is reached.

### How it compares

- **YouTube Data API v3** — official, but needs a Google Cloud project and key, and each `search.list` call costs 100 quota units for 50 results, so the default daily quota caps you at about 5,000 results a day. It also does not reproduce the mixed result page (Shorts shelves, channels and playlists in rank order) that visitors actually see. This Actor reads that page.
- **Other YouTube search scrapers in the Store** — the most used ones charge between US$0.50 and US$2.50 per 1,000 results. This one costs US$0.45, returns all four result types with rank and page, and accepts YouTube's own filter codes from search URLs.
- **Limits** — YouTube decides how deep a search goes; in our tests a query kept paging past 100 results (about 20 videos plus Shorts shelves per page). `publishedAt` is derived from the relative text YouTube shows ("2 months ago"), so it is approximate; Shorts in search carry rounded views and no date or length. Our [YouTube Videos Scraper](https://apify.com/fabrikit/youtube-videos-scraper) adds exact dates, likes, tags and descriptions when you need them.

### Integrations

Call it from the Apify API, the JavaScript or Python client, or schedule it in Apify Console. Send the results to n8n, Make, Zapier, Google Sheets, Airtable or a webhook. AI agents (Claude, ChatGPT, Cursor and other MCP clients) can discover and run it through the Apify MCP server, e.g. "get the top 20 YouTube results for *home espresso* sorted by views".

### FAQ

**Is it legal to scrape YouTube search results?** The Actor reads only the public search page YouTube shows to logged-out visitors. Channel names, handles and snippets can be personal data when a channel belongs to a private person, so laws such as GDPR, CCPA or Chile's Ley 21.719 may apply to how you store and use them; e-mail addresses and phone numbers are hidden in snippets. Videos belong to their creators. This is not legal advice.

**Do I need a proxy?** No setup needed. The Apify datacenter proxy is used by default; if YouTube blocks it twice in a row, the run switches to Apify residential proxy (country = `region`) for the rest of the run.

**Why do positions skip numbers when I pick "video"?** They don't: with `resultType: video` YouTube itself returns a videos-only list, so ranks are consecutive. With `all`, Shorts shelves, channels and playlists take their own positions, exactly as on the page.

**Are results the same as in my browser?** Close, but not identical: YouTube personalises and varies the layout (where Shorts shelves appear, which related channels are shown). The Actor sends no account or history, so you get the neutral page for the chosen `region`.

**Does it return comments, likes or video descriptions?** No. Search pages carry the snippet only; use the YouTube Videos Scraper with details for the full description, likes and tags.

**Which languages work?** Any query in any language. Keep `language: en` so view counts and dates are parsed; results themselves depend on the query and the `region`.

### Changelog

- **2026-10-19** — First version: keyword and search-URL input, all four result types with rank and page, YouTube's filters (type, upload date, duration, sort, features), region and language, continuation paging, pay per result.

### En español

**YouTube Search Scraper** extrae los resultados de búsqueda de YouTube para cualquier palabra clave o URL de búsqueda, sin API key ni login: videos, Shorts, canales y listas de reproducción en el orden en que YouTube los muestra, con posición, vistas, fecha aproximada, duración, canal, insignias y fragmento de descripción. Admite los mismos filtros que la página de YouTube (tipo de resultado, fecha de subida, duración, orden y características como directo, 4K o subtítulos), cualquier región, y respeta el código de filtros `sp` de una URL copiada del navegador. Cobra US$0,45 por cada 1.000 resultados guardados, con proxy incluido. Para detalles por video (likes, fecha exacta, etiquetas), canales o comentarios usa nuestro [YouTube Videos Scraper](https://apify.com/fabrikit/youtube-videos-scraper) y sus hermanos.

# Actor input Schema

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

One search per entry, exactly as you would type it on YouTube, e.g. "espresso machine review", "recetas veganas", "#booktok". Quotes, minus signs and other YouTube search operators work too.

## `searchUrls` (type: `array`):

Search-results pages copied from your browser, like https://www.youtube.com/results?search_query=nasa+artemis\&sp=CAISBAgCEAE%253D. Filters chosen on youtube.com (the sp part) are kept; a URL without filters uses the filters below.

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

Everything YouTube lists (videos, Shorts, channels, playlists) or just one type. "Live" means live streams only.

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

Order of the results: relevance (YouTube's default), upload date (newest first), view count or rating.

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

Only results uploaded in this period.

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

Video length: under 4 minutes, 4 to 20 minutes, or over 20 minutes.

## `features` (type: `array`):

Extra YouTube filters; a result must match all of them. Live = live streams, HD/4K/HDR = picture quality, subtitles = closed captions, creativeCommons = CC-licensed videos, 360 / VR180 / 3D = immersive formats.

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

How many rows to keep for each keyword or URL (YouTube serves about 20 videos per page, plus Shorts shelves, and usually stops after a few hundred results).

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

Stop after this many rows across all searches. You pay only for the rows that are saved.

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

Two-letter country code YouTube uses to rank and localise the results (US, GB, DE, MX, BR, IN...). It also sets the country of the residential fallback proxy.

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

YouTube interface language sent with the requests (en, es, pt, de...). Keep "en" unless you need shelf titles in another language: view counts and relative dates are parsed from English text.

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

Apify datacenter proxy is enough in normal runs. If YouTube blocks it twice in a row (HTTP 403/429 or a consent page), the Actor switches to RESIDENTIAL proxy by itself for the rest of the run.

## Actor input object example

```json
{
  "searchQueries": [
    "espresso machine review"
  ],
  "resultType": "all",
  "sortBy": "relevance",
  "uploadDate": "any",
  "duration": "any",
  "features": [],
  "maxResultsPerQuery": 100,
  "maxItems": 20,
  "region": "US",
  "language": "en",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Every result saved during the run (videos, Shorts, channels, playlists) with its rank, query and metadata

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

Per-search counts (estimated results, pages, rows), filters used, proxy used and any errors

# 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": [
        "espresso machine review"
    ],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fabrikit/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": ["espresso machine review"],
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("fabrikit/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": [
    "espresso machine review"
  ],
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call fabrikit/youtube-search-scraper --silent --output-dataset

```

## MCP server setup

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