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

Scrape YouTube search results (videos, channels, playlists, movies) without cookies or the API. Title, channel, views, duration, publish date, thumbnails. Full filter support.

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

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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

## YouTube Search Scraper — Videos, Channels & Playlists

Scrape YouTube search results (videos, channels, playlists, movies) without cookies or the API. Title, channel, views, duration, publish date, thumbnails. Full filter support. HTTP + residential proxy primary, managed last-resort fallback. MCP-ready.

### YouTube Search Scraper — Videos, Channels, Playlists & Filters

Use this Apify Actor when you need structured YouTube search results from one or more free-text queries. It accepts terms exactly as they would be typed into the YouTube search bar, and returns one normalized record per search result in a dataset row. Each row can include the result type, query, source, rank, IDs, title, canonical URL, channel details, view counts, publish timing, duration, thumbnails, descriptions, badges, and the scrape timestamp. The Actor is usable through Apify MCP and is designed for workflows that turn YouTube search into structured data.

### Best fit and connected workflows

This Actor fits workflows that start with a topic, keyword list, or market question and end with structured YouTube search results. Common routes include content research, channel discovery, competitive monitoring, trend scanning, and agent-driven search summaries.

A practical workflow looks like this:

- start with one or more search queries
- narrow by result type, date, duration, or feature filters when you want a focused slice
- read the dataset as one row per result
- pass the structured rows into spreadsheets, databases, dashboards, or AI workflows

It also works through Apify MCP, where an agent can search YouTube and consume the results as structured data.

### Practical scenario

Maya, a content strategist, starts with the search query `iphone 18 pro` and sets `resultType` to `video`, `sortBy` to `viewCount`, and `maxResultsPerQuery` to `25`. The dataset returns rows with fields such as `title`, `channelName`, `viewCountText`, `publishedTimeText`, `durationText`, and `url`. Maya uses those fields to identify which videos are surfacing for the query and then decides which channels to track in the next weekly review.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| searchQueries | array\[string] | required | One or more free-text YouTube search terms. Each query is scraped independently and merged into one dataset. |
| maxResultsPerQuery | integer | 50 | Maximum number of results to return for each query across pagination. Applies per query. |
| resultType | string | all | Restrict results to all, video, channel, playlist, or movie. |
| sortBy | string | relevance | Use YouTube-style ordering: relevance, uploadDate, viewCount, or rating. |
| uploadDate | string | any | Filter videos by lastHour, today, thisWeek, thisMonth, or thisYear. |
| duration | string | any | Filter videos by short, medium, or long. |
| features | array\[string] | \[] | Optional feature filters such as live, fourK, hd, subtitles, creativeCommons, threeSixty, vr180, threeD, hdr, location, and purchased. |
| country | string | US | YouTube geo context (gl) and proxy country. |
| language | string | en | YouTube interface/content language (hl). |
| rawSpToken | string | empty | Advanced override for a raw YouTube sp filter token. |
| fallbackMode | string | auto | Controls when managed fallback engages: auto, never, or always. |
| proxyConfiguration | object | residential | Proxy settings for the direct HTTP scrape. Residential proxies are the default. |

**Example input**

```json
{
  "searchQueries": ["iphone 18 pro", "tech reviews 2026"],
  "maxResultsPerQuery": 25,
  "resultType": "video",
  "sortBy": "viewCount",
  "uploadDate": "thisYear",
  "duration": "medium",
  "features": ["hd", "subtitles"],
  "country": "US",
  "language": "en",
  "fallbackMode": "auto"
}
```

### Output

The default dataset contains one normalized YouTube search result per row. The main fields are stable across result types, with some fields populated only for videos, channels, or playlists.

| Field | Type | Description |
|---|---|---|
| type | string | Result kind: video, channel, playlist, or movie. |
| query | string | The search query that produced the result. |
| source | string | youtube for direct scrape, managed-fallback for managed fallback. |
| position | integer | 1-based rank within the query. |
| videoId | string or null | YouTube video ID for video and movie results. |
| playlistId | string or null | YouTube playlist ID for playlist results. |
| channelId | string or null | Channel ID for the owner or channel result. |
| title | string or null | Result title. |
| url | string or null | Canonical URL to the result. |
| channelName | string or null | Owning channel display name. |
| channelUrl | string or null | Owning channel URL. |
| viewCount | integer or null | Parsed numeric view count. |
| viewCountText | string or null | Raw view count text as shown by YouTube. |
| publishedTimeText | string or null | Relative publish time text. |
| durationText | string or null | Video duration text. |
| durationSeconds | integer or null | Video duration in seconds. |
| thumbnailUrl | string or null | Highest-resolution thumbnail URL available. |
| description | string or null | Short description snippet. |
| isLive | boolean | True when the result is a live broadcast. |
| isVerified | boolean | True when the channel or owner has a verified badge. |
| badges | array\[string] | Additional badges such as New, CC, or 4K. |
| subscriberCountText | string or null | Subscriber count text for channel results. |
| videoCountText | string or null | Video count text for channel or playlist results. |
| playlistVideoCount | integer or null | Number of videos in a playlist result. |
| scrapedAt | string | ISO 8601 timestamp of the scrape. |

