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

Search YouTube by keyword and extract video IDs, titles, channels, view counts, durations, upload labels, and thumbnails. Apply source filters and pre-write keyword/view filters with no API key or browser required.

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

## Pricing

from $1.50 / 1,000 video results

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### What does YouTube Search Scraper do?

YouTube Search Scraper searches public YouTube videos by keyword and returns flat discovery rows for content research, SEO audits, creator discovery, competitor monitoring, and lead-generation workflows. Each row keeps the original query, video URL, title, channel identity, views, upload label, duration, thumbnail, visible badges, and rank within the fetched results.

The actor is video-only by design. It reads the same signed-out search results a visitor sees, uses YouTube's own public source filters, and applies your keyword and minimum-view filters before writing records. No YouTube Data API key, Google login, browser session, or video download is required.

### What data can you extract from YouTube search?

- Video identity — `videoId`, canonical `url`, `title`, `thumbnailUrl`, and `resultRank`.
- Performance signals — parsed `viewCount` plus the original `viewCountText` label.
- Publishing and format — `publishedText`, `durationSeconds`, `durationText`, and visible `badges`.
- Channel context — `channelId`, `channelName`, `channelHandle`, and `channelUrl` when YouTube exposes them.
- Query context — `searchQuery`, `matchedKeywords`, `sourceUrl`, and `scrapedAt` for traceability.

Search snippets and compact view labels are source fields, not estimates from a separate analytics system. Like counts, comment counts, full descriptions, tags, transcripts, private channel analytics, and channel or playlist rows are outside this video-discovery contract.

### How to use YouTube Search Scraper

1. Open YouTube Search Scraper and click **Try for free**.
2. Enter one or more keyword phrases in **Search queries**, such as `AI tools for small business` or `competitor analysis`.
3. Choose a YouTube source filter, set the result and page caps, and optionally add include, exclude, or minimum-view filters.
4. Click **Run**. Each query is fetched independently, so one failed query does not discard successful queries.
5. Open the Dataset tab to download JSON, CSV, or Excel, or read the dataset through the Apify API.

### How much does it cost?

YouTube Search Scraper uses pay-per-event pricing. The planned FREE-tier price is **$0.0015 per emitted video result ($1.50 per 1,000 videos)** plus a **$0.003 actor-start event per run**. The start event covers the fixed source-request cost even when filters emit zero videos. Filtered-out, duplicate, and invalid rows do not create result events. Keep `maxPagesPerQuery` at `1` for recurring checks and raise it only when you need deeper search coverage.

### Input

`searchQueries` is required and accepts one or more keyword phrases. `maxResultsPerQuery`, `maxPagesPerQuery`, and `maxItems` bound the run. `sourceFilter` selects relevance, popularity, an upload window, or a duration band. Include and exclude phrases are case-insensitive and run before dataset writes.

```json
{
  "searchQueries": ["AI tools for small business", "creator analytics"],
  "maxResultsPerQuery": 20,
  "maxPagesPerQuery": 1,
  "sourceFilter": "week",
  "includeKeywords": ["AI"],
  "excludeKeywords": ["shorts", "livestream replay"],
  "minViews": 1000,
  "maxItems": 50,
  "dryRun": false
}
```

### Output

Each output row represents one unique video that survived the configured filters. Nullable source fields remain `null` when a search result does not expose them.

```json
{
  "searchQuery": "apify",
  "videoId": "KQIo1gNFAeM",
  "url": "https://www.youtube.com/watch?v=KQIo1gNFAeM",
  "title": "Apify FULL GUIDE 2025 (Scrape Literally Anything)",
  "viewCount": 55422,
  "viewCountText": "55,422 views",
  "publishedText": "1 year ago",
  "durationSeconds": 6652,
  "durationText": "1:50:52",
  "thumbnailUrl": "https://i.ytimg.com/vi/KQIo1gNFAeM/hq720.jpg",
  "channelId": "UCbo-KbSjJDG6JWQ_MTZ_rNA",
  "channelName": "Nick Saraev",
  "channelHandle": "@nicksaraev",
  "channelUrl": "https://www.youtube.com/@nicksaraev",
  "descriptionSnippet": "A complete guide to Apify actors and datasets.",
  "badges": ["4K"],
  "matchedKeywords": [],
  "sourceUrl": "https://www.youtube.com/results?search_query=apify&sp=EgIQAQ%3D%3D",
  "resultRank": 2,
  "scrapedAt": "2026-08-24T15:00:00.000Z"
}
```

### Integrations

