YouTube Hashtag Video & Shorts Ranking Scraper
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.
Input schema
Input fields, types, required flags, descriptions, defaults, and prefills come from the published definition. Prefill examples are distinct from defaults.
| Field | Type | Required | Description |
|---|---|---|---|
hashtags | array | required | 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 | integer | optional | 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 | string | optional | Which cards to return: regular videos, Shorts, or both. |
Show all input fields
| Field | Type | Required | Description |
|---|---|---|---|
hashtags | array | required | 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 | integer | optional | 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 | string | optional | Which cards to return: regular videos, Shorts, or both. |
market | string | optional | Country/region used for the hashtag feed. It changes which videos rank and the default language. |
language | string | optional | Language used for YouTube labels, counts and dates. Auto follows the selected market. |
includeVideoDetails | boolean | optional | 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 | string | optional | Order the collected results within each hashtag. Default keeps YouTube's first-seen feed order. |
minViewCount | integer | optional | Drop videos with fewer than this many views. Turns on detail enrichment so compact Shorts labels are not mis-filtered. |
publishedAfter | string | optional | Only keep videos published on or after this date (YYYY-MM-DD). Turns on detail enrichment. |
Download the published input schema
View complete JSON
{
"description": "Scrape YouTube videos and Shorts by hashtag. Provide one or more hashtags to extract ranked videos, channel details, exact engagement counts, publish dates and more.",
"properties": {
"contentType": {
"default": "all",
"description": "Which cards to return: regular videos, Shorts, or both.",
"editor": "select",
"enum": [
"all",
"videos",
"shorts"
],
"enumTitles": [
"All content",
"Regular videos only",
"Shorts only"
],
"prefill": "videos",
"title": "Content Type",
"type": "string"
},
"hashtags": {
"description": "Hashtags to scrape. Accepts a bare tag, a #tag, or a full youtube.com/hashtag/<tag> URL. Up to 200 unique tags per run.",
"editor": "stringList",
"items": {
"type": "string"
},
"minItems": 1,
"prefill": [
"programming"
],
"title": "Hashtags",
"type": "array"
},
"includeVideoDetails": {
"default": true,
"description": "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.",
"prefill": false,
"title": "Include Video Details",
"type": "boolean"
},
"language": {
"default": "auto",
"description": "Language used for YouTube labels, counts and dates. Auto follows the selected market.",
"editor": "select",
"enum": [
"auto",
"en",
"de",
"fr",
"ja",
"ko",
"pt",
"hi",
"es",
"it",
"nl",
"pl",
"ru",
"sv",
"no",
"da",
"fi",
"zh-Hant",
"id",
"ms",
"th",
"ar",
"tr",
"vi",
"uk",
"cs",
"ro",
"hu",
"el",
"he"
],
"enumTitles": [
"Auto (match market)",
"English",
"German",
"French",
"Japanese",
"Korean",
"Portuguese",
"Hindi",
"Spanish",
"Italian",
"Dutch",
"Polish",
"Russian",
"Swedish",
"Norwegian",
"Danish",
"Finnish",
"Traditional Chinese",
"Indonesian",
"Malay",
"Thai",
"Arabic",
"Turkish",
"Vietnamese",
"Ukrainian",
"Czech",
"Romanian",
"Hungarian",
"Greek",
"Hebrew"
],
"prefill": "auto",
"title": "Language",
"type": "string"
},
"market": {
"default": "US",
"description": "Country/region used for the hashtag feed. It changes which videos rank and the default language.",
"editor": "select",
"enum": [
"US",
"GB",
"CA",
"AU",
"DE",
"FR",
"JP",
"KR",
"BR",
"IN",
"MX",
"IT",
"ES",
"NL",
"PL",
"RU",
"SE",
"NO",
"DK",
"FI",
"ZA",
"SG",
"HK",
"TW",
"ID",
"MY",
"TH",
"PH",
"AR",
"CO",
"CL"
],
"enumTitles": [
"United States",
"United Kingdom",
"Canada",
"Australia",
"Germany",
"France",
"Japan",
"South Korea",
"Brazil",
"India",
"Mexico",
"Italy",
"Spain",
"Netherlands",
"Poland",
"Russia",
"Sweden",
"Norway",
"Denmark",
"Finland",
"South Africa",
"Singapore",
"Hong Kong",
"Taiwan",
"Indonesia",
"Malaysia",
"Thailand",
"Philippines",
"Argentina",
"Colombia",
"Chile"
],
"prefill": "US",
"title": "Market / Region",
"type": "string"
},
"maxResultsPerHashtag": {
"default": 50,
"description": "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.",
"maximum": 500,
"minimum": 1,
"prefill": 2,
"title": "Max Results Per Hashtag",
"type": "integer"
},
"minViewCount": {
"description": "Drop videos with fewer than this many views. Turns on detail enrichment so compact Shorts labels are not mis-filtered.",
"maximum": 2000000000,
"minimum": 0,
"title": "Minimum View Count",
"type": "integer"
},
"publishedAfter": {
"description": "Only keep videos published on or after this date (YYYY-MM-DD). Turns on detail enrichment.",
"editor": "textfield",
"title": "Published After",
"type": "string"
},
"sortBy": {
"default": "default",
"description": "Order the collected results within each hashtag. Default keeps YouTube's first-seen feed order.",
"editor": "select",
"enum": [
"default",
"viewCount",
"durationSeconds",
"publishedAt"
],
"enumTitles": [
"Feed order",
"Most views",
"Longest duration",
"Newest first"
],
"prefill": "default",
"title": "Sort By",
"type": "string"
}
},
"required": [
"hashtags"
],
"schemaVersion": 1,
"title": "YouTube Hashtag Scraper Input",
"type": "object"
}
Output schema
Published result links and storage locations. This schema is not an exhaustive contract for every field in a dataset record.
| Field | Type | Required | Description |
|---|---|---|---|
videos | string | optional | Dataset containing all scraped videos and shorts tagged with the requested hashtags. |
Download the published output schema
View complete JSON
{
"actorOutputSchemaVersion": 1,
"description": "Videos and Shorts ranked under the requested hashtags, with view count, channel info and hashtag totals.",
"properties": {
"videos": {
"description": "Dataset containing all scraped videos and shorts tagged with the requested hashtags.",
"template": "{{links.apiDefaultDatasetUrl}}/items",
"title": "YouTube hashtag videos and Shorts",
"type": "string"
}
},
"title": "YouTube Hashtag Video & Shorts Ranking Scraper Output"
}
Dataset schema
Published dataset views and any declared field definitions. A view can select only a subset of the returned record fields.
Download the published dataset schema
View complete JSON
{
"actorSpecification": 1,
"views": {
"full": {
"display": {
"component": "table",
"properties": {
"badges": {
"format": "text",
"label": "Badges"
},
"category": {
"format": "text",
"label": "Category"
},
"channelAvatarUrl": {
"format": "link",
"label": "Channel Avatar"
},
"channelCount": {
"format": "number",
"label": "Total Channel Count"
},
"channelCountText": {
"format": "text",
"label": "Total Channels"
},
"channelHandle": {
"format": "text",
"label": "Channel Handle"
},
"channelId": {
"format": "text",
"label": "Channel ID"
},
"channelName": {
"format": "text",
"label": "Channel"
},
"channelSubscriberCount": {
"format": "number",
"label": "Subscriber Count"
},
"channelSubscriberCountText": {
"format": "text",
"label": "Subscribers"
},
"channelUrl": {
"format": "link",
"label": "Channel URL"
},
"commentCount": {
"format": "number",
"label": "Comments"
},
"commentCountText": {
"format": "text",
"label": "Comments (label)"
},
"description": {
"format": "text",
"label": "Description"
},
"durationSeconds": {
"format": "number",
"label": "Duration (seconds)"
},
"durationText": {
"format": "text",
"label": "Duration"
},
"error": {
"format": "text",
"label": "Error"
},
"errorCode": {
"format": "text",
"label": "Error Code"
},
"hashtag": {
"format": "text",
"label": "Hashtag"
},
"hashtagTitle": {
"format": "text",
"label": "Hashtag Title"
},
"hashtagUrl": {
"format": "link",
"label": "Hashtag URL"
},
"isShort": {
"format": "boolean",
"label": "Is Short"
},
"keywords": {
"format": "text",
"label": "Keywords"
},
"likeCount": {
"format": "number",
"label": "Like Count"
},
"likeCountText": {
"format": "text",
"label": "Likes"
},
"position": {
"format": "number",
"label": "Position"
},
"publishedAt": {
"format": "text",
"label": "Published At"
},
"publishedTimeText": {
"format": "text",
"label": "Published (relative)"
},
"recordType": {
"format": "text",
"label": "Record Type"
},
"scrapedAt": {
"format": "text",
"label": "Scraped At"
},
"success": {
"format": "boolean",
"label": "Success"
},
"thumbnailUrl": {
"format": "link",
"label": "Thumbnail"
},
"title": {
"format": "text",
"label": "Title"
},
"type": {
"format": "text",
"label": "Type"
},
"url": {
"format": "link",
"label": "URL"
},
"videoCount": {
"format": "number",
"label": "Total Video Count"
},
"videoCountText": {
"format": "text",
"label": "Total Videos"
},
"videoId": {
"format": "text",
"label": "Video ID"
},
"viewCount": {
"format": "number",
"label": "View Count"
},
"viewCountText": {
"format": "text",
"label": "Views"
}
}
},
"title": "Full Details",
"transformation": {
"fields": [
"hashtag",
"hashtagUrl",
"hashtagTitle",
"videoCountText",
"videoCount",
"channelCountText",
"channelCount",
"position",
"recordType",
"success",
"type",
"videoId",
"title",
"url",
"channelName",
"channelId",
"channelUrl",
"channelHandle",
"channelAvatarUrl",
"channelSubscriberCountText",
"channelSubscriberCount",
"viewCountText",
"viewCount",
"likeCountText",
"likeCount",
"commentCountText",
"commentCount",
"publishedTimeText",
"publishedAt",
"durationText",
"durationSeconds",
"thumbnailUrl",
"isShort",
"description",
"keywords",
"category",
"badges",
"scrapedAt",
"errorCode",
"error"
]
}
},
"overview": {
"display": {
"component": "table",
"properties": {
"channelName": {
"format": "text",
"label": "Channel"
},
"hashtag": {
"format": "text",
"label": "Hashtag"
},
"position": {
"format": "number",
"label": "Position"
},
"publishedAt": {
"format": "text",
"label": "Published"
},
"title": {
"format": "text",
"label": "Title"
},
"type": {
"format": "text",
"label": "Type"
},
"url": {
"format": "link",
"label": "URL"
},
"videoId": {
"format": "text",
"label": "Video ID"
},
"viewCount": {
"format": "number",
"label": "Views"
}
}
},
"title": "Hashtag Overview",
"transformation": {
"fields": [
"hashtag",
"position",
"type",
"videoId",
"title",
"url",
"channelName",
"viewCount",
"publishedAt"
]
}
}
}
}
Key-value schema
Published key-value store definitions, when provided by this build.
This definition is not present in the default published build. See the published README for available documentation.
Published README
Read the full published documentation
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,
#tagsor 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
{
"hashtags": ["#webscraping"],
"contentType": "all",
"maxResultsPerHashtag": 100,
"sortBy": "viewCount",
"includeVideoDetails": true
}
Example: regular videos in Germany
{
"hashtags": ["cooking"],
"contentType": "videos",
"market": "DE",
"language": "de",
"maxResultsPerHashtag": 50
}
Example: recent Shorts with a view floor
{
"hashtags": ["travel", "food"],
"contentType": "shorts",
"minViewCount": 100000,
"publishedAfter": "2026-01-01",
"sortBy": "publishedAt",
"maxResultsPerHashtag": 100
}
Example: paste a hashtag URL
{
"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.
Python quickstart
Use a schema-derived input and the Python standard library to start a run. An Apify account and token are required for execution.
Source build jVtydLgaRgAoNQmFS. Documentation is regenerated from the default published build; private drafts are not included.