# YouTube Hashtag Video & Shorts Ranking Scraper (`dataspryva/youtube-hashtag-video-and-shorts-ranking-scraper`) Actor

Look up one or more YouTube hashtags and get the videos and Shorts currently ranked under them, in order, with view count, channel, duration and the hashtag's own total video and channel counts.

- **URL**: https://apify.com/dataspryva/youtube-hashtag-video-and-shorts-ranking-scraper.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** Social media, Videos, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Hashtag Video & Shorts Ranking Scraper

YouTube's hashtag pages are live rankings of the videos and Shorts carrying a tag. This actor reads that feed for any hashtag, pages as deep as YouTube allows, and returns each card with its channel, engagement, publish date and hashtag totals — with no login, cookies, API key or proxy setup.

### What this actor does

- **Reads one or many hashtags** in a single run, from bare tags, `#tags` or full YouTube hashtag URLs
- **Pages the whole reachable feed** instead of stopping at the first screen, and handles both regular videos and Shorts
- **Adds detail data on request** — exact views, likes, comments, subscriber counts, ISO publish dates, descriptions, keywords, categories, channel handles and avatars
- **Sorts and filters locally** by views, duration, publish date, minimum views or earliest publish date
- **Localizes correctly** with a market and language pair, including localized tab names and count formats
- **Empty fields are omitted** — each record contains only the values YouTube actually supplied

### Output per video or Short

| Field | Description |
|---|---|
| `recordType` | `video` for content rows, `error` for a hashtag-level failure |
| `success` | `false` on error rows, omitted on content rows |
| `type` | `video` or `short` |
| `hashtag` | Normalized hashtag, without `#` |
| `hashtagUrl` | Canonical hashtag page URL |
| `hashtagTitle` | The hashtag page's own display title |
| `videoCountText` / `videoCount` | Total videos tagged with the hashtag, as displayed and as an exact number when YouTube shows one |
| `channelCountText` / `channelCount` | Total channels posting under the hashtag, as displayed and as an exact number when available |
| `position` | 1-indexed position in the returned, deduplicated result set |
| `videoId` | YouTube video ID |
| `title` | Video or Short title |
| `url` | Watch URL for videos, Shorts URL for Shorts |
| `channelName` | Channel display name |
| `channelId` | YouTube channel ID |
| `channelUrl` | Channel page URL |
| `channelHandle` | Channel handle such as `@creator`, when YouTube exposes it |
| `channelAvatarUrl` | Channel avatar image URL |
| `channelSubscriberCountText` | Subscriber label as displayed, e.g. `1.2M subscribers` |
| `channelSubscriberCount` | Exact subscriber count only when the label is not rounded |
| `viewCountText` | Views as displayed, in the selected language |
| `viewCount` | Exact view count when available; rounded labels stay text-only |
| `likeCountText` | Likes as displayed, e.g. `11K` |
| `likeCount` | Exact like count only when the label is not rounded |
| `commentCountText` / `commentCount` | Comment count as displayed, and as an exact number when available |
| `publishedTimeText` | Relative publish label, e.g. `3 days ago` |
| `publishedAt` | ISO 8601 publish date; includes the time and source offset when YouTube exposes them |
| `durationText` | Duration label such as `12:34` |
| `durationSeconds` | Duration in seconds, including Shorts when details are on |
| `thumbnailUrl` | Highest-resolution thumbnail available |
| `isShort` | `true` for a Short, `false` for a regular video |
| `description` | Video description |
| `keywords` | Video keywords/tags array |
| `category` | YouTube category name |
| `badges` | Content badges such as `CC` or `4K` |
| `scrapedAt` | ISO 8601 UTC timestamp of the run |
| `errorCode` / `error` | Present on error rows: `INVALID_HASHTAG`, `HASHTAG_NOT_FOUND`, `NO_VIDEOS` or `BLOCKED` |

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `hashtags` | array | – | Tags to scrape, with or without `#`, or full hashtag URLs (required) |
| `maxResultsPerHashtag` | integer | `50` | Records to return per hashtag after sorting and filters (1–500) |
| `contentType` | string | `all` | `all`, `videos` (regular only) or `shorts` (Shorts only) |
| `market` | string | `US` | Country/region for the feed |
| `language` | string | `auto` | Label language; `auto` follows the market |
| `includeVideoDetails` | boolean | `true` | Add exact counts, dates, descriptions and channel metadata |
| `sortBy` | string | `default` | `default`, `viewCount`, `durationSeconds` or `publishedAt` |
| `minViewCount` | integer | – | Drop videos below this exact view count |
| `publishedAfter` | string | – | Keep only videos published on or after this date (`YYYY-MM-DD`) |

#### Example: one hashtag, ranked by views

```json
{
  "hashtags": ["#webscraping"],
  "contentType": "all",
  "maxResultsPerHashtag": 100,
  "sortBy": "viewCount",
  "includeVideoDetails": true
}
```

#### Example: regular videos in Germany

```json
{
  "hashtags": ["cooking"],
  "contentType": "videos",
  "market": "DE",
  "language": "de",
  "maxResultsPerHashtag": 50
}
```

