# YouTube Hashtag Trend Discovery — Find Trending Videos (`sian.agency/youtube-hashtag-trend-discovery`) Actor

Discover viral YouTube hashtags by topic. Find trending Shorts and videos behind any hashtag — explore, bulk-audit, autocomplete-discover, or expand into related hashtags. Built for social media managers, content strategists, and trend forecasters. No account or API key needed.

- **URL**: https://apify.com/sian.agency/youtube-hashtag-trend-discovery.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** Videos, Social media, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 hashtag video rows

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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 Hashtag Trend Discovery — Find Trending Videos #️⃣🚀

[![Store-SIÁN Agency](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Store-YouTube Query Suggestions](https://img.shields.io/badge/Store-YouTube%20Query%20Suggestions-FF0000)](https://apify.com/sian.agency/youtube-auto-complete-and-query-suggestion?fpr=sian) [![Store-YouTube Shorts Transcript](https://img.shields.io/badge/Store-YouTube%20Shorts%20Transcript-FF0000)](https://apify.com/sian.agency/youtube-shorts-ai-transcript-and-metadata-extractor?fpr=sian) [![Store-YouTube Comments Scraper](https://img.shields.io/badge/Store-YouTube%20Comments%20Scraper-FF0000)](https://apify.com/sian.agency/cheapest-youtube-comments-scraper?fpr=sian)

#### 🎉 Four hashtag operations in one tool — explore, bulk, autocomplete, expand
##### For social media managers, content strategists, SEO teams, and trend forecasters who need YouTube hashtag intelligence before their competitors do.

---

### 📋 Overview

**Stop guessing which YouTube hashtags actually work.** This actor turns any hashtag — or any topic seed — into a structured dataset of trending videos, Shorts, suggestion lists, and related hashtag networks. Built for teams who run on data, not vibes.

**Why thousands of professionals choose us:**
- ✅ **Four operations, one input**: Explore one hashtag, bulk-audit a list, autocomplete-discover new ideas, or expand a seed into its related hashtag neighborhood — all from a single actor. No other YouTube hashtag tool offers this.
- ⚡ **Adoption metadata on every row**: Each video carries `hashtagTotalVideos` and `hashtagTotalChannels` (parsed straight from YouTube's hashtag panel — e.g. `#music` = 186M videos · 28M channels). Know which hashtags are saturated battlegrounds vs fresh territory at a glance.
- 🎯 **Real trending data, not guesses**: Direct from YouTube's own hashtag pages, search ranking, and autocomplete engine. Same data YouTube serves to users — clean, structured, paginated.
- 💰 **Mid-tier pricing that signals quality**: $0.004 per row. Below premium tools at $0.02, double the rock-bottom commodity at $0.002. Honest middle.
- 💎 **Built for production**: Bulk inputs up to 200 hashtags per run. Pagination up to 25 pages. Geo + language localization. Webhook-ready clean JSON output.
- ✨ **NEW**: Hashtag expansion mode — give us one seed hashtag, get back a structured map of related hashtags + the actual trending content for each. Perfect for SEO and content-cluster research.

---

### ✨ Features

- #️⃣ **Single Hashtag Explore**: Get the latest trending videos OR Shorts for any hashtag with paginated depth control.
- 📚 **Bulk Hashtag Mode**: Audit up to 200 hashtags in one run — one paginated pull per hashtag, clean rows.
- 💡 **Autocomplete Discovery**: Seed a topic (`trav`, `fitness`, `react`) and get back the hashtag suggestions YouTube actually surfaces in its search box.
- 🌐 **Hashtag Expansion**: Pass one seed hashtag, get back BOTH the related hashtag suggestions YouTube ranks AND the trending content for them.
- 📊 **Adoption Counts on Every Row**: `hashtagTotalVideos` and `hashtagTotalChannels` parsed and surfaced as integers. Filter saturated hashtags out of your dataset.
- 🎥 **Content Type Filter**: Pick `videos` (long-form, full metadata) or `shorts` (Shorts feed) per run — no mixed rows, no surprises.
- 🌍 **Geo + Language Localization**: Optional country code and language code parameters — surface region-specific trending content.
- 🔄 **Auto-Normalized Hashtags**: We strip leading `#`, reject invalid whitespace tokens before charging, and emit an explicit `invalid_hashtag` status row when YouTube rejects an input.
- 📦 **Clean JSON Output**: ISO 8601 timestamps, integer view counts, canonical channel/video/short URLs — everything is webhook-ready.
- 📑 **HTML Run Report**: Each run writes a styled summary report (success counts, hashtag breakdown, pages fetched, duration) to the key-value store.

---

### 🎬 Quick Start

Pass one hashtag, get back the trending videos behind it. Or pass a list of 50 hashtags and let the actor paginate each one. Three minutes from input to dataset.

```bash
curl -X POST "https://api.apify.com/v2/acts/sian.agency~youtube-hashtag-trend-discovery/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"operation":"hashtagVideos","hashtag":"music","maxPages":3,"contentType":"videos"}'
````

***

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Pick your operation

Choose `hashtagVideos` (one hashtag, paginated), `bulkHashtags` (a list of hashtags), `suggestHashtags` (topic → autocomplete hashtag ideas), or `hashtagExpansion` (one hashtag → related hashtags + content).

#### Step 2: Provide your input

Drop in a hashtag without the `#` prefix (we auto-strip it). For bulk mode, paste a comma-separated list or one hashtag per line. For autocomplete, pass a short topic seed.

#### Step 3: Run and review

Hit Start. Results stream into the Apify dataset as they come in. The HTML run summary shows hashtag breakdown, success counts, and pagination depth.

**That's it! In under five minutes, you'll have:**

- A clean dataset of trending videos with view counts, channels, publish dates, and adoption metadata
- Hashtag suggestion lists or related-hashtag maps for content clustering
- A styled HTML report you can share with your team

***

### 📥 Input Configuration

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `operation` | string (enum) | Yes | One of `hashtagVideos`, `bulkHashtags`, `suggestHashtags`, `hashtagExpansion` |
| `hashtag` | string | When `hashtagVideos` | Single hashtag, `#` auto-stripped, no spaces allowed |
| `hashtags` | string | When `bulkHashtags` | Comma- or newline-separated list, max 200 hashtags |
| `seedTopic` | string | When `suggestHashtags` | Topic seed for autocomplete (e.g. `trav`, `fitness`) |
| `seedHashtag` | string | When `hashtagExpansion` | One hashtag to expand into related hashtags + content |
| `contentType` | string (enum) | No (default `videos`) | `videos` for long-form, `shorts` for Shorts feed |
| `maxPages` | integer | No (default `3`) | Max paginated pages per hashtag, range 1-25 |
| `geo` | string | No | 2-letter country code (e.g. `US`, `JP`) for localization |
| `lang` | string | No | Language code (e.g. `en`, `es`, `ja`) for result language |

**Single hashtag example:**

```json
{
  "operation": "hashtagVideos",
  "hashtag": "music",
  "maxPages": 3,
  "contentType": "videos"
}
```

**Bulk example:**

```json
{
  "operation": "bulkHashtags",
  "hashtags": "music\ngaming\nsolana\ntravelhacks\nhomelab",
  "maxPages": 1,
  "contentType": "videos"
}
```

**Autocomplete discovery example:**

```json
{
  "operation": "suggestHashtags",
  "seedTopic": "trav"
}
```

**Hashtag expansion example:**

```json
{
  "operation": "hashtagExpansion",
  "seedHashtag": "tutorial",
  "maxPages": 2
}
```

***

### 📤 Output

Results are saved to the Apify dataset with **30+ fields** spanning four row kinds (`video`, `suggestion`, `related-hashtag`, plus error/invalid statuses). Filter by `rowKind` or `_operation` to slice cleanly.

#### Top fields by use case

| Field | Type | Description |
|-------|------|-------------|
| `_operation` | string | Which operation produced this row (`hashtagVideos`, `bulkHashtags`, `suggestHashtags`, `hashtagExpansion`) |
| `_sourceHashtag` | string | The hashtag this row was discovered from (normalized form) |
| `rowKind` | string | `video`, `suggestion`, or `related-hashtag` |
| `videoId` | string | YouTube 11-char video ID |
| `videoPageUrl` | string | Canonical `https://www.youtube.com/watch?v=...` URL |
| `shortsPageUrl` | string | Canonical `https://www.youtube.com/shorts/...` URL |
| `isShort` | boolean | `true` for YouTube Shorts, `false` for long-form |
| `videoTitle` | string | Video title (long-form videos always; Shorts feed often returns null) |
| `channelTitle` | string | Channel display name |
| `channelHandle` | string | `@handle` for the channel |
| `channelPageUrl` | string | Canonical channel URL |
| `viewCount` | integer | Integer view count |
| `publishDate` | string | ISO 8601 publish date |
| `hashtagText` | string | The hashtag itself (e.g. `#music`) |
| `hashtagTotalVideos` | integer | Total videos using this hashtag (e.g. `186000000`) |
| `hashtagTotalChannels` | integer | Total channels using this hashtag (e.g. `28000000`) |
| `suggestionText` | string | Raw autocomplete suggestion (suggestHashtags mode) |
| `normalizedHashtag` | string | Suggestion converted to a hashtag form, ready to feed back into the actor |
| `position` | integer | 1-based ordinal in the response |

**Example hashtag video row:**

```json
{
  "_operation": "hashtagVideos",
  "_sourceHashtag": "music",
  "rowKind": "video",
  "videoId": "BDdcoiGMRQU",
  "videoPageUrl": "https://www.youtube.com/watch?v=BDdcoiGMRQU",
  "isShort": false,
  "videoTitle": "JORJ - SNIMKITE | Official 4K Video, 2026 #music",
  "channelId": "UCZW6wX1ATmWR13R8Cj7wE4A",
  "channelTitle": "Ra Music",
  "channelPageUrl": "https://www.youtube.com/channel/UCZW6wX1ATmWR13R8Cj7wE4A",
  "viewCount": 103167,
  "viewCountText": "103,167 views",
  "lengthText": "3:00",
  "publishDate": "2026-05-07",
  "publishedAt": "2026-05-07T00:00:00Z",
  "hashtagText": "#music",
  "hashtagInfoText": "186M videos • 28M channels",
  "hashtagTotalVideos": 186000000,
  "hashtagTotalChannels": 28000000
}
```

**Example suggestion row:**

```json
{
  "_operation": "suggestHashtags",
  "_sourceSeed": "trav",
  "rowKind": "suggestion",
  "suggestionText": "#travelhacks",
  "normalizedHashtag": "travelhacks",
  "isHashtagSuggestion": true,
  "position": 7
}
```

**Example related-hashtag row (from `hashtagExpansion`):**

```json
{
  "_operation": "hashtagExpansion",
  "_sourceSeed": "tutorial",
  "rowKind": "related-hashtag",
  "hashtagText": "#tutorial",
  "hashtagInfoText": "11M videos • 2.3M channels",
  "hashtagTotalVideos": 11000000,
  "hashtagTotalChannels": 2300000,
  "position": 1
}
```

***

### 💼 Use Cases & Examples

#### 1. Social Media Manager — Hashtag Research Before Campaign Launch

**Sarah runs the social team at a DTC fashion brand. She needs to pick 5 hashtags for next month's video drop — but she doesn't want to waste budget on a saturated tag with 200M competing videos.**

**Input:** 25 candidate hashtags via `bulkHashtags`.
**Output:** Every hashtag's trending videos plus adoption counts (`hashtagTotalVideos`, `hashtagTotalChannels`).
**Use:** Sarah filters to hashtags where total videos are between 100K and 5M — the goldilocks zone — and ships the campaign on data, not gut feel.

#### 2. Content Strategist — Discover Topical Wedges Before They Saturate

**Marcus runs content strategy at a B2B SaaS shop targeting devs. He needs to find the rising YouTube hashtags around `react` and `nextjs` before everyone else piles in.**

**Input:** `suggestHashtags` mode with seed topics like `react`, `nextjs`, `serverless`.
**Output:** YouTube's actual autocomplete suggestions — ranked hashtag candidates straight from the search box.
**Use:** Marcus spots `#reactislands` and `#partialhydration` as emerging hashtags weeks before they hit mainstream blog posts and prebuilds content for the wave.

#### 3. Trend Forecaster — Weekly Hashtag Delta Tracking

**Jen builds dashboards at a trend-forecasting agency. Her clients pay $5K/mo for early-signal reports — and she needs to detect rising hashtags 2-4 weeks before they hit mainstream metrics.**

**Input:** A locked list of 50 vertical-specific hashtags, run weekly via `bulkHashtags`.
**Output:** Time-series-ready rows with `hashtagTotalVideos` snapshots she diffs week-over-week.
**Use:** Hashtags showing 15%+ weekly video-count growth flag as "trending up" in Jen's dashboards — the early-warning system her clients pay for.

#### 4. SEO Team — Hashtag-to-Keyword Research at Scale

**Priya leads SEO at a hospitality marketplace. She knows hashtag intent often mirrors search intent — but she needs a way to map the topical neighborhood around `#travelhacks` for her content cluster planning.**

**Input:** `hashtagExpansion` mode with `travelhacks` as the seed.
**Output:** A structured list of related hashtags YouTube surfaces (`#travelessentials`, `#travelvlog`, `#solotraveltips`...) each with adoption counts.
**Use:** Priya pipes the rows into her keyword tool, cross-references search volumes, and builds 15 content briefs targeting under-served corners of the travel space.

#### 5. AI Training Pipeline — Hashtag-Clustered Video Datasets

**Diego ships training data for an open-source video understanding model. His team needs hashtag-tagged YouTube video metadata for clustering — clean, structured, with source-of-truth labels.**

**Input:** `bulkHashtags` mode with the project's 80-hashtag taxonomy.
**Output:** Thousands of video rows each carrying the `_sourceHashtag` they came from, ready for clustering.
**Use:** Diego trains the model with hashtag labels as weak supervision — no manual labeling pipeline required, complete reproducibility per hashtag.

***

### 🔗 Integration Examples

#### JavaScript / Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });

const run = await client.actor('sian.agency/youtube-hashtag-trend-discovery').call({
  operation: 'hashtagVideos',
  hashtag: 'tutorial',
  maxPages: 3,
  contentType: 'videos',
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
// → { rowKind: 'video', videoId: '...', viewCount: 103167, hashtagTotalVideos: 11000000, ... }
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')

run = client.actor('sian.agency/youtube-hashtag-trend-discovery').call(
    run_input={
        'operation': 'bulkHashtags',
        'hashtags': 'music\ngaming\nsolana',
        'maxPages': 1,
    }
)

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item['hashtagText'], item['videoTitle'], item['viewCount'])
```

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/sian.agency~youtube-hashtag-trend-discovery/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"operation":"suggestHashtags","seedTopic":"react"}'
```

#### Automation Workflows (N8N / Zapier / Make)

1. **Trigger**: Weekly schedule, webhook, or new-row event in your CRM
2. **HTTP Request**: Call the actor's run endpoint with your hashtag list as JSON
3. **Process**: Fetch the dataset items via `/datasets/{id}/items`
4. **Action**: Write to Notion/Airtable, post to Slack, or pipe into your dashboard

***

### 📊 Performance & Pricing

#### FREE Tier (Try It Now)

- Full feature access — same operations, same quality, same fields
- Perfect for testing your hashtag list before scaling
- No credit card required

#### PAID Tier (Production Ready)

- Unlimited hashtags per run (up to the 200-per-run input cap)
- Pay-per-row: only billed for successful row pushes (invalid hashtags and errors are NEVER charged)
- Auto-laddered pricing — BRONZE through DIAMOND tier discounts apply automatically as you scale

💰 **Mid-tier honest pricing** — $0.004 per hashtag-video row puts us below the premium tools ($0.02+) and above the race-to-the-bottom commodity ($0.002 — fragile data, no metadata). The middle is where reliable bulk research lives.

🔗 [View current pricing](https://apify.com/sian.agency/youtube-hashtag-trend-discovery?fpr=sian)

***

### ❓ Frequently Asked Questions

**Q: How many hashtags can I process per run?**
A: Up to 200 hashtags in `bulkHashtags` mode. Single-hashtag operations have no limit on output rows — only on pagination depth (1-25 pages). For larger workloads, split into multiple runs.

**Q: Does the `#` prefix matter on input?**
A: No. We auto-strip leading `#` so `music`, `#music`, and `  #music  ` are all treated identically. Hashtags containing whitespace are rejected before charging with a clear error message — YouTube doesn't accept them.

**Q: Why do Shorts rows have fewer fields than videos rows?**
A: YouTube's Shorts feed itself returns sparser metadata than its videos feed — title, channel, and publish date are not in the Shorts response payload. We surface every field YouTube actually provides; we don't fabricate the rest. The `viewCount` and `videoId` are always present.

**Q: What happens if I pass an invalid hashtag?**
A: One row is pushed with `status: 'invalid_hashtag'` and a clear `errorMessage`, and you are NOT charged for it. You'll never lose budget to typos or YouTube-rejected inputs.

**Q: Can I get both videos AND Shorts in one run?**
A: Not in one operation — `contentType` is `videos` OR `shorts`, not both. The reason is that YouTube returns them via separate endpoints with different rate-limit budgets, and mixing them would make per-row pricing unfair. To get both, run twice.

**Q: How accurate is `hashtagTotalVideos`?**
A: We parse YouTube's own hashtag-info panel string (e.g. `"186M videos • 28M channels"`) into integers. The number itself is YouTube's published count and updates on their refresh cadence. Use it for relative ranking — it's the same number that powers their UI.

**Q: Is the data live or cached?**
A: Live — every run pulls fresh data from YouTube's hashtag, search, and autocomplete endpoints. No caching layer between you and YouTube.

**Q: Is this legal?**
A: Yes — we only access publicly visible YouTube data (the same data YouTube serves to any logged-out browser visiting a hashtag page). See our [legal section](#-is-it-legal-to-scrape-data) below.

*YouTube® is a trademark of Google LLC. This actor is an independent discovery tool. It is not affiliated with, endorsed by, or sponsored by Google LLC or YouTube.*

***

### 🐛 Troubleshooting

**"Hashtag contains whitespace" error before run starts**

- YouTube hashtags are single tokens — `machine learning` is invalid. Use the joined form `machinelearning` instead. We reject this BEFORE charging so you don't lose budget on typos.

**Only 1 page fetched even though `maxPages` is higher**

- YouTube's pagination is best-effort — the `continuation` token isn't always returned (depends on hashtag size, request rate, time of day). The actor stops when YouTube stops handing out tokens. The first page typically contains 25-36 rows of high-quality content already.

**Shorts rows are missing title / channelTitle**

- This is upstream behavior, not a bug. YouTube's Shorts feed endpoint returns sparser metadata than the videos endpoint — they only return `videoId`, `viewCount`, and thumbnail data. Use `hashtagVideos` with `contentType: videos` if you need full metadata.

**Empty dataset with `status: 'invalid_hashtag'` row**

- YouTube returned `"This hashtag is invalid"` or `"Not much to see right now"` for the input. Hashtag may not exist, may contain unsupported characters (emoji, certain non-Latin scripts), or has zero indexed content. Try a different spelling or a parent hashtag.

**Bulk mode returning very different row counts per hashtag**

- Normal — niche hashtags (`#solana` ≈ 21 videos per page) return fewer rows than mainstream ones (`#shorts` ≈ 36). This is the actual content YouTube has for each hashtag.

***

### ⚖ Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the **GDPR** in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

***

### 🤝 Support

[![Telegram Support](https://img.shields.io/badge/Telegram-Support%20Group-0088cc?logo=telegram)](https://t.me/+vyh1sRE08sAxMGRi)

**Join our active support community**

- For issues or questions, open an issue in the actor's repository
- Check [SIÁN Agency Store](https://apify.com/sian.agency?fpr=sian) for more automation tools
- 📧 <apify@sian-agency.online>

***

**Built by [SIÁN Agency](https://www.sian-agency.online)** | **[More Tools](https://apify.com/sian.agency?fpr=sian)**

# Actor input Schema

## `operation` (type: `string`):

Which operation to run. **`hashtagVideos`** explores ONE hashtag and returns trending videos or Shorts. **`bulkHashtags`** runs the same explore across many hashtags at once. **`suggestHashtags`** seeds YouTube's autocomplete (e.g. `trav` → `#travel`, `#traveltips`) for hashtag discovery. **`hashtagExpansion`** searches YouTube using a hashtag query and surfaces related hashtags + the trending content for each.

## `hashtag` (type: `string`):

**`hashtagVideos` mode.** A single hashtag to explore (e.g. `music`, `gaming`, `solana`). The `#` prefix is auto-stripped if present. Spaces are not allowed by YouTube — use the joined form (`machinelearning`, not `machine learning`). Non-Latin scripts and accented characters work fine (e.g. `アニメ`, `comida`).

## `hashtags` (type: `string`):

**`bulkHashtags` mode.** A list of hashtags, comma-separated OR one per line. Each hashtag becomes one paginated pull. The `#` prefix is auto-stripped. Limit 200 hashtags per run — split larger jobs into multiple runs.

## `seedTopic` (type: `string`):

**`suggestHashtags` mode.** A topic seed for YouTube's autocomplete engine (e.g. `trav`, `fitness`, `react`). YouTube returns up to 15 suggestions; we surface every suggestion that looks like a hashtag (starts with `#`) plus a normalized hashtag form for non-hashtag suggestions. Use this to find which hashtags YouTube *thinks* people search for in your topic.

## `seedHashtag` (type: `string`):

**`hashtagExpansion` mode.** A seed hashtag — we search YouTube with it as a query and return BOTH the related hashtag suggestions YouTube surfaces AND the trending videos for that search. Charges `related-hashtag-row` per related hashtag plus `hashtag-video-row` per video found.

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

For `hashtagVideos` and `bulkHashtags`. **`videos`** returns long-form videos with full metadata (title, channel, description, viewCount, publishDate). **`shorts`** returns YouTube Shorts only — these are sparser (viewCount, videoId, and thumbnail only — title/channel/date are not returned by YouTube for the Shorts feed). Pick one. To get both, run twice.

## `maxPages` (type: `integer`):

Max paginated pages to fetch PER hashtag for `hashtagVideos`, `bulkHashtags`, and `hashtagExpansion`. Each page returns about 36 video rows. Set to `1` for cheap sampling, `3-5` for a quality dataset, `10+` for deep dives. Range 1-25. Has no effect on `suggestHashtags` (single call always).

## `geo` (type: `string`):

Optional 2-letter country code (ISO 3166-1 alpha-2, e.g. `US`, `JP`, `DE`) to localize trending results. Different geos surface different videos for the same hashtag. Omit for global default.

## `lang` (type: `string`):

Optional language code (e.g. `en`, `es`, `ja`, `ar`) to localize the result language. Pairs well with `geo`. Omit for default.

## Actor input object example

```json
{
  "operation": "hashtagVideos",
  "hashtag": "music",
  "hashtags": "music\ngaming\ntutorial\ntravel\nfitness",
  "seedTopic": "trav",
  "seedHashtag": "tutorial",
  "contentType": "videos",
  "maxPages": 3,
  "geo": "US",
  "lang": "en"
}
```

# Actor output Schema

## `output` (type: `string`):

Hashtag-video rows (videoId, title, channelTitle, viewCount, publishDate, hashtagTotalVideos, hashtagTotalChannels, …), hashtag-suggestion rows (suggestionText, normalizedHashtag, position, …), or related-hashtag rows (hashtag, hashtagTotalVideos, hashtagTotalChannels, …).

## `report` (type: `string`):

HTML report with run status, success/error counts, hashtag breakdown, pages fetched, duration, and inputs — written even on fatal crash.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/youtube-hashtag-trend-discovery").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/youtube-hashtag-trend-discovery").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call sian.agency/youtube-hashtag-trend-discovery --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=sian.agency/youtube-hashtag-trend-discovery",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "YouTube Hashtag Trend Discovery — Find Trending Videos",
        "description": "Discover viral YouTube hashtags by topic. Find trending Shorts and videos behind any hashtag — explore, bulk-audit, autocomplete-discover, or expand into related hashtags. Built for social media managers, content strategists, and trend forecasters. No account or API key needed.",
        "version": "1.0",
        "x-build-id": "Te5dgmkJKS83c4Lse"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/sian.agency~youtube-hashtag-trend-discovery/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-sian.agency-youtube-hashtag-trend-discovery",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/sian.agency~youtube-hashtag-trend-discovery/runs": {
            "post": {
                "operationId": "runs-sync-sian.agency-youtube-hashtag-trend-discovery",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/sian.agency~youtube-hashtag-trend-discovery/run-sync": {
            "post": {
                "operationId": "run-sync-sian.agency-youtube-hashtag-trend-discovery",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "operation"
                ],
                "properties": {
                    "operation": {
                        "title": "🎯 Operation",
                        "enum": [
                            "hashtagVideos",
                            "bulkHashtags",
                            "suggestHashtags",
                            "hashtagExpansion"
                        ],
                        "type": "string",
                        "description": "Which operation to run. **`hashtagVideos`** explores ONE hashtag and returns trending videos or Shorts. **`bulkHashtags`** runs the same explore across many hashtags at once. **`suggestHashtags`** seeds YouTube's autocomplete (e.g. `trav` → `#travel`, `#traveltips`) for hashtag discovery. **`hashtagExpansion`** searches YouTube using a hashtag query and surfaces related hashtags + the trending content for each.",
                        "default": "hashtagVideos"
                    },
                    "hashtag": {
                        "title": "#️⃣ Hashtag (single)",
                        "type": "string",
                        "description": "**`hashtagVideos` mode.** A single hashtag to explore (e.g. `music`, `gaming`, `solana`). The `#` prefix is auto-stripped if present. Spaces are not allowed by YouTube — use the joined form (`machinelearning`, not `machine learning`). Non-Latin scripts and accented characters work fine (e.g. `アニメ`, `comida`)."
                    },
                    "hashtags": {
                        "title": "📚 Hashtags (bulk)",
                        "type": "string",
                        "description": "**`bulkHashtags` mode.** A list of hashtags, comma-separated OR one per line. Each hashtag becomes one paginated pull. The `#` prefix is auto-stripped. Limit 200 hashtags per run — split larger jobs into multiple runs."
                    },
                    "seedTopic": {
                        "title": "💡 Seed Topic (autocomplete)",
                        "type": "string",
                        "description": "**`suggestHashtags` mode.** A topic seed for YouTube's autocomplete engine (e.g. `trav`, `fitness`, `react`). YouTube returns up to 15 suggestions; we surface every suggestion that looks like a hashtag (starts with `#`) plus a normalized hashtag form for non-hashtag suggestions. Use this to find which hashtags YouTube *thinks* people search for in your topic."
                    },
                    "seedHashtag": {
                        "title": "🌐 Seed Hashtag (expansion)",
                        "type": "string",
                        "description": "**`hashtagExpansion` mode.** A seed hashtag — we search YouTube with it as a query and return BOTH the related hashtag suggestions YouTube surfaces AND the trending videos for that search. Charges `related-hashtag-row` per related hashtag plus `hashtag-video-row` per video found."
                    },
                    "contentType": {
                        "title": "🎥 Content Type",
                        "enum": [
                            "videos",
                            "shorts"
                        ],
                        "type": "string",
                        "description": "For `hashtagVideos` and `bulkHashtags`. **`videos`** returns long-form videos with full metadata (title, channel, description, viewCount, publishDate). **`shorts`** returns YouTube Shorts only — these are sparser (viewCount, videoId, and thumbnail only — title/channel/date are not returned by YouTube for the Shorts feed). Pick one. To get both, run twice.",
                        "default": "videos"
                    },
                    "maxPages": {
                        "title": "📄 Max pages per hashtag",
                        "minimum": 1,
                        "maximum": 25,
                        "type": "integer",
                        "description": "Max paginated pages to fetch PER hashtag for `hashtagVideos`, `bulkHashtags`, and `hashtagExpansion`. Each page returns about 36 video rows. Set to `1` for cheap sampling, `3-5` for a quality dataset, `10+` for deep dives. Range 1-25. Has no effect on `suggestHashtags` (single call always).",
                        "default": 3
                    },
                    "geo": {
                        "title": "🌍 Geo (optional)",
                        "type": "string",
                        "description": "Optional 2-letter country code (ISO 3166-1 alpha-2, e.g. `US`, `JP`, `DE`) to localize trending results. Different geos surface different videos for the same hashtag. Omit for global default."
                    },
                    "lang": {
                        "title": "🗣 Language (optional)",
                        "type": "string",
                        "description": "Optional language code (e.g. `en`, `es`, `ja`, `ar`) to localize the result language. Pairs well with `geo`. Omit for default."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