### How it works

The Actor uses direct HTTP scraping over residential proxies as its primary path. It parses YouTube search results, supports query-level filtering, and returns a normalized dataset. If YouTube returns challenges during direct scraping, the Actor can use a managed fallback depending on fallbackMode.

The filtering controls map to YouTube search behavior:

- `resultType` narrows the result kind
- `sortBy` mirrors YouTube ordering options
- `uploadDate` and `duration` apply only where video results are present
- `features` applies one or more YouTube feature filters
- `rawSpToken` lets advanced users supply a raw sp token directly

The dataset schema includes source, so each row shows whether it came from direct YouTube scraping or from the fallback path.

### Pricing

YouTube Search Scraper - Videos, Channels, Playlists & Filters uses Pay per event pricing plus Apify platform usage. The billed events are tied to search results returned, actor start usage, and managed fallback queries when that path is used. Apify platform usage is billed separately according to the active Apify plan and runtime resources.

### Use with AI agents (MCP)

This Actor is MCP-ready and usable through Apify MCP. The tool exposes YouTube search as a structured workflow where an agent provides search terms and receives normalized results.

- **Tool description**: Search YouTube by free-text query and return structured search results with result type, ranking, channel metadata, timing, and URLs.
- **Actor identity**: `extractlabs/youtube-search-scraper`

#### Apify API Example

```javascript
import { ApifyClient } from "apify-client";

const client = new ApifyClient({
  token: process.env.APIFY_TOKEN,
});

const input = {
  searchQueries: ["iphone 18 pro", "tech reviews 2026"],
  maxResultsPerQuery: 5,
  resultType: "video",
  sortBy: "relevance",
  country: "US",
  language: "en",
  fallbackMode: "auto",
};

const run = await client.actor("extractlabs/youtube-search-scraper").call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### FAQ

**Can I search multiple queries in one run?**
Yes. Provide an array in searchQueries, and each query is scraped independently before the results are merged into one dataset.

**Which result types can this Actor return?**
It returns YouTube search results for videos, channels, playlists, and movies.

**How do I focus on only videos?**
Set `resultType` to `video`. You can also combine it with `sortBy`, `uploadDate`, `duration`, and `features`.

**When does managed fallback appear in the output?**
When direct scraping needs the fallback path and fallbackMode allows fallback, the source field shows `managed-fallback` for those rows.

**Can I use this in an Apify MCP workflow?**
Yes. This Actor is MCP-ready and can be used through Apify MCP with the actor identity `extractlabs/youtube-search-scraper`.

### Responsible use

This Actor extracts publicly available YouTube search result data. Use the output in ways that respect YouTube's terms, applicable law, and any obligations tied to personal data, copyright, or local privacy rules. Review the source site, your jurisdiction, and your intended use before storing or sharing the data.

# Actor input Schema

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

One or more free-text YouTube search terms. Each query is scraped independently and merged into one dataset.

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

Maximum number of results to return for each query across pagination.

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

Restrict results to all, video, channel, playlist, or movie.

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

Use YouTube-style ordering: relevance, uploadDate, viewCount, or rating.

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

Filter videos by lastHour, today, thisWeek, thisMonth, or thisYear.

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

Filter videos by short, medium, or long.

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

Optional feature filters such as live, fourK, hd, subtitles, creativeCommons, threeSixty, vr180, threeD, hdr, location, and purchased.

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

YouTube geo context (gl) and proxy country.

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

YouTube interface/content language (hl).

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

Advanced override for a raw YouTube sp filter token.

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

Controls when managed fallback engages: auto, never, or always.

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

Proxy settings for the direct HTTP scrape.

## Actor input object example

```json
{
  "searchQueries": [
    "react tutorial 2025"
  ],
  "maxResultsPerQuery": 50,
  "resultType": "all",
  "sortBy": "relevance",
  "uploadDate": "any",
  "duration": "any",
  "features": [],
  "country": "US",
  "language": "en",
  "rawSpToken": "",
  "fallbackMode": "auto",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `overview` (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": [
        "react tutorial 2025"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("extractlabs/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": ["react tutorial 2025"] }

# Run the Actor and wait for it to finish
run = client.actor("extractlabs/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": [
    "react tutorial 2025"
  ]
}' |
apify call extractlabs/youtube-search-scraper --silent --output-dataset

```

## MCP server setup

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