# YouTube Search & Video Metrics \[Only $0.9💰] Scraper (`memo23/youtube-search-results-scraper`) Actor

Scrape YouTube search results without login or API key. Metrics mode returns flat analytics rows — parsed views, duration, channel, publish age — per video, with free title/age filters (filtered videos never charged). Schedule it for keyword monitoring. JSON or CSV.

- **URL**: https://apify.com/memo23/youtube-search-results-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Lead generation, AI, Agents
- **Stats:** 175 total users, 30 monthly users, 99.3% runs succeeded, 5 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.90 / 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.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## YouTube Search & Video Metrics Scraper

Turn any YouTube search into structured video data — no login, no API key, no quota.
Paste search URLs or plain keywords and get video titles, channels, view counts, durations, publish age, and thumbnails as JSON or CSV.

**Metrics mode** returns one flat, analytics-ready row per video (parsed `views` number, `durationSeconds`, `publishedAgeDays`, `isLive`) and skips YouTube's non-video junk (shelves, ads, channel cards) — so you only pay for actual videos. Combine with the free title and age filters and a schedule, and it becomes a keyword-monitoring pipeline.

### Features

- **Metrics mode**: flat analytics rows — parsed view counts, duration in seconds, publish age in days, live-stream flag, originating query, `checkedAt` timestamp.
- **Free result filters**: `titleMustInclude`, `titleExclude`, and `maxAgeDays` run BEFORE billing — filtered videos are never charged.
- **Junk-row protection**: in metrics mode, shelves/ads/channel cards are skipped, not billed.
- **RUN\_SUMMARY diagnostics**: every run writes pages parsed, items seen, junk skipped, and per-filter drop counts — "why did I get fewer videos?" is answered by the run itself.
- **Flexible input**: YouTube search URLs or plain keywords/search terms.
- **Raw mode** (default): the full YouTube renderer object per result, for consumers that want everything.
- **Proxy support** and concurrency control.

### Metrics mode — YouTube keyword tracking

Set `"metricsMode": true`:

```json
{
  "videoId": "1nVGaNbvuXg",
  "url": "https://www.youtube.com/watch?v=1nVGaNbvuXg",
  "title": "How I'd Learn Data Engineering in 2026 From Zero to Senior",
  "channelName": "Data with Baraa",
  "channelUrl": "https://www.youtube.com/@DataWithBaraa",
  "views": 166861,
  "viewsText": "166,861 views",
  "publishedTimeText": "5 months ago",
  "publishedAgeDays": 150,
  "durationText": "32:59",
  "durationSeconds": 1979,
  "isLive": false,
  "query": "data engineering",
  "position": 1,
  "checkedAt": "2026-07-08T09:59:20.000Z"
}
```

Typical setups:

- **Keyword monitoring**: schedule the same queries with `maxAgeDays: 7` — each run returns only fresh uploads for your niche.
- **Competitor tracking**: query competitor brand names, sort the dataset by `views`.
- **Content research**: `titleMustInclude` / `titleExclude` shape the result set before you pay for a single row.

### How to Use

1. Set Up: Ensure you have an Apify account and access to the Apify platform.
2. Configure Input: Set the YouTube search URL(s) or keyword(s) you want to scrape results for (see Input Data section).
3. (Optional) Adjust additional parameters like `maxItems`, concurrency, and proxy settings.
4. Run the Scraper: Execute the scraper on the Apify platform.
5. Data Collection: The scraper will output data in your chosen format, which can include JSON, CSV, or others as supported by Apify.

### Input Configuration

Here's an example of how to set up the input for the YouTube Search Results Scraper:

```json
{
    "startUrls": [
        "music",
        "https://www.youtube.com/results?search_query=medical"
    ],
    "maxItems": 100,
    "maxConcurrency": 10,
    "minConcurrency": 1,
    "maxRequestRetries": 3,
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
}
```

#### Input Fields Explanation

