# YouTube Search Scraper: Videos, Views, Likes, Descriptions (`datagleaner/youtube-search-scraper`) Actor

YouTube search scraper and video details extractor: keyword search with date, length and sort filters, plus views, likes, comment count, description and channel for any video URL. $0.30 per 1,000 results. No login, no API key.

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

## Pricing

from $0.21 / 1,000 search 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: Videos, Views, Likes, Descriptions

A YouTube search scraper and video details extractor in one Actor. Search YouTube by keyword with date, length, sort and type filters, and get each result's **video details**: title, channel, **views, likes**, comment count, **description**, publish date and length. Or give it video URLs or IDs and get the same details for each. Plain HTTP, no browser, no login, no cookies from any account and no YouTube API key or quota.

It costs **$0.0003 per search result** and **$0.0008 per video with details** ($0.30 per 1,000 results, $0.80 per 1,000 detailed videos), with no start fee and no separate platform charge. Videos that are unavailable are never billed.

### What does YouTube Search Scraper do?

It returns what a visitor sees on YouTube, as rows in an Apify dataset you can download as JSON, CSV or Excel or read through the API. Typical uses:

- **Keyword and topic research:** search a keyword and see which videos rank, with views, age, length and channel. Add `uploadDate: "month"` to see what is working now.
- **Competitor and channel monitoring:** search a brand or product name every day on a schedule and send new videos to Slack, a sheet or a CRM.
- **Trending topic lists:** `uploadDate: "today"` with `sortBy: "viewCount"` gives a daily list of the most-watched new videos on a topic.
- **Influencer discovery:** `resultType: "channel"` returns channels for a keyword with handle and subscriber count. Pass the channel URLs to YouTube Channel Email & Influencer Contacts Finder to get public emails.
- **Video metadata for a list of links:** put URLs or IDs in `videoUrls` and get views, likes, comment count, description with full links, hashtags, exact publish date and channel subscribers.
- **Live stream discovery:** `resultType: "live"` lists streams that are on now with viewers watching.
- **AI agents and datasets:** feed fresh YouTube search results into an agent, a RAG pipeline or an analysis notebook.

If you used the YouTube Data API for search, this Actor needs no API key, project or quota, and a search costs a fraction of a cent.

### Input

| Field | Meaning |
|---|---|
| `searchQueries` | **Search mode.** Keywords as typed in the YouTube search box. Up to `maxResults` results per keyword in YouTube's order for the chosen sort and filters. |
| `videoUrls` / `videoIds` | **Details mode.** Watch, `youtu.be`, Shorts or live URLs, or 11-character video IDs. One details row per video. Private, removed or unavailable videos are skipped and not charged. |
| `maxResults` | Results per keyword, default 50, up to 500. YouTube ends very long result lists at roughly 500 to 600 results. |
| `includeDetails` | Default off. Adds likes, comment count, full description, exact publish date, hashtags and channel subscribers to every search result, for one extra request each. A row with details is charged the details price instead of the search price, never both. |
| `sortBy` | `relevance` (default), `uploadDate` or `viewCount`. YouTube applies its sort loosely to the top of the results, so pair `uploadDate` with the Upload date filter when you need recent videos. |
| `uploadDate` | `any` (default), `hour`, `today`, `week`, `month` or `year`. |
| `duration` | `any` (default), `short` (under 3 minutes), `medium` (3 to 20 minutes) or `long` (over 20 minutes). |
| `resultType` | `video` (default), `channel`, `playlist` or `live` (streams on now). |
| `country`, `language` | Localize the results (`US`, `GB`, `DE`, `JP`...; `en`, `de`, `pt-BR`...). Use `en` if you want `publishedAt` estimated from the age text. Video details are always read in English. |
| `maxConcurrency`, `requestDelaySecs` | Politeness controls. Default 4 requests at once, at least 0.25 s between request starts. |
| `proxyConfiguration` | Optional, off by default. |