#### Example: recent Shorts with a view floor

```json
{
  "hashtags": ["travel", "food"],
  "contentType": "shorts",
  "minViewCount": 100000,
  "publishedAfter": "2026-01-01",
  "sortBy": "publishedAt",
  "maxResultsPerHashtag": 100
}
```

#### Example: paste a hashtag URL

```json
{
  "hashtags": ["https://www.youtube.com/hashtag/artificialintelligence"],
  "contentType": "videos",
  "market": "JP",
  "language": "ja",
  "maxResultsPerHashtag": 75
}
```

### Use cases

- **Trend discovery** — see which videos and Shorts currently rank under a topic, in a chosen market
- **Creator sourcing** — find channels that repeatedly appear under a niche hashtag
- **Campaign tracking** — monitor a branded hashtag's ranking and engagement over time
- **Format research** — compare regular videos with Shorts using exact views, likes, comments and duration
- **Regional analysis** — compare the same hashtag across markets and languages

### FAQ

**Do I need a YouTube account, API key or cookies?**
No. Hashtag pages and the detail data are public and the actor reads them anonymously.

**Why are some fields missing from Shorts?**
Shorts cards carry less metadata than regular video cards. With `includeVideoDetails` on, channel, exact views, publish date and duration are filled from each Short's detail data. Rounded labels such as `1.2M views` remain text-only and are never presented as exact numbers.

**How many results can I get per hashtag?**
Up to `maxResultsPerHashtag`, but YouTube's hashtag feed is a ranked sample rather than a complete index. Large tags typically expose a few hundred unique cards over many pages; small or new tags may expose only a handful.

**Why does the same input return a different order on another run?**
YouTube shuffles hashtag feeds between requests. The actor deduplicates by video ID and assigns `position` from the returned set; use `sortBy` when you need a stable order.

**What does `market` change?**
It changes which videos rank and the default language. `language` controls only labels and formatting; set it explicitly if you want a different language from the market default.

**What is the difference between `viewCountText` and `viewCount`?**
`viewCountText` is exactly what YouTube displayed. `viewCount` is an integer only when the source gives an unabridged number; compact labels remain text-only, so an estimate is never passed off as exact.

**What happens if a hashtag has no results?**
The run continues to the next hashtag and writes an error row with `recordType: "error"`, an `errorCode` and a readable message.

**Can I scrape more than one hashtag at once?**
Yes. List up to 200 unique hashtags; results are combined in one dataset with per-hashtag positions.

# Actor input Schema

## `hashtags` (type: `array`):

Hashtags to scrape. Accepts a bare tag, a #tag, or a full youtube.com/hashtag/<tag> URL. Up to 200 unique tags per run.

## `maxResultsPerHashtag` (type: `integer`):

Maximum records to return per hashtag after sorting and filters. YouTube's hashtag feed is a ranked sample, so large values may return fewer rows.

## `contentType` (type: `string`):

Which cards to return: regular videos, Shorts, or both.

## `market` (type: `string`):

Country/region used for the hashtag feed. It changes which videos rank and the default language.

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

Language used for YouTube labels, counts and dates. Auto follows the selected market.

## `includeVideoDetails` (type: `boolean`):

Fetch each video's detail data to fill exact views, likes, comments, subscriber counts, publish date, description, keywords, category and Shorts channel metadata. Slower but more complete.

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

Order the collected results within each hashtag. Default keeps YouTube's first-seen feed order.

## `minViewCount` (type: `integer`):

Drop videos with fewer than this many views. Turns on detail enrichment so compact Shorts labels are not mis-filtered.

## `publishedAfter` (type: `string`):

Only keep videos published on or after this date (YYYY-MM-DD). Turns on detail enrichment.

## Actor input object example

```json
{
  "hashtags": [
    "programming"
  ],
  "maxResultsPerHashtag": 2,
  "contentType": "videos",
  "market": "US",
  "language": "auto",
  "includeVideoDetails": false,
  "sortBy": "default"
}
```

# Actor output Schema

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

Dataset containing all scraped videos and shorts tagged with the requested hashtags.

# 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 = {
    "hashtags": [
        "programming"
    ],
    "maxResultsPerHashtag": 2,
    "contentType": "videos",
    "market": "US",
    "language": "auto",
    "includeVideoDetails": false,
    "sortBy": "default"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/youtube-hashtag-video-and-shorts-ranking-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 = {
    "hashtags": ["programming"],
    "maxResultsPerHashtag": 2,
    "contentType": "videos",
    "market": "US",
    "language": "auto",
    "includeVideoDetails": False,
    "sortBy": "default",
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/youtube-hashtag-video-and-shorts-ranking-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 '{
  "hashtags": [
    "programming"
  ],
  "maxResultsPerHashtag": 2,
  "contentType": "videos",
  "market": "US",
  "language": "auto",
  "includeVideoDetails": false,
  "sortBy": "default"
}' |
apify call dataspryva/youtube-hashtag-video-and-shorts-ranking-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataspryva/youtube-hashtag-video-and-shorts-ranking-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/mSw6ELIsZXjgPdFNp/builds/jVtydLgaRgAoNQmFS/openapi.json