- `startUrls`: Array of YouTube search URLs or keywords/search terms.
- `metricsMode`: Output one flat analytics row per video instead of the raw renderer object (default: false).
- `titleMustInclude`: Keep only videos whose title contains at least one of these terms — free, never charged (default: \[]).
- `titleExclude`: Drop videos whose title contains any of these terms — free (default: \[]).
- `maxAgeDays`: Drop videos older than N days; 0 disables the age filter — free (default: 0).
- `maxItems`: Maximum number of search result items to scrape (default: 100).
- `maxConcurrency`: Maximum number of pages processed simultaneously (default: 10).
- `minConcurrency`: Minimum number of pages processed simultaneously (default: 1).
- `maxRequestRetries`: Number of retries for failed requests (default: 3).
- `proxy`: Proxy configuration for enhanced scraping reliability.

### Output Structure

The output data includes detailed information about each search result item. The structure can vary depending on the type of result (video, playlist, channel, etc.). Here's a more comprehensive breakdown of the output structure, focusing on a playlist item:

```json
{
    "radioRenderer": {
        "playlistId": "RDQMsHhx03c4Dwk",
        "title": {
            "simpleText": "Mix - Music"
        },
        "thumbnail": {
            "thumbnails": [
                {
                    "url": "https://i.ytimg.com/vi/859u6uiZdds/hqdefault.jpg?sqp=-oaymwEWCKgBEF5IWvKriqkDCQgBFQAAiEIYAQ==&rs=AOn4CLAEZ8uHdyBRjh16O5H9eUfB5hTotQ",
                    "width": 168,
                    "height": 94
                },
                // ... more thumbnail sizes ...
            ],
            "sampledThumbnailColor": {
                "red": 89,
                "green": 66,
                "blue": 53
            }
        },
        "videoCountText": {
            "runs": [
                {
                    "text": "50+ videos"
                }
            ]
        },
        "navigationEndpoint": {
            "clickTrackingParams": "CLcDELs3GAAiEwj558GAhd6IAxVIcA8CHV5aOmUyBnNlYXJjaA==",
            "commandMetadata": {
                "webCommandMetadata": {
                    "url": "/watch?v=859u6uiZdds&list=RDQMsHhx03c4Dwk&start_radio=1",
                    "webPageType": "WEB_PAGE_TYPE_WATCH",
                    "rootVe": 3832
                }
            },
            "watchEndpoint": {
                "videoId": "859u6uiZdds",
                "playlistId": "RDQMsHhx03c4Dwk",
                "params": "OALAAQE%3D",
                "continuePlayback": true,
                "loggingContext": {
                    "vssLoggingContext": {
                        "serializedContextData": "Gg9SRFFNc0hoeDAzYzREd2s%3D"
                    }
                }
            }
        },
        "videos": [
            {
                "childVideoRenderer": {
                    "title": {
                        "simpleText": "Tujamo - Down (Official Music Video)"
                    },
                    "lengthText": {
                        "accessibility": {
                            "accessibilityData": {
                                "label": "3 minutes, 15 seconds"
                            }
                        },
                        "simpleText": "3:15"
                    },
                    "videoId": "859u6uiZdds"
                }
            },
            // ... more videos ...
        ],
        "longBylineText": {
            "simpleText": "C. Tangana, Öwnboss, ELYAZ, and more"
        },
        "thumbnailOverlays": [
            {
                "thumbnailOverlayBottomPanelRenderer": {
                    "text": {
                        "simpleText": "Mix"
                    },
                    "icon": {
                        "iconType": "MIX"
                    }
                }
            },
            // ... more overlays ...
        ]
    }
}
```

#### Field Explanations

