Vexaloom Labs

Use YouTube Shorts Metadata Extractor for Channels & Hashtags with Python

Pull Shorts from a channel's Shorts tab, a hashtag feed, or specific Shorts links, with views, likes, comment counts, upload dates and channel profile detail.

1. Choose the data you need

Review the published README for supported collection modes, examples, and limits. The recipe below uses the current published input definition.

2. Prepare a source-based input

This JSON contains published prefills and required-field defaults. Review every value for your task before running it; it is not a promise of successful collection.

{
  "channelUrls": [
    "https://www.youtube.com/@MrBeast"
  ],
  "hashtags": [
    "#shorts"
  ],
  "includeDetails": true,
  "includeMembersOnly": false,
  "maxShorts": 3,
  "oldestPostDate": "",
  "searchQueries": [
    "cooking shorts"
  ],
  "shortUrls": [
    "https://www.youtube.com/shorts/pfUG56htjBc"
  ],
  "sortShortsBy": "newest"
}

Download input.example.json and save your reviewed copy as input.json.

FieldTypeRequiredDescription
inputModestringoptionalWhere to find Shorts. 'channel' reads a channel's Shorts tab, 'hashtag' a hashtag's Shorts feed, 'search' YouTube search results filtered to Shorts, 'direct' specific Shorts URLs or video IDs, 'sound' finds other Shorts that use the same sound as seed Shorts.
channelUrlsarrayoptionalYouTube channel URLs, handles (@username), or channel IDs (UCxxx). Required when inputMode is 'channel'.
hashtagsarrayoptionalHashtags to scrape Shorts from (e.g. #cooking, sports). Required when inputMode is 'hashtag'. Include or omit the # prefix.
searchQueriesarrayoptionalKeywords to search on YouTube, keeping only Shorts results. Required when inputMode is 'search'.
shortUrlsarrayoptionalShorts URLs, youtu.be links, watch URLs, or 11-character video IDs. Required when inputMode is 'direct'; used as the sound seeds when inputMode is 'sound'.
sortShortsBystringoptionalOrder of the channel's Shorts tab, matching the buttons YouTube shows: newest first (default), most popular, or oldest first. Falls back to newest when a channel does not offer the chosen order.
maxShortsintegeroptionalMaximum number of Shorts to return per channel, hashtag or search query (per run in direct mode).
includeDetailsbooleanoptionalVisit each Short's page for exact views, likes, comment count, publish date, duration, category, sound and captions. Turn off for a faster, cheaper listing-only run (views as displayed, no likes or dates).
includeMembersOnlybooleanoptionalChannel mode only. Also collect members-only Shorts when YouTube offers the 'Members only' filter on that channel's Shorts tab (a gradual rollout — the actor retries the tab a few times and notes it in the status message when unavailable). Member rows count toward maxShorts and cost up to two player requests each.
oldestPostDatestringoptionalOnly include Shorts published on or after this date. Format: YYYY-MM-DD. Leave empty to include all. Works in channel, search and direct modes; hashtag mode needs 'Include Exact Details' because dates come from each Short's page.
marketstringoptionalYouTube market/region for localized content. Affects the language of metadata returned.

3. Start an Actor run

Set APIFY_TOKEN in your environment. Python 3.10 or newer is sufficient; this recipe uses no third-party packages.

Execution may incur charges. Review current pricing on Apify. The request asks for a 120-second timeout and a charge limit; these settings are subject to Apify’s pricing and do not guarantee an all-inclusive spending cap.

import json
import os
import urllib.request

# Save the schema-derived example as input.json; review and edit it first.
with open("input.json", encoding="utf-8") as stream:
    actor_input = json.load(stream)

token = os.environ["APIFY_TOKEN"]
request = urllib.request.Request(
    "https://api.apify.com/v2/acts/4Y3stChofe6TqJpa9/runs?timeout=120&maxTotalChargeUsd=0.50",
    data=json.dumps(actor_input).encode("utf-8"),
    headers={"Authorization": "Bearer " + token, "Content-Type": "application/json"},
    method="POST",
)
# This starts a potentially billable run. Do not automatically retry this POST.
with urllib.request.urlopen(request, timeout=40) as response:
    run = json.load(response)["data"]
print("Run ID:", run["id"])
print("Status:", run["status"])
# Inspect and download results in Apify Console once the run succeeds.

4. Inspect the actual results

Open the run in Apify Console and wait for a successful completion. Use the published output schema to locate results and the dataset schema to understand declared views. Missing or optional record fields must not be treated as guaranteed values.

YouTube Shorts with exact view, like, comment, date, duration, category and sound metadata, scraped by channel, hashtag, keyword search or direct URL.

Questions before you run

Which inputs are required?

No top-level fields are marked required in the published schema. Conditional requirements can still apply; check the README.

What does this guide verify?

The fields, prefills, and schema links are rendered from the published build. This is a usage recipe, not a paid live extraction test. Source availability and collection results can vary.

What if the run request times out?

Check Apify Console before retrying. The first request may already have created a run. Do not automatically repeat a run-creation POST.

Generated from source build 19hYhFgrgWdPSTJvc and its README and schemas. Source changes regenerate this guide; no third-party editorial claims are inferred.