With no input at all, the Actor runs a built-in example (3 search results and 1 video's details) and says so in the run's status message. If you already call another YouTube Actor, these input names are also accepted: `startUrls`, `searchTerms`, `queries`, `keywords`, `maxItems`, `maxVideos`, `countryCode`, `languageCode`.

Search with filters and details:

```json
{
  "searchQueries": ["web scraping tutorial", "python data analysis"],
  "maxResults": 50,
  "uploadDate": "month",
  "duration": "medium",
  "includeDetails": true
}
```

Details for a list of videos:

```json
{
  "videoUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "https://youtu.be/QObMUbtzEqw"],
  "videoIds": ["_uQrJ0TkZlc"]
}
```

Channels for a keyword:

```json
{
  "searchQueries": ["home workout"],
  "resultType": "channel",
  "maxResults": 40
}
```

### Output

A search row with `includeDetails` on:

```json
{
  "type": "video",
  "videoId": "_uQrJ0TkZlc",
  "url": "https://www.youtube.com/watch?v=_uQrJ0TkZlc",
  "title": "Python Full Course for Beginners",
  "channelName": "Programming with Mosh",
  "channelId": "UCWv7vMbMWH4-V0ZXdmDpPBA",
  "channelUrl": "https://www.youtube.com/@programmingwithmosh",
  "channelHandle": "@programmingwithmosh",
  "channelVerified": true,
  "channelSubscribers": 5170000,
  "viewCount": 49389646,
  "viewCountText": "49,389,646 views",
  "likeCount": 1273634,
  "commentCount": 62000,
  "publishedText": "7y ago",
  "publishedAt": "2019-02-18",
  "publishedApprox": false,
  "durationSeconds": 22447,
  "durationText": "6:14:07",
  "thumbnailUrl": "https://i.ytimg.com/vi/_uQrJ0TkZlc/hqdefault.jpg",
  "descriptionSnippet": "Learn Python for AI, machine learning, and web development with this beginner-friendly course! Get 6 months of PyCharm ...",
  "description": "Learn Python for AI, machine learning, and web development with this beginner-friendly course! ...",
  "hashtags": ["#Python", "#AI", "#MachineLearning"],
  "isLive": false,
  "isShort": false,
  "badges": ["CC"],
  "rank": 1,
  "query": "python tutorial",
  "inputType": "search",
  "filters": null,
  "scrapedAt": "2026-10-21T08:00:00Z"
}
```

Field notes:

- `viewCount` is exact for every video. For a live stream it is the viewers watching now.
- `likeCount` is exact when YouTube shows the full number. `commentCount` and `channelSubscribers` are YouTube's public numbers, rounded for large values (2.4M comments is 2400000).
- `publishedAt` is exact (a date) in details rows. In search rows without details it is estimated from the age text ("7y ago") and `publishedApprox` is `true`.
- `durationSeconds` comes from search results. Videos read only by URL or ID have no length, because YouTube's public watch data does not include it.
- Channel rows carry `channelName`, `channelHandle`, `channelSubscribers` and `descriptionSnippet`. Playlist rows carry `playlistId`, `title`, `channelName` and `videoCount`.
- Every row has `scrapedAt` and the keyword (`query`) or the URL or ID (`inputUrl`) it came from.

### How much does it cost?

| Row | Price |
|---|---|
| Search result (video, channel, playlist or live) | **$0.0003** |
| Video with details (search result with `includeDetails`, or a URL or ID) | **$0.0008** |

Worked examples:

- 1 keyword, 100 results: 100 x $0.0003 = **$0.03**.
- 20 keywords, 50 results each: 1,000 x $0.0003 = **$0.30**.
- 20 keywords, 50 results each, with details: 1,000 x $0.0008 = **$0.80**.
- 1,000 video URLs: 1,000 x $0.0008 = **$0.80**. A video that is unavailable is not charged.
- A daily monitor of 5 brand names, 20 newest results each: 100 rows a day, about **$3 a month** without details.

Set **Max charge per run** in the run options and the Actor stops at that limit and keeps what it has.

### Limits

- YouTube ends very long result lists at roughly 500 to 600 results per keyword, so `maxResults` is capped at 500. Use several related keywords for wider coverage.
- Search results are YouTube's own for the chosen filters. They can differ a little between countries and over time. Results shelves (Shorts shelves, ads, suggested topics) are not returned.
- `duration`, `uploadDate` and `sortBy` apply to video and live searches. YouTube ignores the date and length filters for channel and playlist results.
- No captions, subtitles or video downloads: this Actor reads titles, counts and descriptions only. For transcripts use YouTube Transcript Scraper.
- Pace and volume: the Actor keeps to 4 requests at once with a short pause between requests and backs off when YouTube answers 429. Very heavy runs from one IP can still be rate limited. Lower `maxConcurrency`, raise `requestDelaySecs` or turn on a proxy.
- Videos that are private, removed, age-restricted or region-locked return no details row and are not charged.

### Use with Python

```python
## pip install apify-client
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("datagleaner/youtube-search-scraper").call(run_input={
    "searchQueries": ["web scraping tutorial"],
    "maxResults": 20,          # at most 20 x $0.0003 = $0.006
    "uploadDate": "month",
})
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item["rank"], item["title"], item["viewCount"], item["channelName"])
```

### Use with JavaScript / Node.js

```js
// npm install apify-client
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('datagleaner/youtube-search-scraper').call({
    videoUrls: ['https://www.youtube.com/watch?v=dQw4w9WgXcQ'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) {
    console.log(item.title, item.viewCount, item.likeCount, item.commentCount);
}
```

### Use it from n8n, Make, Zapier or an AI agent

Actor ID: `datagleaner/youtube-search-scraper`

Minimal input:

```
{
  "searchQueries": ["web scraping tutorial"],
  "maxResults": 20
}
```

Each tool below runs this Actor with your own Apify API token.

- **n8n:** add the **Apify** node (`@apify/n8n-nodes-apify`). On n8n Cloud you install it from the community node registry. Choose **Run an Actor and get dataset**, set Actor to `datagleaner/youtube-search-scraper` and paste the input above. Add a second step with YouTube Channel Email & Influencer Contacts Finder to turn the `channelUrl` values into public emails.
- **Make:** use the Apify app's **Run an Actor** module, then **Get Dataset Items** to read the results. **Watch Actor Runs** can trigger a scenario when a run finishes.
- **Zapier:** use the Apify action **Run Actor**, then the search **Fetch dataset items**. The trigger **Finished Actor run** starts a Zap when a run ends.
- **AI agents (MCP):** connect to `https://mcp.apify.com?tools=datagleaner/youtube-search-scraper`. In Claude Code:

  ```
    claude mcp add --transport http apify "https://mcp.apify.com?tools=datagleaner/youtube-search-scraper"
  ```

  Then run `/mcp` to sign in to Apify in your browser. Then ask in plain words, for example: "Search YouTube for 'standing desk review' uploaded this month, take the 30 most viewed videos and give me a table with title, channel, views, likes and publish date."
- **LangChain (Python):**

```python
## pip install langchain-apify, then set APIFY_TOKEN in your environment
import json
from langchain_apify import ApifyActorsTool
tool = ApifyActorsTool("datagleaner/youtube-search-scraper")
result = tool.invoke({"run_input": json.loads('{"searchQueries": ["web scraping tutorial"], "maxResults": 10}')})
```

### FAQ

**How do I scrape YouTube search results?** Put your keywords in `searchQueries` and set `maxResults`. Each result becomes a row with title, channel, views, age and length. Turn on `includeDetails` to add likes, comment count and the full description.

**How do I get the views, likes and description of a list of videos?** Paste the URLs or IDs into `videoUrls` or `videoIds`. Each video returns one row with exact views, likes, comment count, description with full links, hashtags, publish date and channel subscribers.

**Do I need a YouTube API key or a Google login?** No. The Actor reads the same public pages and data a logged-out visitor's browser loads, so there is no quota, key or account.

**Can I filter by upload date, length or sort by views?** Yes: `uploadDate` (hour, today, week, month, year), `duration` (short, medium, long) and `sortBy` (relevance, uploadDate, viewCount).

**Can it search for channels, playlists or live streams?** Yes, with `resultType` set to `channel`, `playlist` or `live`.

**How many results can I get for one keyword?** Up to 500. YouTube stops a result list at roughly 500 to 600 results, so use several related keywords for more.

**Is the publish date exact?** In details rows, yes: it is the date shown on the video page. In search rows without details it is estimated from the age text and flagged with `publishedApprox`.

**Does it download videos or captions?** No. It returns metadata only. For transcripts see YouTube Transcript Scraper.

**What happens if I enter an empty input?** It runs a small built-in example (3 search results and 1 video's details) and tells you in the status message.

### Related Actors

- [YouTube Channel Email & Influencer Contacts Finder](https://apify.com/datagleaner/youtube-channel-contacts): public emails, websites and socials for the channels you find. Run it on the `channelUrl` values from this Actor.
- [YouTube Shorts & Channel Scraper](https://apify.com/datagleaner/youtube-channel-scraper): go from a channel you found here to its full video, Shorts and live list with views, plus subscribers, country and join date.
- [YouTube Comments Scraper](https://apify.com/datagleaner/youtube-comments-scraper): the comments and replies of the videos you find here, top or newest, with authors, likes and an optional keyword filter. Give it this run's dataset ID or the `videoId` values.
- [YouTube Transcript Scraper](https://apify.com/datagleaner/youtube-transcript-scraper): captions and transcripts as text or SRT for the videos you find here.
- [Website Contact Details Scraper](https://apify.com/datagleaner/website-contact-details-scraper): emails, phones and social profiles from a channel's own website.

### Responsible use

This Actor reads public pages only and collects no personal data beyond what YouTube shows publicly, such as channel names and handles. You are responsible for lawful use of the data, including YouTube's terms of service, copyright and any privacy rules that apply to how you use it. Keep volumes reasonable so you do not burden the site.

# Actor input Schema

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

Search mode: keywords as you would type them in the YouTube search box, e.g. `web scraping tutorial`. Each returns up to `Max results per keyword` results in YouTube's own order for the chosen sort and filters.

## `videoUrls` (type: `array`):

Details mode: video links (`https://www.youtube.com/watch?v=...`, `youtu.be`, Shorts or live URLs) or 11-character video IDs. Each returns one row with title, views, likes, comment count, description, publish date, channel and subscribers. Videos that are private, removed or unavailable are skipped and not charged.

## `videoIds` (type: `array`):

Same as video URLs, for plain 11-character video IDs such as `dQw4w9WgXcQ`. You can use either field or both.

## `maxResults` (type: `integer`):

Stops after this many results for each keyword. YouTube ends a very long result list at roughly 500 to 600 results, so 500 is the cap.

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

Reads each video's watch data for one extra request and adds likes, comment count, full description, exact publish date, hashtags and channel subscribers. Details rows use the details price instead of the search price (one price per row, never both). Off by default.

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

Passes YouTube's own sort option. YouTube applies it loosely to the top of the results, so combine `uploadDate` with the Upload date filter below when you need recent videos.

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

Only videos uploaded in this period. Applies to video and live searches.

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

Only videos of this length. Applies to video searches.

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

What to search for. `video` returns videos, `channel` returns channel cards (name, handle, subscribers), `playlist` returns playlists and courses, `live` returns streams that are on now.

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

Two-letter country code that localizes the results, e.g. `US`, `GB`, `DE`, `JP`, `BR`.

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

Interface language of the search page, e.g. `en`, `de`, `pt-BR`. Use `en` if you parse the text fields (`viewCountText`, `publishedText`): view counts are numbers in any language, but the age text is only turned into a date in English. Video details are always read in English.

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

How many requests run at once. Lower it if you see rate limiting.

## `requestDelaySecs` (type: `number`):

Minimum gap between request starts across the whole run. Polite pacing: higher is slower and safer.

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

Optional. Off by default: YouTube answered Apify datacenter IPs in testing. Turn a proxy on if runs start getting refused at high volume; the Actor then switches to a fresh IP after repeated refusals.

## Actor input object example

```json
{
  "searchQueries": [
    "web scraping tutorial"
  ],
  "maxResults": 10,
  "includeDetails": false,
  "sortBy": "relevance",
  "uploadDate": "any",
  "duration": "any",
  "resultType": "video",
  "country": "US",
  "language": "en",
  "maxConcurrency": 4,
  "requestDelaySecs": 0.25
}
```

# Actor output Schema

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

No description

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

No description

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

No description

## `results` (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": [
        "web scraping tutorial"
    ],
    "maxResults": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("datagleaner/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": ["web scraping tutorial"],
    "maxResults": 10,
}

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

```

## MCP server setup

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