- `radioRenderer`: Contains information about a YouTube Mix playlist.
  - `playlistId`: Unique identifier for the playlist.
  - `title`: Title of the playlist.
    - `simpleText`: Plain text of the title.
  - `thumbnail`: Information about the playlist's thumbnail image.
    - `thumbnails`: Array of thumbnail objects with different sizes.
      - `url`: URL of the thumbnail image.
      - `width`: Width of the thumbnail in pixels.
      - `height`: Height of the thumbnail in pixels.
    - `sampledThumbnailColor`: Average color of the thumbnail, useful for UI design.
  - `videoCountText`: Indicates the number of videos in the playlist.
  - `navigationEndpoint`: Contains data for navigating to the playlist.
    - `clickTrackingParams`: Used by YouTube for analytics.
    - `commandMetadata`: Metadata for the navigation action.
    - `watchEndpoint`: Specific data for starting playback.
      - `videoId`: ID of the first video in the playlist.
      - `playlistId`: ID of the playlist to be played.
      - `params`: Additional parameters for playback.
  - `videos`: Array of video objects in the playlist.
    - `childVideoRenderer`: Contains information about each video.
      - `title`: Title of the video.
      - `lengthText`: Duration of the video.
        - `accessibility`: Accessible version of the duration.
        - `simpleText`: Formatted duration string.
      - `videoId`: Unique identifier for the video.
  - `longBylineText`: Description of the playlist content, often listing featured artists.
  - `thumbnailOverlays`: Array of overlay information displayed on the thumbnail.
    - `thumbnailOverlayBottomPanelRenderer`: Information for the bottom panel overlay.
      - `text`: Text displayed in the overlay.
      - `icon`: Icon type used in the overlay.

This structure provides a comprehensive view of a playlist item in YouTube search results. It includes details about the playlist itself, its thumbnail, navigation data, and information about the videos contained within the playlist. The actual output may include additional fields or vary slightly depending on the specific type of search result (e.g., individual videos, channels, or other content types).

### Support

