# YouTube Search Scraper (`sedgelabs/youtube-search-scraper`) Actor

Videos and Shorts from any YouTube search, with YouTube's own filters, no login and no duplicates. Optional exact views, likes and publish dates.

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

## Pricing

from $0.35 / 1,000 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

Get the videos and Shorts from any YouTube search, with YouTube's own filters, no login and no API
key. Each video is delivered once: YouTube repeats results on later pages, and you don't pay for
the repeats.

### What you get

One row per unique video or Short, in YouTube's order:

- title, URL, video ID, type (video or Short)
- channel name, ID and handle
- views, length, "3 weeks ago" and an estimated date
- description snippet, thumbnail, live flag
- with **Exact details** on: exact views, likes, publish date and time, full description,
  keywords and category

### Filters

The same filters as YouTube's search page: type (videos, Shorts or both), upload date (today, this
week, this month, this year), length (under 3, 3 to 20, over 20 minutes) and sort (relevance or
popularity). They are applied the way the site applies them, so results match what you'd see.

YouTube itself returns nothing for Shorts with "This week", "This month" or popularity sort. The
actor tells you so when you start the run instead of returning an empty file. For Shorts from a
time window, use [YouTube Shorts Scraper](https://apify.com/sedgelabs/youtube-shorts-scraper)
with a date limit.

"Today" can come back empty for some searches even when YouTube has new uploads for them; the same
search with type set to Videos often returns them. An empty search costs nothing.

### How many results can one search return?

About 300 unique results per search term (316 to 340 for "home workout" across four runs on
2026-10-27). After that YouTube stops serving more. To go wider, split the search: add a few related terms, or run the same
term with different upload-date filters.

### Input example

```json
{
  "queries": ["home workout", "lofi hip hop"],
  "maxResultsPerQuery": 50,
  "type": "videos",
  "uploadDate": "this_month",
  "includeDetails": true,
  "country": "US"
}
```

### Output example

```json
{
  "input": "home workout",
  "rank": 1,
  "type": "video",
  "videoId": "cbKkB3POqaY",
  "url": "https://www.youtube.com/watch?v=cbKkB3POqaY",
  "title": "25 MIN FULL BODY HIIT for Beginners - No Equipment - No Repeat",
  "channelName": "growingannanas",
  "channelHandle": "@growingannanas",
  "viewCount": 34361669,
  "likeCount": 518555,
  "durationSeconds": 1699,
  "publishedAt": "2023-03-12T19:00:07-07:00",
  "publishedTimeText": "3 years ago",
  "category": "Sports",
  "hasExactDetails": true
}
```

The full row has more fields; see the Output tab.

### Pricing

$1.00 per 1,000 results. Exact details, when you turn them on, are a separate event of $1.00 per
1,000 results. Apify's platform usage and proxies are included. Repeats are never charged.

YouTube declines the exact details for a few results in every hundred. Those rows still arrive with
everything the search page shows, and their details charge is not applied.

### Why did a search stop where it did?

Each search gets one plain sentence in `RUN_SUMMARY` (and in the status message when you run one):

- "50 results for "home workout": stopped at your limit of 50."
- "316 results for "home workout": YouTube served no more."
- "0 results for "…": YouTube found no results."

### FAQ

#### Is this an alternative to the YouTube Data API search?

For search results, yes. You don't need a Google Cloud project, an API key or a daily quota.

#### Do I need a YouTube account or proxies?

No. It reads public search results logged out and uses Apify's proxy by default.

#### Why are some fields empty for Shorts?

YouTube's search page shows only a Short's title and rounded views. Turn on **Exact details** to
get its channel, likes, date and length.

#### Can I use it through the API, Make, Zapier or n8n?

Yes, like any Apify actor. Call it with your API token and read the dataset when the run finishes.

#### Is scraping YouTube search results legal?

The actor collects only public information, logged out. You are responsible for how you use it.
If you're unsure, ask a lawyer. Don't use the data for spam, impersonation or any other unlawful
purpose.

This actor is independent and not affiliated with, endorsed by or sponsored by YouTube or Google.
YouTube is a trademark of Google LLC.

### More from Sedge Labs

- [YouTube Comments Scraper](https://apify.com/sedgelabs/youtube-comments-scraper): comments and replies from any public video, Short or live replay.
- [YouTube Shorts Scraper](https://apify.com/sedgelabs/youtube-shorts-scraper): a channel's Shorts with exact views, likes and publish dates.
- [YouTube Channel Scraper](https://apify.com/sedgelabs/youtube-channel-scraper): a channel's videos, Shorts and live streams, with its profile on every row.

### Support

Open an issue on the Issues tab and include your run link.

# Actor input Schema

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

One search per line, as you would type it on YouTube.

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

Stop after this many unique videos and Shorts per search. One YouTube search ends after about 300 unique results, so higher numbers may not be reached.

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

What YouTube's own type filter allows.

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

YouTube's upload-date filter. With Shorts only, YouTube itself returns nothing for This week and This month.

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

YouTube's length filter. Not for Shorts only.

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

YouTube's sort. Not for Shorts only.

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

Also fetch each video's exact views, likes, publish date, full description, keywords and category. One extra request per result, charged as a separate small event. Off: rows show what the search page shows (views, length, "3 weeks ago").

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

Two-letter country code YouTube ranks results for, like US, GB, IN or DE.

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

Proxy for the search and channel pages. Apify's datacenter proxy works for these. Exact details always go through Apify residential IPs at no extra proxy cost to you; YouTube refuses them from datacenter IPs.

## Actor input object example

```json
{
  "queries": [
    "lofi hip hop"
  ],
  "maxResultsPerQuery": 10,
  "type": "all",
  "uploadDate": "any",
  "duration": "any",
  "sortBy": "relevance",
  "includeDetails": false,
  "country": "US",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per unique video or Short.

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

Per search: how many results you got and why it stopped.

# 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": [
        "lofi hip hop"
    ],
    "maxResultsPerQuery": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("sedgelabs/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 = {
    "queries": ["lofi hip hop"],
    "maxResultsPerQuery": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("sedgelabs/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 '{
  "queries": [
    "lofi hip hop"
  ],
  "maxResultsPerQuery": 10
}' |
apify call sedgelabs/youtube-search-scraper --silent --output-dataset

```

## MCP server setup

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