# YouTube Scraper - Search, Channels and Shorts (`sumitr_mardy/youtube-scraper`) Actor

Export public YouTube search results, channel videos, Shorts and video URLs in one flat schema. Add exact displayed dates, likes, descriptions and comment counts at no extra charge. Download JSON or CSV. No API key, login or video downloads.

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

## Pricing

from $0.40 / 1,000 videos

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 Scraper — Search, Channels and Shorts

Export public YouTube video listings from keyword search, channel Videos/Shorts/Live tabs, or individual video URLs. One flat, never-null schema; optional video details are included at the same per-video price. No YouTube API key, login, cookies or video downloads.

For comment text and linked replies, use [YouTube Comments Scraper](https://apify.com/sumitr_mardy/youtube-comments-scraper). This Actor returns video rows, not comment rows.

### Quick start

```json
{"searchQueries":["lofi hip hop"],"maxResults":10}
```

Channel uploads:

```json
{"startUrls":["@MrBeast"],"channelTab":"videos","maxResults":50}
```

Shorts:

```json
{"startUrls":["https://www.youtube.com/@MrBeast"],"channelTab":"shorts","maxResults":50}
```

Exact displayed date and additional metadata:

```json
{"startUrls":["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],"includeDetails":true}
```

Search date filter:

```json
{"searchQueries":["iphone 17 review"],"uploadDate":"week","maxResults":40}
```

### Input

| Field | Default | Meaning |
|---|---|---|
| searchQueries | \[] | Keyword strings, one result limit per query. |
| startUrls | \[] | Video ID, watch/Shorts/youtu.be URL, channel @handle or /channel/UC… /c/… /user/… URL, or /results?search_query= URL. |
| maxResults | 50 | Unique videos per query/channel, 1–5,000. Direct video input returns one row. Default prefill is 10 results. |
| channelTab | videos | videos, shorts or streams. A missing channel tab returns no_results. |
| uploadDate | any | Search only: any, today, week, month or year. Read from the current public filter menu. |
| sortBy | relevance | Only relevance is supported. YouTube's measured menu does not expose Sort by upload date. |
| includeDetails | false | Add exact displayed calendar date, likes, full public description and comment count. No extra charge per result. |
| language | en | Listing UI language. Channel metadata, filter discovery and exact-date enrichment use English for reliable parsing. |
| country | US | Two-letter country code sent as gl. |

At most 100 combined inputs. Duplicate normalized inputs and repeated videos within each input are removed. The same video found under different queries may appear once per query. Unsupported inputs yield free failed rows. Past hour and sortBy=date are explicitly rejected; they are not silently approximated. Search skips Shorts shelves; use a channel's Shorts tab for Shorts.

### Output

Each result has all 32 keys, without null. Missing strings are "", counts are 0, badges are \[].

| Field | Meaning |
|---|---|
| inputIndex, input | Original combined input index and supplied query/URL. Queries precede URLs. |
| source, query | search, channel or video; keyword when applicable. |
| videoId, url, title, type | Canonical ID/link/title; video, short or live. |
| channelName, channelId, channelUrl, channelHandle | Available public channel identity. Handle excludes @. |
| subscribersText, subscribers | Displayed subscriber label and numeric interpretation; often absent in search. |
| viewCountText, viewCount | Raw displayed views or live viewer label and numeric interpretation. |
| publishedTimeText, publishedAt | Raw relative date; exact displayed date YYYY-MM-DD only with details and when available. |
| durationText, durationSeconds | Displayed duration and parsed seconds; 0 when unavailable or live. |
| isLive | Whether the public response identifies a current live stream. Past streams are videos. |
| likeCount, commentCount, description | Detail enrichment; 0/0/"" without details or when unavailable. |
| thumbnail, badges | Public thumbnail URL and badge labels. |
| position, detailsIncluded | One-based returned position for this input; whether detail enrichment ran. |
| status, subStatus, error, scrapedAt | Stable outcome, machine-readable reason, explanation and ISO scrape timestamp. |

The details path reads the public video next response and, when needed, the first public comment page for its count. It does not collect comment text into results. Individual video URLs also require next to identify the video even when includeDetails is false. That endpoint does not expose a reliable duration, so direct video duration may be empty/0. Channel tab data does not always expose a handle or a publish date, especially for Shorts.

| status | subStatus | Charged video event |
|---|---|---|
| ok | video | Yes |
| no_results | no_results | No |
| failed | invalid_input, not_found, http_CODE, blocked, parse_error, network_error, free_work_limit, cost_limit_reached | No |

A partial input can return saved videos and a final free failure/limit row. Failed detail enrichment produces free failure rows instead of charging an incomplete enriched result.

### Pricing

One video event per saved successful video, including optional details. No per-query, date-filter or Shorts surcharge.

| Apify tier | Per video | Per 1,000 |
|---|---|---|
| FREE | $0.001 | $1.00 |
| BRONZE | $0.0008 | $0.80 |
| SILVER | $0.0006 | $0.60 |
| GOLD+ | $0.0004 | $0.40 |

Default Actor start fee: $0.00005 per start event (per GB, minimum one). Failed and empty rows have no video charge; the start fee still applies. Dataset-item billing is disabled. The Actor pays platform usage under PPE. Your configured spending limit may stop results early.

### API examples

Replace APIFY_TOKEN with your own token; do not paste it into input.

```bash
curl -X POST "https://api.apify.com/v2/acts/sumitr_mardy~youtube-scraper/run-sync-get-dataset-items?format=json" \
  -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{"searchQueries":["lofi hip hop"],"maxResults":10}'
```

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("sumitr_mardy/youtube-scraper").call(
    run_input={"startUrls": ["@MrBeast"], "channelTab": "shorts", "maxResults": 50}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row["videoId"], row["title"], row["viewCount"])
```

For larger jobs use asynchronous runs, then download the dataset as JSON, CSV or Excel.

### Use it from AI agents (MCP)

Hosted OAuth:

```json
{"mcpServers":{"youtube":{"url":"https://mcp.apify.com/?tools=sumitr_mardy/youtube-scraper"}}}
```

Hosted Bearer alternative:

```json
{"mcpServers":{"youtube":{"url":"https://mcp.apify.com/?tools=sumitr_mardy/youtube-scraper","headers":{"Authorization":"Bearer YOUR_APIFY_TOKEN"}}}}
```

Stdio:

```json
{"mcpServers":{"youtube":{"command":"npx","args":["-y","@apify/actors-mcp-server","--tools","sumitr_mardy/youtube-scraper"],"env":{"APIFY_TOKEN":"YOUR_APIFY_TOKEN"}}}}
```

Ask your agent to search a keyword, list channel uploads or export Shorts; set maxResults explicitly. Enable details only when you need dates, likes or descriptions. Always inspect status/subStatus before using counts.

### Limits and data accuracy

Public data only. Not affiliated with YouTube or Google. No player endpoint, video/audio downloads, transcripts, private videos or login. Public availability and JSON structures can change. Country and public moderation can change visible results; the Actor does not bypass availability restrictions.

Without details dates remain relative. Displayed views, subscribers and likes can be rounded; numeric values interpret that display and are not hidden exact statistics. Details can expose exact displayed views/likes and calendar dates, but a field YouTube does not expose remains empty/0. Comment counts are YouTube's displayed header count and may include unavailable comments. Shorts listing dates/durations can be absent. Details do not guarantee every field on every video.

Current date filters: Today, This week, This month and This year. Sort by upload date and Past hour were absent in both local and Apify responses on 2026-10-30; they are not supported. Result inventory can run out before maxResults. The run has bounded deadlines, a free-work loss guard, two parallel inputs and at most three simultaneous detail calls. Blocking is retried once directly, then once through Apify's default datacenter pool; no residential proxy or cookies.

# Actor input Schema

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

Keywords to search; result limit applies separately.

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

Public video IDs, video/Shorts/channel/search URLs or @handles.

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

Maximum unique results per query or channel.

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

Channel tab to list; missing tabs return no_results.

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

Search only. Discovered from the live filter menu; past hour is unavailable.

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

Relevance only; current public menu has no Sort by upload date.

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

Add exact displayed date, likes, description and comment count, with no surcharge. Extra JSON requests take longer.

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

Listing UI language. Channel metadata, filter discovery and exact-date enrichment use English for reliable parsing.

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

Two-letter country code sent as gl.

## Actor input object example

```json
{
  "searchQueries": [
    "lofi hip hop"
  ],
  "maxResults": 10,
  "channelTab": "videos",
  "uploadDate": "any",
  "sortBy": "relevance",
  "includeDetails": false,
  "language": "en",
  "country": "US"
}
```

# Actor output Schema

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

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

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

```

## MCP server setup

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