# YouTube Shorts Scraper — Channel Shorts & Search, Views Growth (`northbell/youtube-shorts-scraper`) Actor

YouTube Shorts scraper: a channel's Shorts or the Shorts for any search, with views (exact on request), channel, thumbnail and rank. Run it again or on a schedule to get views per day, new Shorts and rank changes since the last run. @handles, URLs or search terms. No login.

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

## Pricing

from $0.80 / 1,000 shorts

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 Shorts Scraper — Channel Shorts & Search, Views Growth

Give it YouTube channels (`@handles`, channel URLs or `UC…` IDs) and/or search terms and get one clean row per Short: **title, link, views, channel, rank and thumbnail**, with **exact view counts and the publish date** when you ask for them. **$1 per 1,000 Shorts**, no login, no API key.

Run it again — or put it on a daily or hourly schedule — and every row also tells you **what changed since the last run**: views gained, **views per day**, how far the Short moved up or down the list, and which Shorts are **new**. YouTube only shows you today's numbers; this keeps the history for you.

### What you get

| Field | What it is |
|---|---|
| `source`, `sourceType` | the channel or search term you gave, and `channel` or `search` |
| `rank` | position in that source: for a channel, newest first; for a search, YouTube's own order |
| `videoId`, `url`, `title`, `thumbnailUrl` | the Short (`url` is `youtube.com/shorts/…`; `title` has e-mail addresses and phone numbers removed) |
| `views`, `viewsText`, `viewsExact` | views as a number, as YouTube writes it, and whether it is the exact count (`true` with *Exact views*) or the rounded one YouTube shows in lists (`30K views`) |
| `publishedText`, `publishedAt` | the publish date as YouTube writes it (`Aug 14, 2026`) and as `YYYY-MM-DD` — only with *Exact views* |
| `channelName`, `channelHandle`, `channelId` | who posted it (`channelHandle` is e.g. `@NASA`) |
| `previousViews`, `viewsChange`, `viewsPerDay`, `hoursSincePrevious` | the views when this Short was last seen, the change since then and the change per day (`null` on the first run) |
| `previousRank`, `rankChange`, `isNew` | the rank when last seen, how far it moved (**positive = moved up**) and whether this Short was not in the list before (`null` on the first run) |
| `observedAt`, `type` | when it was read, and `short` or `error` |

### Use it for

- **Trend watching** — schedule a search such as your niche's keyword every day and see which Shorts are new and which are climbing
- **Competitor and creator research** — all Shorts of a channel with views and views per day, to see what actually takes off
- **Reporting** — a Shorts log for your own channel or a client's, with history you own, exportable to Sheets or your BI tool

### Input

```json
{ "channels": ["@NASA", "https://www.youtube.com/@TED"], "searches": ["cooking hacks"], "maxShortsPerSource": 50, "exactViews": false }
```

Use channels, searches or both. History is remembered per channel and per search term in a named key-value store in your Apify account, so the second run of the same Actor already shows changes. Schedule it (Apify → Schedules) for a daily history. Put everything in one run: the run-start fee is charged once.

### Pricing

**$1 per 1,000 Shorts**, plus $0.01 per run. Error rows (a typo in a handle, a channel without Shorts, a search with no Shorts) are free. The $0.01 run-start fee is the one charge every run pays, even one that returns nothing.

### Notes

