# YouTube Scraper - Exact Views & Likes (`trakk/youtube-scraper`) Actor

Scrape YouTube videos, Shorts, streams, channels, playlists, search results and comments in one Actor. Returns exact view and like counts read from each video, not the rounded labels other scrapers ship, plus category, tags, subtitle languages and engagement metrics. No API key or quota.

- **URL**: https://apify.com/trakk/youtube-scraper.md
- **Developed by:** [Kelopr\_bk](https://apify.com/trakk) (community)
- **Categories:** Videos, Social media, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.80 / 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?

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 Scraper — exact counts, not rounded labels

Scrape YouTube **videos, Shorts, live streams, channels, playlists, search results and comments** — and get the *real* numbers.

Most YouTube scrapers hand you what's printed on the thumbnail grid: `18M views`, `2 days ago`, likes rounded to `306,000`. This one opens each video and reads the actual figures:

| | Typical scraper | 🎯 This Actor |
|---|---|---|
| Views | `18,000,000` | **`18,592,498`** |
| Likes | `306,000` | **`306,738`** |
| Published | `"2 days ago"` | **`2026-09-10T07:29:55Z`** |
| Length | `17:14` *(off by a second)* | **`00:17:14`** · `1034` seconds |
| Category | — | **`Science & Technology`** |
| Tags | — | **`["iPhone Duo", "iPhone 18 Pro"]`** |

On a single MKBHD video, the rounded figure is **344,000 views wrong**. If your numbers end up in a report, a chart or a database, that gap matters.

**Every row tells you how precise it is**, in a `dataPrecision` field. Nothing is guessed, nothing is silently rounded.

***

### ⚡ Quick start

1. Click **Try for free**.
2. Type a search term, or paste a YouTube URL — a channel, a video, a playlist, a Shorts link, even a YouTube search page URL.
3. Set **Maximum videos per source**.
4. Hit **Start** ▶️

That's it. Results appear live in the **Output** tab and export to CSV, Excel, JSON or XML in one click.

**Simplest possible input:**

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

**A whole channel, videos and Shorts together:**

```json
{
  "startUrls": [{ "url": "https://www.youtube.com/@mkbhd" }],
  "maxResults": 200,
  "maxResultsShorts": 50
}
```

**This month's long HD videos in a niche, best first:**

```json
{
  "searchQueries": ["home studio setup"],
  "maxResults": 100,
  "sortingOrder": "views",
  "dateFilter": "month",
  "lengthFilter": "over20",
  "isHD": true
}
```

***

### 📥 What you can feed it

| You give it | You get back |
|---|---|
| 🔍 A search term | Matching videos, with every filter YouTube offers |
| 📺 A channel URL or `@handle` | Its videos, Shorts and past live streams |
| ▶️ A video, Shorts or `youtu.be` link | That one video, fully detailed |
| 📃 A playlist link | Every video in the playlist |
| 🔗 A YouTube search-page URL | Exactly the results that page shows |
| 💬 Any of the above + comments | Top-level comments attached to each video |

Mix them freely — search terms and URLs can go in the same run. Bare video IDs (`dQw4w9WgXcQ`) and handles (`@mkbhd`) work too.

***

### 🏆 What makes it different

**1. Exact numbers.** Views, likes, publish timestamps and durations read from each video, not from the listing shelf. Verifiable in one run.

**2. Fields nobody else ships.** 📂 `category` · 🏷️ `tags` · 🌍 `availableCountryCount` (249 countries or 12?) · 💬 `captionLanguages` and whether they're human-written · 👨‍👩‍👧 `isFamilySafe`

**3. Performance metrics, computed for you.** 📈 `engagementRate`, `likeRate`, `commentRate`, `viewsPerDay`, `daysSincePublished` — plus `viewsVsChannelMedian` and `isChannelOutlier`, which answer the question a channel dump is usually *for*: **which of these videos actually overperformed?**

**4. Sponsorship detection.** 💰 `hasSponsorSignals` and `sponsorSignals` flag videos whose description reads like a paid placement, alongside YouTube's own `isPaidContent` disclosure.

**5. One Actor, not four.** Search, channels, Shorts, streams, playlists and comments are all here. No juggling separate tools and stitching their outputs together.

**6. Honest about its limits.** When YouTube withholds something, the row says so instead of inventing a value.

***

### 📤 Example output

One row per video (trimmed):

```json
{
  "id": "Od6M0AXpcxQ",
  "url": "https://www.youtube.com/watch?v=Od6M0AXpcxQ",
  "title": "iPhone 18 Pro/Duo Impressions: Mogged",
  "type": "video",
  "dataPrecision": "exact",

  "viewCount": 18592498,
  "likes": 306738,
  "commentsCount": 21043,
  "date": "2026-09-10T07:29:55Z",
  "duration": "00:17:14",
  "durationSeconds": 1034,

  "category": "Science & Technology",
  "tags": ["iPhone Duo", "iPhone 18 Pro", "MKBHD"],
  "hashtags": ["#iPhone18"],
  "captionLanguages": ["en", "ja", "pt", "ru", "tr", "vi"],
  "hasManualCaptions": true,
  "availableCountryCount": 249,
  "isFamilySafe": true,
  "isPaidContent": false,
  "hasSponsorSignals": true,
  "sponsorSignals": ["check out"],

  "likeRate": 1.6498,
  "commentRate": 0.1129,
  "engagementRate": 1.7627,
  "viewsPerDay": 8810621,
  "daysSincePublished": 2.1,
  "channelMedianViews": 4884885,
  "viewsVsChannelMedian": 3.806,
  "isChannelOutlier": true,

  "channelName": "Marques Brownlee",
  "channelUrl": "https://www.youtube.com/@mkbhd",
  "numberOfSubscribers": 21200000,
  "channelTotalViews": 5609670895,
  "channelTotalVideos": 1849,
  "channelLocation": "United States",
  "isChannelVerified": true,
  "channelExternalLinks": ["http://twitter.com/MKBHD", "http://instagram.com/MKBHD"],
  "channelXUrl": "http://twitter.com/MKBHD",
  "channelInstagramUrl": "http://instagram.com/MKBHD",

  "text": "Full video description…",
  "descriptionLinks": [{ "url": "https://ridge.com/MKBHD", "text": "https://ridge.com/MKBHD" }]
}
```

Up to **89 fields** per video. The **Output** tab groups them into three ready-made views — 🎬 **Videos**, 📈 **Performance**, 📺 **Channel & links**.

***

### 🎯 How precise are the numbers?

Every row carries a `dataPrecision` field, so nothing has to be taken on trust:

| Value | What it means |
|---|---|
| ✅ **`exact`** | Everything: exact view and like counts, full publish timestamp, category, tags, subtitle languages, country availability. |
| 🟡 **`partial`** | **The counts are still exact** — views, likes, publish date, duration and every metric derived from them. YouTube declined to serve the classification details for this particular video, so category, tags and captions are *absent rather than guessed*. |
| ⚪ **`approximate`** | YouTube's rounded listing labels only (`18M views`, `2 days ago`). Produced by the **Fast** preset. |

On **Balanced** and **Detailed**, every row comes back `exact` or `partial` — **both with exact counts**. A typical 60-video run lands around three quarters `exact`.

#### Presets

| Preset | What it does | Use it when |
|---|---|---|
| 🚀 **Fast** | Reads the listing only. Rounded counts, relative dates. | You just want an inventory of what exists. |
| ⚖️ **Balanced** *(default)* | Opens each video for the real figures. | Almost always. |
| 🐢 **Detailed** | Same data, gentler pace. | Very large runs. |

***

### 🔎 Search filters

Every filter YouTube's own search page offers — and unlike that page, **they combine**:

- ↕️ **Sort by** — relevance · upload date · view count · rating
- 📅 **Uploaded** — last hour · today · this week · this month · this year
- ⏱️ **Length** — under 3 min · 3–20 min · over 20 min
- 📦 **Type** — videos · Shorts · channels · playlists · movies
- ⚙️ **Features** — HD · 4K · HDR · subtitles/CC · Creative Commons · live · 360° · 3D · VR180

So *"HD videos over 20 minutes, uploaded this month, sorted by views"* is one run, not four.

📆 There's also a separate **date range** (`Published after` / `Published before`) accepting `2026-01-31` or a relative form like `7 days`. It works on channels and playlists too — not just search — and on Balanced/Detailed it's applied to the **exact** publish timestamp.

***

### 💬 Comments

Switch on **Also scrape comments** and set a maximum per video. Each comment carries the author, their channel ID and avatar, whether they're verified or the channel owner, like and reply counts, and whether the creator ❤️ hearted it.

Enabling comments also upgrades `commentsCount` on the video row from YouTube's rounded label to the **exact** total.

***

### 📱 Shorts

Shorts come back as ordinary rows with `type: "shorts"` and their `/shorts/` URL. Set **Maximum shorts per channel** above zero to include them, or set **Result type** to *Shorts* to search them specifically.

Two honest notes: the Shorts shelf carries no length, so `durationSeconds` appears only when the video's own page answered; and it carries no publish label either, so a Short's date always comes from the video page.

> 📊 **Want Shorts-specific depth?** For posting cadence, audience signals, comments and creator avatars as their own datasets, use the dedicated **[YouTube Shorts Scraper — Growth & Audience Insights](https://apify.com/trakk/youtube-shorts-scraper)**.

***

### 🔗 Creator links

Every row carries the creator's own links exactly as the channel lists them — the raw list, the labels they chose, and recognised profiles broken out into their own fields:

🐦 `channelXUrl` · 📸 `channelInstagramUrl` · 🎵 `channelTiktokUrl` · 👥 `channelFacebookUrl` · 💼 `channelLinkedinUrl` · 🎮 `channelDiscordUrl` · 🟣 `channelTwitchUrl` · 💻 `channelGithubUrl` · 🧡 `channelPatreonUrl` · ✈️ `channelTelegramUrl`

…plus `channelExternalLinks` and `channelLinkTitles` for everything else, including the creator's own website. This costs nothing extra — the channel is read anyway for the subscriber and view totals — so links are on **every row in every mode**.

> 📧 **Looking for creator email addresses?** That's a different job: finding a business address, confirming the domain actually accepts mail, and scoring how reachable a creator is. It has its own Actor — **[YouTube Channel Email & Sponsor Lead Scraper](https://apify.com/trakk/youtube-channel-email-sponsor-leads)** — which does it properly. This one deliberately stays out of it and gives you the links instead.

***

### 🍳 Recipes

**📈 Find this month's breakout videos in a niche**
Search term + sort by view count + uploaded this month. Then sort the dataset by `viewsPerDay`.

**🔬 Audit a channel's whole catalogue**
Channel URL with a high **Maximum videos per source**. `viewsVsChannelMedian` and `isChannelOutlier` show which videos beat that creator's own average — the ones worth studying.

**💰 Build a sponsorship prospect list**
Search your niche, filter for `hasSponsorSignals: true` to find creators already running paid placements, then reach them through their own links. For verified business emails, pair with [YouTube Channel Email & Sponsor Lead Scraper](https://apify.com/trakk/youtube-channel-email-sponsor-leads).

**🌐 Check subtitle coverage before localising**
`captionLanguages` and `hasManualCaptions` show which videos already have human-written subtitles, and in which languages.

**🏁 Track competitors**
Several channel URLs in one run, then schedule it weekly. `viewsPerDay` and `engagementRate` make the comparison fair across videos of different ages.

**📱 Pull a channel's Shorts only**
Use the `/shorts` channel URL, set **Maximum videos per source** to 0 and **Maximum shorts per channel** to what you need.

***

### ❓ FAQ

**Why do my view counts differ slightly from YouTube?**
YouTube counts continuously — a number read a minute later will be a little higher. What's guaranteed is that the figure is the exact one YouTube reported at the moment it was read, not a rounded label.

**Do I need a YouTube account or cookies?**
No. 🔓 Everything scraped here is public.

**What does it cost?**
You pay per video returned, and it's all-in — no separate charge for the run itself, no add-ons. Set a maximum charge on the run if you want a hard ceiling.

**Can I get transcripts?**
The Actor tells you which subtitle languages exist for each video (`captionLanguages`, `captionTracks`), so you know what's available before pulling any.

**What if a video can't be opened?**
Nothing is dropped silently. The row is still returned with whatever YouTube did provide, marked `partial` or `approximate`, and the run summary reports how many rows landed in each state.

**What if I make a mistake in the input?**
You get a plain-English explanation on the run's status line — *"'https://vimeo.com/1' is not a YouTube URL"* — not a stack trace. The run stops in a few seconds without burning your budget.

**Can I schedule it?**
Yes ⏰ — use Apify's scheduler. The Actor keeps no state between runs, so every run is independent and reproducible.

**Can I call it from my own code?**
Yes. It works through the Apify API and the JavaScript/Python clients like any other Actor, and the dataset is available as JSON, CSV, Excel or XML.

***

### 🧰 More YouTube tools

| Actor | Use it for |
|---|---|
| 📧 **[YouTube Channel Email & Sponsor Lead Scraper](https://apify.com/trakk/youtube-channel-email-sponsor-leads)** | Creator business emails, deliverability checks and sponsor-readiness scoring. |
| 📊 **[YouTube Shorts Scraper — Growth & Audience Insights](https://apify.com/trakk/youtube-shorts-scraper)** | Shorts-only growth analysis, audience signals, comments and avatars. |

# Actor input Schema

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

Search YouTube for these terms. Combine with the filters below to narrow the results.

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

Video, shorts, live, channel, channel tab (/videos, /shorts, /streams), playlist or search URLs. Handles like @mkbhd and bare video IDs also work.

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

How many videos to return for each search term or channel.

## `maxResultsShorts` (type: `integer`):

Shorts are only scraped when this is above zero.

## `maxResultStreams` (type: `integer`):

Past live streams are only scraped when this is above zero.

## `preset` (type: `string`):

Balanced and Detailed open each video to read its exact view count, exact like count and full publish timestamp. Fast skips that and returns YouTube's rounded listing labels ("18M views", "2 days ago"); those rows are marked dataPrecision=approximate.

## `sortingOrder` (type: `string`):

Applies to search terms only.

## `dateFilter` (type: `string`):

YouTube's own upload-date filter, applied at the source.

## `videoType` (type: `string`):

Restrict search results to one kind of result.

## `lengthFilter` (type: `string`):

Restrict search results by video length.

## `isHD` (type: `boolean`):

Only results available in HD.

## `is4K` (type: `boolean`):

Only results available in 4K.

## `isHDR` (type: `boolean`):

Only results available in HDR.

## `hasSubtitles` (type: `boolean`):

Only results that have subtitles or closed captions.

## `hasCC` (type: `boolean`):

Only results published under a Creative Commons licence.

## `isLive` (type: `boolean`):

Only results that are live right now.

## `is360` (type: `boolean`):

Only 360-degree results.

## `is3D` (type: `boolean`):

Only 3D results.

## `isVR180` (type: `boolean`):

Only VR180 results.

## `oldestPostDate` (type: `string`):

Keep videos published after this date. Accepts YYYY-MM-DD or a relative form such as "7 days". Applied to the exact publish timestamp on Balanced and Detailed.

## `newestPostDate` (type: `string`):

Keep videos published before this date. Same formats as above.

## `includeComments` (type: `boolean`):

Attach top-level comments to each video row.

## `maxComments` (type: `integer`):

How many top-level comments to attach to each video. Comments are only scraped when this is above zero.

## `sortCommentsBy` (type: `string`):

Whether to take YouTube's top comments or the most recent ones.

## `region` (type: `string`):

Two-letter country code YouTube should serve results for.

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

Proxy used to reach YouTube. The default works for most runs.

## Actor input object example

```json
{
  "searchQueries": [
    "web scraping tutorial"
  ],
  "startUrls": [],
  "maxResults": 20,
  "maxResultsShorts": 0,
  "maxResultStreams": 0,
  "preset": "balanced",
  "sortingOrder": "relevance",
  "dateFilter": "any",
  "videoType": "video",
  "lengthFilter": "any",
  "isHD": false,
  "is4K": false,
  "isHDR": false,
  "hasSubtitles": false,
  "hasCC": false,
  "isLive": false,
  "is360": false,
  "is3D": false,
  "isVR180": false,
  "includeComments": false,
  "maxComments": 0,
  "sortCommentsBy": "top",
  "region": "US",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `performance` (type: `string`):

No description

## `channel` (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"
    ],
    "startUrls": [],
    "maxResults": 20
};

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

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

```

## MCP server setup

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