# YouTube Data Scraper - Videos & Channels (`enezli/youtube-scraper`) Actor

Scrape YouTube videos and channels: titles, views, likes, subscriber counts, and upload dates. Alternative to YouTube Data API with no limits or quotas — extract data easily and reliably.

- **URL**: https://apify.com/enezli/youtube-scraper.md
- **Developed by:** [Turgay NANTA](https://apify.com/enezli) (community)
- **Categories:** Agents, MCP servers, Videos
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 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/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

## YouTube Video Scraper — No API Key, No Quota Limits

Search YouTube by keyword and get clean, de-duplicated video JSON — title, channel, views, duration, upload date. No API key, no quota. Free to start, MCP ready.

Runs with **one click — no required fields**. Type a query (or use the default), get clean, de-duplicated JSON. Built for both humans and AI agents (MCP-ready).

### What it does

The official YouTube Data API v3 charges quota per call and caps you at 10,000 units/day — enough for a handful of searches before you're locked out. This actor reads YouTube's own public search results page (the same data your browser renders, no login) and returns every video as clean, normalized JSON: no API key to request, no quota to run out of, no Google Cloud project to set up. You give it a search query, it gives you the matching videos — de-duplicated and ready for your dashboard, spreadsheet, or AI agent.

### Quick start (no code)

1. Click **Start** with the default query, or type your own in `query`.
2. Wait a few seconds — the actor searches and returns results as a dataset.
3. Export the dataset as JSON, CSV, or Excel directly from the Apify Console, or pull it via API.

### Input

| Field | Required | Description |
|---|---|---|
| `query` | no | What to search on YouTube (default: `greenhouse jobs api`) |
| `maxResults` | no | Max clean results (default 20, cap 500) |
| `enrich` | no | Deterministic enrichment per record (domain extraction, completeness score) |
| `monitor` | no | Compare with the previous run, flag NEW videos only — ideal for scheduled runs tracking a topic over time |

### Output (dataset, per record)

Real example — query `"greenhouse jobs api"` (captured live 2026-08-11, unedited):

```json
{
  "id": "TvZvYx2fGHw",
  "title": "Building on Your ATS: Greenhouse API + Make Demo",
  "url": "https://www.youtube.com/watch?v=TvZvYx2fGHw",
  "channel": "PromptMates",
  "channel_url": "https://www.youtube.com/@PromptMates",
  "views_text": "710 views",
  "duration": "14:54",
  "published_text": "5 months ago",
  "description": "All our resources (community, live sessions, newsletter)...",
  "thumbnail": "https://i.ytimg.com/vi/TvZvYx2fGHw/hq720.jpg",
  "domain": "www.youtube.com",
  "completeness": 0.33
}
```

The final dataset row `_summary` carries run totals (`total_clean`, `deduped`, `enriched`). In monitor mode, a `_changes` row lists the video IDs that are new since the last run.

### Use cases

- **Content research** — see what's already ranking for a topic before you script your own video.
- **Competitor tracking** — monitor a niche's search results weekly (`monitor: true`) to catch new uploads the moment they appear.
- **Market/trend signals** — video titles and upload cadence for a keyword are a cheap, fast proxy for what's heating up.
- **Lead-gen adjacent** — find channels actively publishing about a product/integration (e.g. companies with tutorial videos about a competitor's API).

### Enrichment (optional, charged only when it produces something)

With `enrich: true`, each record gets a `domain` field (canonical host extracted from the video URL) and a `completeness` score (0–1). No LLM is used anywhere in this actor — enrichment is deterministic, so output is stable run to run and costs are fully predictable in advance.

### Monitor mode — change alerts on a schedule

Set `monitor: true` and schedule the actor (daily/weekly via Apify's built-in Scheduler). Each run compares the current result set against the previous one and adds a `_changes` row listing only the video IDs that weren't there before — so you can wire an alert (email, Slack, Telegram) off new uploads for a topic without re-processing the whole result set yourself.

### Use it from your code

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("enezli/youtube-scraper").call(run_input={
    "query": "greenhouse jobs api",
    "maxResults": 50,
    "enrich": True,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

```bash
curl "https://api.apify.com/v2/acts/enezli~youtube-scraper/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"query": "greenhouse jobs api", "maxResults": 20}'
```

### Use it with AI agents (MCP)

This actor is listed under the `MCP_SERVERS` category and works out of the box as an Apify MCP tool — an agent can call it directly with a `query` and get structured JSON back, no scraping code for the agent to write or maintain.

### Pricing — Pay-Per-Event, start is free

You only pay for what you get — no subscription, no charge for a run that finds nothing useful:
| Event | When charged |
|---|---|
| `actor-start` | $0.0001 — symbolic, effectively free |
| `result` | $0.002 per clean video record returned |
| `enrichment` | $0.01 — only for a record that actually got enriched |
| `change-alert` | $0.005 — monitor mode only, per NEW video since the previous run |

Volume discounts apply automatically via Apify account tiers (up to −44% on GOLD).

### Is this legal?

This actor collects **publicly available data only** — the same search results any visitor sees in a browser, without logging in. It does not bypass authentication, does not access private videos, and does not store personal credentials. You are responsible for using the output in compliance with YouTube's Terms of Service and applicable law (e.g. GDPR) in your jurisdiction.

### Support & feedback

Found a bug, or need a field this actor doesn't return yet (e.g. like/subscriber counts — see Limitations below)? **Open an issue** on the actor's Issues tab. Feature requests are welcome; frequently-requested fields get added to the standard output in a future version.

### Changelog

- **0.1 (2026-08-11)** — Initial release: keyword search, clean/de-duplicated JSON, optional deterministic enrichment, monitor mode.

### Limitations (honest ones)

- **No like or subscriber counts in this version.** Those live on the individual video/channel page, not the search-results page this actor reads — adding them means an extra request per video, planned for a future version, not silently promised here.
- YouTube's search page markup can change without notice; if a run suddenly returns 0 results, please open an issue so the parser can be updated.
- This is search-result data, not the full YouTube Data API surface (no comments, no captions in this version).

### FAQ

**Does this need a YouTube API key?** No — it reads the public search page directly, no Google Cloud project or API key required.
**Will I get rate-limited?** The actor makes one request per run for up to ~20 results; for larger `maxResults` it's still a small, polite number of requests. No login means no per-account YouTube quota applies.
**Can I search by channel instead of keyword?** Not in this version — this actor is keyword-search only. A dedicated channel-scraper variant is planned.
**Why is `completeness` sometimes low?** The scoring field was designed for e-commerce/business data (price, location, rating); most of those don't apply to video content, so a "low" score here is expected and not a data-quality problem — check the YouTube-specific fields (`channel`, `views_text`, `duration`) instead.

# Actor input Schema

## `query` (type: `string`):

What to search for on Youtube. Leave empty to use the default example query — the actor runs with one click, no required fields.

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

Maximum number of clean results to return (capped at 500).

## `enrich` (type: `boolean`):

Adds deterministic enrichment per record: extracted emails, canonical domain and a completeness score. Charged per enriched record (see Pricing).

## `monitor` (type: `boolean`):

Compares this run with the previous one and flags NEW records only. Ideal for scheduled runs — get alerted when something changes. Charged per change.

## Actor input object example

```json
{
  "query": "greenhouse jobs api",
  "maxResults": 20,
  "enrich": false,
  "monitor": false
}
```

# Actor output Schema

## `results` (type: `string`):

Clean, normalized and de-duplicated records scraped from YouTube, as JSON. Each item follows the dataset schema (see storages.dataset.fields in actor.json).

# 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 = {
    "query": "greenhouse jobs api"
};

// Run the Actor and wait for it to finish
const run = await client.actor("enezli/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 = { "query": "greenhouse jobs api" }

# Run the Actor and wait for it to finish
run = client.actor("enezli/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 '{
  "query": "greenhouse jobs api"
}' |
apify call enezli/youtube-scraper --silent --output-dataset

```

## MCP server setup

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