- **Rounded or exact views.** In lists YouTube rounds views (`30K`, `1.2M`), so with *Exact views* off a Short can show `viewsChange` 0 for days. Turn *Exact views* on when you track growth: the Actor opens each Short and reads the exact count (`260,647`) and the publish date. That is one extra request per Short, about a second each, at the same price.
- **Change since the last run.** `viewsChange` is only filled when both runs used the same kind of number (both exact or both rounded), so switching *Exact views* on or off skips the comparison once. `viewsPerDay` needs at least an hour between the runs. Without *Exact views* it is as coarse as YouTube's rounding.
- **Memory.** A Short that dropped out of the list and came back within 30 days is compared with when it was last seen (`hoursSincePrevious` tells you how long ago). After 30 days it counts as new again. If you raise *Shorts per channel or search*, the older Shorts that were not read before count as new in that run. For a channel (newest first), a new upload pushes every other Short down one place, so `rankChange` is -1 for all of them; watch `viewsChange` and `viewsPerDay` instead.
- **First run.** The *since last run* fields (`previousViews`, `viewsChange`, `viewsPerDay`, `hoursSincePrevious`, `previousRank`, `rankChange`, `isNew`) are `null` for a channel or search that is read for the first time. `publishedText` and `publishedAt` are `null` unless *Exact views* is on, because YouTube does not show the date in lists.
- **Channels.** You get the channel's Shorts tab, newest first, up to the number you ask for (500 at most). A channel has no more Shorts than it has: 201 for a large channel in our test.
- **Searches.** The search is filtered to Shorts and returns what YouTube gives a signed-out request in English. The Actor has no country setting: it runs from Apify's servers (in the US), so results are what a signed-out viewer in the US sees, and your own screen can differ. In our tests a search ran out after about 130 to 150 Shorts. YouTube also reshuffles search results from run to run: in one test, two runs seconds apart for the same term shared only 9 of 30 Shorts. So for a search, `isNew` means "was not in the list last time", not "was just published", and `rankChange` is noisy. For steady growth numbers track channels, whose Shorts list does not reshuffle. Channel names for search results cost one extra request per channel; if YouTube does not answer for one, `channelName` and `channelHandle` stay empty and `channelId` is still there.
- **Shorts that cannot be opened** with *Exact views* (removed, private, age-restricted) keep the rounded views from the list and `viewsExact: false`.
- Public data only: what anyone sees without signing in. No e-mail addresses or phone numbers are returned — they are removed from titles.

To track **specific videos** (exact likes and comments too), see [YouTube Video Stats Tracker](https://apify.com/northbell/youtube-video-stats-tracker). For **channel totals and growth** (subscribers, total views, uploads), see [YouTube Channel Stats & Growth Tracker](https://apify.com/northbell/youtube-channel-growth-tracker). For **where regular videos rank in YouTube search**, see [YouTube Search Rank Tracker](https://apify.com/northbell/youtube-search-rank-tracker).

### For AI agents

`{"channels": ["@NASA"], "maxShortsPerSource": 5}` returns 5 rows with title, views, channel and link; add `"searches": ["cooking hacks"]` for a search, and `"exactViews": true` for exact counts and publish dates. Rows have `type`: `short` or `error`.

# Actor input Schema

## `channels` (type: `array`):

One channel per line: @handle, a channel URL (youtube.com/@name, /channel/UC…, /c/name, /user/name) or a channel ID (UC…). You get that channel's Shorts, newest first. Use this, Search terms, or both.

## `searches` (type: `array`):

One search term per line. You get the Shorts YouTube shows for that search, in YouTube's order (what a signed-out viewer in the US sees). Use this, Channels, or both.

## `maxShortsPerSource` (type: `integer`):

How many Shorts to read from each channel and each search. A channel page holds 48 Shorts, a search page 25-40. Up to 500.

## `exactViews` (type: `boolean`):

On: open every Short to read its exact view count (260,647 instead of 260K), and its publish date. Slower: one extra request per Short, about 1 second each. Off: views are the rounded numbers YouTube shows in the list (30K, 1.2M). Turn it on when you track growth, because rounded numbers hide small changes.

## Actor input object example

```json
{
  "channels": [
    "@NASA"
  ],
  "maxShortsPerSource": 50,
  "exactViews": false
}
```

# Actor output Schema

## `shorts` (type: `string`):

Shorts with views, channel, rank and growth since the last run.

# 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 = {
    "channels": [
        "@NASA"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("northbell/youtube-shorts-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 = { "channels": ["@NASA"] }

# Run the Actor and wait for it to finish
run = client.actor("northbell/youtube-shorts-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 '{
  "channels": [
    "@NASA"
  ]
}' |
apify call northbell/youtube-shorts-scraper --silent --output-dataset

```

## MCP server setup

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