- For issues or feature requests, please use the [Issues](https://console.apify.com/actors/9ezF2UTn4xgBvKUfG/issues) section of this actor.
- If you need customization or have questions, feel free to contact the author:
  - Author's website: <https://muhamed-didovic.github.io/>
  - Email: <muhamed.didovic@gmail.com>

### Additional Services

- Request customization or whole dataset: <muhamed.didovic@gmail.com>
- If you need anything else scraped, or this actor customized, email: <muhamed.didovic@gmail.com>
- For API services of this scraper (no Apify fee, just usage fee for the API), contact: <muhamed.didovic@gmail.com>

### FAQ

#### Do I need a YouTube API key or account?

No. The actor reads YouTube's public search surface — no login, no API key, no Google quota.

#### What's the difference between metrics mode and the default output?

Default output is YouTube's raw renderer object per result — every field YouTube sends, for developers who want it all. Metrics mode outputs one flat row per video with parsed numbers (views, duration in seconds, publish age in days) — for spreadsheets, dashboards, and scheduled keyword tracking. Metrics mode also skips non-video results (shelves, ads, channel cards), so you only pay for videos.

#### Are the filters really free?

Yes. `titleMustInclude`, `titleExclude`, and `maxAgeDays` run before rows are saved, so filtered videos are never charged.

#### Why did I get fewer videos than `maxItems`?

Check the `RUN_SUMMARY` record in the run's key-value store — it reports pages parsed, items seen, junk skipped, and how many videos each filter dropped.

#### How accurate is `publishedAgeDays`?

It's derived from YouTube's relative label ("3 weeks ago"), so it's approximate — precise enough for freshness filtering, not for exact timestamps.

***

### 🤖 For AI Agents & LLM Apps

Compact reference for AI agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the Apify API (actor: `memo23/youtube-search-results-scraper`).

**Purpose:** Scrape YouTube search results into structured video rows (title, channel, views, duration, publish age), with an optional flat metrics mode that skips non-video junk — no login, API key, or quota.

**Minimal input:**

```json
{ "startUrls": ["music"], "maxItems": 25 }
```

URL variant (same field): `"startUrls": ["https://www.youtube.com/results?search_query=medical"]`.

**Output (metrics mode):** one row per video — videoId, url, title, channelName, channelUrl, views, viewsText, publishedTimeText, publishedAgeDays, durationText, durationSeconds, isLive, query, position, checkedAt. Default mode returns YouTube's raw renderer object per result instead.

**Behaviors an agent should know:**

- Always set `maxItems` (default 100); an uncapped run follows all search-result pages for every query.
- `startUrls` accepts both YouTube search URLs and plain keywords in the same array.
- Set `metricsMode: true` for flat analytics rows and to skip shelves, ads and channel cards (not billed); default output is the raw renderer object.
- Free filters `titleMustInclude`, `titleExclude`, `maxAgeDays` run before billing — dropped videos are never charged.
- Pay-per-event billing — see the Pricing tab on the actor page.

***

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by YouTube or Google LLC or any of their subsidiaries. All trademarks mentioned are the property of their respective owners.

The scraper accesses only publicly available YouTube search pages — no authenticated endpoints, paid features, or content behind a login. Users are responsible for ensuring their use complies with YouTube's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organization.

***

### SEO Keywords

youtube search scraper, youtube scraper, scrape youtube search results, youtube video metrics, youtube keyword tracker, youtube analytics data, youtube view count scraper, youtube trends data, youtube API alternative, youtube data extraction, video research tool, content research scraper, competitor youtube analysis, youtube monitoring tool, youtube search API, Apify youtube, video marketing data, youtube channel data, keyword research youtube, fresh video alerts

# Actor input Schema

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

List of URLs to start scraping from, it can be in form of a link or search term or query from youtube.

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

Maximum number of items to scrape. Default 100.

## `metricsMode` (type: `boolean`):

Output ONE flat, analytics-ready row per video — <code>title</code>, <code>channelName</code>, <code>views</code> (parsed number), <code>durationSeconds</code>, <code>publishedAgeDays</code>, <code>isLive</code>, <code>query</code>, <code>checkedAt</code> — instead of YouTube's raw renderer object. Also skips non-video junk (shelves, ads, channel cards) so you only pay for actual videos. Ideal for dashboards, spreadsheets, and scheduled keyword monitoring.

## `titleMustInclude` (type: `array`):

Keep only videos whose title contains at least ONE of these terms (case-insensitive). Filtered videos are never charged.

## `titleExclude` (type: `array`):

Drop videos whose title contains ANY of these terms (case-insensitive). Applied after 'Title must include'. Free.

## `maxAgeDays` (type: `integer`):

Drop videos older than this many days (based on YouTube's relative publish time). <code>0</code> = no age limit. Combine with a scheduled run for fresh-content monitoring. Free — dropped videos are never charged.

## `maxConcurrency` (type: `integer`):

Maximum number of pages that can be processed at the same time. Default 10.

## `minConcurrency` (type: `integer`):

Minimum number of pages that will be processed at the same time. Default 1.

## `maxRequestRetries` (type: `integer`):

Number of times the crawler will retry a failed request before giving up. Default 10.

## `proxy` (type: `object`):

Specifies proxy servers that will be used by the scraper in order to hide its origin.<br><br>For details, see <a href='https://apify.com/apify/web-scraper#proxy-configuration' target='_blank' rel='noopener'>Proxy configuration</a> in README.

## Actor input object example

```json
{
  "startUrls": [
    "music"
  ],
  "maxItems": 100,
  "metricsMode": false,
  "titleMustInclude": [],
  "titleExclude": [],
  "maxAgeDays": 0,
  "maxConcurrency": 10,
  "minConcurrency": 1,
  "maxRequestRetries": 10,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# 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 = {
    "startUrls": [
        "music"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/youtube-search-results-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 = {
    "startUrls": ["music"],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/youtube-search-results-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    "music"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call memo23/youtube-search-results-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=memo23/youtube-search-results-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/9ezF2UTn4xgBvKUfG/builds/Ir0V26bgPCWLeHl6m/openapi.json
