Deep-dive lookup
Hashtag lookup
Size up one hashtag on TikTok, Instagram, or YouTube Shorts before you build a campaign or brief creators around it.
- What it does
- Collects a sample of videos from one hashtag and sums up their views, creators, related tags, sounds, and posting dates. Optional trend analysis finds their creative patterns.
- You send
- The platform (
tiktok,instagram, oryoutube) and one hashtag, without the#. - You get back
- A
job_idright away. Check it every 10 to 15 seconds (this is called polling) until it sayscompleted, then read the results. - Cost
- $0.50, or up to $2.50 with more videos and trend analysis. Status checks, saved results, and the same lookup repeated within 6 hours are free.
- How long
- About 15 seconds on TikTok and 1 minute on YouTube or Instagram. Trend analysis on TikTok takes about 2 minutes. Bigger YouTube lookups take a few minutes.
Every number comes from a sample: the videos the platform lists first, not every video under the hashtag. On TikTok the sample can span years. For quick numbers on many hashtags, use Hashtags ($0.05 a request).
What it costs
You pay when the lookup starts. 1 credit is $0.01.
| You ask for | Videos collected, at most | Price |
|---|---|---|
| Standard (the default) | 50, or up to 100 with max_videos | $0.50 (50 credits) |
trend_analysis=true, depth=deep, or both | About 300 | $1.00 (100 credits) |
depth=full | About 500 | $2.00 (200 credits) |
depth=full with trend analysis | About 500 | $2.50 (250 credits) |
- A failed lookup is refunded in full, and the trend fee when no trends come out. Finding fewer videos than you paid for isn't refunded:
depth=deepon YouTube #cleantok found 103 videos and still cost $1.00. For a small hashtag, trymax_videos=100first. - Repeats within 6 hours are free (
cached: true) whensortmatches and the saved lookup already has the trends anddepthyou ask for (or deeper). A differentmax_videosstill gets the saved result as it was. Anything else is a new, billed lookup. - Your balance must cover the full price, even for a free repeat. To skip that check, open the saved run.
- The exact charge is in the
X-Cost(dollars) andX-Credits-Used(credits) response headers.
Start a hashtag lookup
Starts a lookup in the background and returns its ID at data.job_id. Each new lookup is billed (unusual for a GET), so don't call it in a loop. A free repeat returns status: "completed" and cached: true instead.
Up to $2.50 with options. See What it costs.
Path parameters
- Name
platform- Type
- string
- Required
- *
- Description
tiktok,instagram, oryoutube, in lowercase. YouTube collects Shorts only.
- Name
hashtag- Type
- string
- Required
- *
- Description
One tag, up to 100 characters, any case. Leave off the
#(or send it as%23). Spaces and other%signs are rejected. Comma lists likecleantok,organizingare not: they run as one tag, and you're billed.
Query parameters
- Name
trend_analysis- Type
- boolean
- Description
trueadds trend analysis (+$0.50) and collects about 300 videos (500 withdepth=full). Onlytrueor1work.Trueoryescount asfalse, with no error. Defaultfalse.
- Name
max_videos- Type
- integer
- Description
How many videos to collect, 1 to 100. Default
50. Standard lookups only.
- Name
sort- Type
- string
- Description
top(most views first, the default) orrecent(newest first). It only reorders the videos, but changing it bills a new lookup.
- Name
depth- Type
- string
- Description
standard(the default, usesmax_videos),deep(up to about 300 videos, +$0.50, no extra with trend analysis), orfull(up to about 500, +$1.50). The charge stays the same if fewer turn up. Not available on Instagram.
Request
curl -G https://api.virlo.ai/v1/satellite/hashtags/tiktok/cleaninghacks \
-H "Authorization: Bearer YOUR_API_KEY" \
-d trend_analysis=true
Response
{
"data": {
"job_id": "0bebf4eb-01a0-4b3c-b880-3c36fe32c4ea",
"status": "processing"
}
}
Check lookup status
Free to call. status is processing, then completed (with result) or failed (with error, refunded in full). Keep checking until you see one of those.
This check works for 24 hours, then returns 404. The same ID still opens the saved run.
Rather not poll? The satellite.lookup.completed webhook, with type: "hashtag_lookup", fires on success or failure. A free repeat sends no webhook, so read its result right away.
What's in the result
- Name
run_id- Type
- string
- Description
Same value as your
job_id. Reopens this result for free.
- Name
stats- Type
- object
- Description
See Stats.
- Name
trends- Type
- object
- Description
See Trend analysis.
analyzed: falseif you didn't ask for it.
- Name
videos- Type
- array
- Description
The collected videos, in your
sortorder.
- Name
request- Type
- object
- Description
Your settings as applied.
max_videosshows the real target:300or500on bigger lookups.
Request
curl https://api.virlo.ai/v1/satellite/hashtags/status/0bebf4eb-01a0-4b3c-b880-3c36fe32c4ea \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"data": {
"status": "completed",
"result": {
"run_id": "0bebf4eb-01a0-4b3c-b880-3c36fe32c4ea",
"request": {
"hashtag": "cleaninghacks",
"platform": "tiktok",
"trend_analysis": true,
"max_videos": 300,
"sort": "top",
"depth": "standard"
},
"hashtag": {
"name": "cleaninghacks",
"platform": "tiktok",
"page_url": "https://www.tiktok.com/tag/cleaninghacks"
},
"data_captured_at": "2026-09-24T17:48:57.782Z",
"credits_charged": 100,
"stats": {
"videos_analyzed": 300,
"views": { "total": 1529643491, "avg": 5098812, "median": 2628772, "max": 36788449, "min": 1011 },
"engagement": {
"total_likes": 93695696, "total_comments": 440623, "total_shares": 4075438, "total_collects": 10542388,
"avg_likes": 312319, "avg_comments": 1469, "avg_shares": 13585, "avg_collects": 35141,
"engagement_rate": 0.0711
},
"velocity": {
"videos_per_week": [{ "iso_week": "2026-W38", "count": 8 }, { "iso_week": "2026-W39", "count": 14 }],
"last_4w_avg_videos_per_week": 7.5,
"prior_4w_avg_videos_per_week": 4.5,
"is_accelerating": true
},
"verified_creator_count": 36,
"verified_creator_pct": 0.12,
"duration_distribution": { "under_15s": 33, "between_15_30s": 64, "between_30_60s": 47, "over_60s": 110 },
"top_creators": [
{ "unique_id": "creator_a", "nickname": "Creator A", "is_verified": true, "follower_count": null, "video_count": 10, "total_views": 95651889, "avg_views": 9565189 }
],
"related_hashtags": [
{ "hashtag": "cleantok", "used_count": 172, "total_views": 820116970, "avg_views": 4768122 }
],
"top_sounds": [
{ "external_id": "7468711641658525713", "title": "SHAKE IT TO THE MAX (FLY) [REMIX]", "artist": "MOLIY & Shenseea & Skillibeng & Silent Addy", "is_original": false, "used_count": 2, "total_views": 38805562, "avg_views": 19402781 }
],
"top_video": { "id": "7171372479372365099", "...": "same fields as a videos[] item" }
},
"sample_quality": { "truncated_by_cap": true, "pages_fetched": 17, "note": "deep_corpus" },
"trends": {
"analyzed": true,
"status": "ok",
"summary": "The #cleaninghacks corpus reveals a strong and continuous interest in practical, satisfying, and motivational cleaning content.",
"trends": [
{
"name": "Quick Cleaning Hacks & Everyday Tips",
"description": "Short, practical videos demonstrating clever and easy cleaning solutions or organizational tips for daily household problems.",
"tactics": ["Present a common problem and a quick solution", "Target everyday household items or situations"],
"confidence": 0.92,
"video_count": 82,
"evidence_video_ids": ["6984134268918271237", "7099896027146177797", "..."],
"time_windows": [
{ "start_date": "2020-05-26", "end_date": "2026-09-04", "video_count": 82, "total_views": 494830450, "total_likes": 30599073, "total_comments": 130883, "total_shares": 1640360, "avg_views": 6034518, "description": "A continuous run of quick cleaning tips and life hacks from 2020 to 2026." }
],
"resurged": false,
"momentum": null
}
]
},
"videos": [
{
"id": "7171372479372365099",
"url": "https://www.tiktok.com/@creator_b/video/7171372479372365099",
"description": "Car retreading #fyp #carbeauty #cleaninghacks",
"publish_date": "2022-11-29T09:48:06.000Z",
"duration_seconds": 15,
"views": 36788449, "likes": 630082, "comments": 4351, "shares": 30904, "collects": 69181,
"hashtags": ["fyp", "carbeauty", "cleaninghacks"],
"is_duet": false,
"is_stitch": false,
"region": "US",
"author": { "unique_id": "creator_b", "nickname": "Creator B", "is_verified": false, "follower_count": null }
}
]
}
}
}
What each platform returns
Each platform shares different data, so compare hashtags within one platform.
| TikTok | YouTube | ||
|---|---|---|---|
| Where videos come from | The hashtag page, including photo slideshows (url contains /photo/) | The hashtag page, Shorts only | Public reels, 100 to 150 at most, even with trend analysis |
depth options | All three | All three | standard only |
views | Yes | Yes | 0 when Virlo couldn't look up that reel. Treat it as unknown. |
shares, collects (saves) | Yes | Always 0 | Always 0 |
duration_seconds | null for slideshows | Yes | Often null |
author.unique_id | Handle | Channel ID (starts with UC) | Handle |
author.follower_count | null (use a Creator lookup) | Channel subscribers | null |
top_sounds | Yes | Yes | Usually empty |
is_duet, is_stitch, region | Yes | false, null | false, null |
Stats
Plain math over your sample, with no AI.
- Name
views- Type
- object
- Description
total,avg,median,max, andmin.
- Name
engagement- Type
- object
- Description
Totals and averages of likes, comments, shares, and collects (saves).
engagement_rateis their sum divided by total views (0.0711means 7.11%). YouTube and Instagram have no shares or saves, so don't compare it across platforms.
- Name
velocity- Type
- object
- Description
How many of the sampled videos were posted each week. It reflects the sample, not every post under the hashtag.
videos_per_week: counts by calendar week, for up to the 26 most recent weeks that have videos. Empty weeks are left out.last_4w_avg_videos_per_week,prior_4w_avg_videos_per_week: the average of the latest 4 of those weeks (or fewer, if that's all), and of up to 4 weeks before them (0if none).is_accelerating:truewhen the last-4-week average beats the prior one by 15% or more. Alsotruewith 4 or fewer weeks of videos: ignore it then.
- Name
top_creators- Type
- array
- Description
Up to 10 creators with the most views in the sample.
- Name
related_hashtags- Type
- array
- Description
Up to 20 other hashtags on the same videos, ranked by total views, leaving out the one you looked up.
used_countis how many videos use it.
- Name
top_sounds- Type
- array
- Description
Up to 10 sounds with the most views.
is_originalmeans the creator's own audio.
- Name
verified_creator_count / verified_creator_pct- Type
- number
- Description
How many videos come from verified accounts, and that share. It counts videos, not separate creators.
- Name
duration_distribution- Type
- object
- Description
Videos per length band. Videos of unknown length aren't counted, so the bands can add up to less than
videos_analyzed.
Trend analysis
Filled in only with trend_analysis=true. An AI model reads each video's caption, hashtags, and numbers (it doesn't watch the videos). It groups them into named creative patterns, with tactics a creator can copy. It reads up to 240 videos, most viewed first, so depth=full adds videos to the stats but not to the trends.
Each trend's time_windows are the date ranges when its videos were posted. resurged means the pattern faded and came back, and momentum compares views in the last two windows. A pattern that never paused has one window, resurged: false, and momentum: null.
status is ok, skipped (you didn't ask), or insufficient_corpus (under 10 videos, $0.50 refunded). If the AI step errors, you still get ok with an empty trends list, and the $0.50 is refunded too.
Full field reference
- Name
confidence- Type
- number
- Description
The AI's own score, from 0 to 1, for how clear the pattern is.
- Name
evidence_video_ids- Type
- string[]
- Description
The videos that show the pattern. All of them are in
videos[].
- Name
time_windows- Type
- array
- Description
A sample covering under 14 days gets one window per trend.
- Name
momentum- Type
- string | null
- Description
stronger(average views 15% or more higher than the window before),weaker(15% or more lower), orsimilar.
A trend that came back after a gap:
A trend that resurged
{
"name": "Before/after speed-cleans",
"description": "Sub-30s transformations that hard-cut from mess to spotless on the beat.",
"tactics": ["open on the worst angle of the mess", "single hard cut to the reveal", "text overlay with the time it took"],
"confidence": 0.84,
"video_count": 78,
"evidence_video_ids": ["7412345678901234567", "7419876543210987654", "..."],
"time_windows": [
{ "start_date": "2026-06-14", "end_date": "2026-06-30", "video_count": 31, "total_views": 44000000, "total_likes": 3600000, "total_comments": 21000, "total_shares": 96000, "avg_views": 1419355, "description": "First wave, mostly small-account transformations." },
{ "start_date": "2026-07-18", "end_date": "2026-07-31", "video_count": 47, "total_views": 88000000, "total_likes": 7400000, "total_comments": 43000, "total_shares": 214000, "avg_views": 1872340, "description": "Came back with larger creators joining the format." }
],
"resurged": true,
"momentum": "stronger"
}
Re-read past runs
Every paid lookup is saved as its own run that never expires. Reopening it is free:
GET /v1/satellite/runs/:run_id: the full saved result, underresult.GET /v1/satellite/runs?type=hashtag_lookup&platform=tiktok: your past hashtag lookups.GET /v1/satellite/runs/:run_id/videos?limit=50&offset=0: the videos, a page at a time (limitup to 200, default 25).
A newer lookup of the same hashtag gets a new run_id. That happens after 6 hours, or sooner if you change sort, add trends, or ask for a bigger depth. The older run stays as it was, even if the new lookup fails.
Errors
These happen before a lookup starts, so they are never charged.
- Name
400 Bad Request- Description
Unknown platform. Empty hashtag, over 100 characters, or with a space or a
%other than%23.depth=deeporfullon Instagram. Unknowndepthorsortvalue,max_videosoutside 1 to 100, or an unknown query parameter.
- Name
401 Unauthorized- Description
API key missing (
missing_api_key), or wrong or revoked (invalid_api_key). See Authentication.
- Name
402 Payment Required- Description
Balance below the full price, even for a repeat that would be free. Under $0.50, the error always says $0.50.
- Name
404 Not Found- Description
Status check only: wrong ID, another lookup type's ID, or over 24 hours old.
- Name
429 Too Many Requests- Description
Your key's daily request limit is used up. Lookups have no per-minute or hourly limit. See Rate limits.