Trigger runs with the [Apify API](https://docs.apify.com/api/v2), schedules, or webhooks, then send the dataset to Make, n8n, Zapier, Google Sheets, Slack, or your own Python and Node.js workflow. JSON, CSV, and Excel exports are available from the Dataset tab.

### Related actors

- [YouTube Video Scraper](https://apify.com/schnellscrapers/youtube-video-monitor) — monitor public channel uploads with date, topic, and view filters.
- [YouTube Shorts Scraper](https://apify.com/schnellscrapers/youtube-shorts-monitor) — collect Shorts from specific channels.
- [YouTube Channel Stats Scraper](https://apify.com/schnellscrapers/youtube-channel-stats-scraper) — retrieve one profile row per public channel.

### FAQ

#### How does YouTube Search Scraper work?

It requests the public YouTube search page for each query, reads the video cards and continuation token returned in that page, and walks only the bounded number of pages you request. Source filters are sent to YouTube before pagination; local include, exclude, and minimum-view filters run before records are written.

#### Can I use YouTube Search Scraper as an API?

Yes. Start the Actor through the [Apify API](https://docs.apify.com/api/v2/actor-runs), wait for the run to finish, and read the default dataset at the URL returned in the run object.

#### Can I use YouTube Search Scraper in Python or Node.js?

Yes. Use `apify-client` to start a run and iterate over its dataset:

```js
const run = await client.actor("YOUR_USERNAME/youtube-search-scraper").call({
  searchQueries: ["AI tools for small business"],
  maxResultsPerQuery: 20
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

#### Does it need a YouTube login or API key?

No. The default input uses public signed-out search pages and page continuation requests. It does not ask for a Google account, OAuth token, YouTube Data API key, cookies, or a proxy configuration.

#### Does it return channels, playlists, comments, or transcripts?

No. It returns video discovery rows only. Use the channel, Shorts, or transcript actor when your workflow needs those separate data shapes.

#### Is it legal to scrape YouTube with YouTube Search Scraper?

The actor reads public search results and does not make a legal determination. You are responsible for how you use the output and for following the rules that apply to your workflow, location, and account.

### Your feedback

If a search field changes, a useful filter is missing, or a query returns an unexpected row, open an issue from the Actor page with the input and a short reproduction. Feature requests for content research and creator-marketing workflows are welcome.

# Actor input Schema

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

One or more YouTube keyword searches, such as `AI tools for small business` or `competitor analysis`. Each query is processed independently.

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

Cap video candidates collected for each query before local filters. Start with `20` for a low-cost discovery run.

## `maxPagesPerQuery` (type: `integer`):

Bound the initial page plus continuation pages fetched for each query. One page is the cheapest recurring check; increase it for deeper discovery.

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

Hard cap on unique videos written across all queries after filters. Excluded videos are never emitted or billed as results.

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

Apply one of YouTube's public search filters before pagination: relevance, popularity, upload window, or duration band. Choose `relevance` for the default video search.

## `includeKeywords` (type: `array`):

Keep a video when its title, channel name, snippet, or badge contains at least one case-insensitive phrase. Filtering happens before dataset writes.

## `excludeKeywords` (type: `array`):

Drop a video when its title, channel name, snippet, or badge contains any case-insensitive phrase. Filtering happens before dataset writes.

## `minViews` (type: `integer`):

Keep only videos with at least this parsed view count. Videos without a source view count are excluded when this is greater than zero.

## `dryRun` (type: `boolean`):

Fetch, filter, and validate videos without writing dataset records. Use this to preview matched versus written counts without result events.

## Actor input object example

```json
{
  "searchQueries": [
    "AI tools for small business"
  ],
  "maxResultsPerQuery": 20,
  "maxPagesPerQuery": 1,
  "maxItems": 1000,
  "sourceFilter": "relevance",
  "includeKeywords": [],
  "excludeKeywords": [],
  "minViews": 0,
  "dryRun": false
}
```

# Actor output Schema

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

Video URL, ID, title, views, upload label, duration, thumbnail, channel metadata, matched keywords, and source query.

# 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": [
        "AI tools for small business"
    ],
    "includeKeywords": [],
    "excludeKeywords": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("schnellscrapers/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": ["AI tools for small business"],
    "includeKeywords": [],
    "excludeKeywords": [],
}

# Run the Actor and wait for it to finish
run = client.actor("schnellscrapers/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": [
    "AI tools for small business"
  ],
  "includeKeywords": [],
  "excludeKeywords": []
}' |
apify call schnellscrapers/youtube-search-scraper --silent --output-dataset

```

## MCP server setup

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