Deep-dive lookup
Creator lookup
See how any creator on TikTok, YouTube Shorts, or Instagram performs: their stats, top hashtags, standout videos, and who comments on their posts.
- What it does
- Sums up one creator (or up to 25 at once): profile, stats, top hashtags, and the videos that beat their usual views.
- You send
- A platform (
tiktok,youtube, orinstagram), the creator's handle, and any add-ons you want. - You get back
- A job ID right away. You check that job every 15 seconds or so (this is called polling) until the result is ready.
- Cost
- $0.50 per creator, up to $1.75 with every add-on. Repeating it within 6 hours is free if the earlier lookup had every option you ask for.
- How long
- Usually 20 to 40 seconds. Bigger lookups and add-ons can take a few minutes.
Every address here starts with https://api.virlo.ai/v1/satellite/. Successful answers sit inside a data field (the job ID is data.job_id). Error messages don't.
What it costs
You pay when you start a lookup. Checking status and re-reading saved results are free.
| What you ask for | Price |
|---|---|
| Creator lookup | $0.50 |
Trend analysis (trend_analysis=true) | + $0.50 |
Data Intelligence, an AI breakdown of every video (data_intelligence=true) | + $0.25 |
Audience breakdown (audience_demographics and/or audience_geography) | + $0.50 once, even for both. Free if Virlo measured this creator's audience in the last 30 days. |
| Every add-on at once | Up to $1.75 |
| The same creator again within 6 hours | Free if the earlier lookup had every option you ask for. Batches too. |
| Batch lookup | $0.50 per creator that starts a lookup, plus any audience fees |
- Failed lookups are refunded in full, such as a handle that doesn't exist, a private account, a YouTube channel with no Shorts, or a lookup that stalls and is closed out as failed. The trend fee is refunded when no trends come out, the audience fee when no new snapshot was needed, and a creator lookup's Data Intelligence fee when there were no posts to enrich or its analysis failed. The refund comes later, as
credits_refundedon the status check and on the saved run. - The exact charge is in the response headers:
X-Costin dollars andX-Credits-Usedin credits (1 credit = $0.01, so $0.50 = 50 credits).
Start a creator lookup
Starts a lookup and returns a job ID in about a second, while the work runs in the background. Each new lookup is charged, even though it's a GET request.
Repeated within 6 hours by anyone on your team? You get the same job ID back, already completed and marked "cached": true. This only happens when the earlier lookup had every add-on and include you ask for, at least as many videos (max_videos), and the same outlier_threshold. Otherwise a new paid lookup runs. A cached repeat costs nothing, but your balance must still cover the normal price.
Path parameters
- Name
platform- Type
- string
- Required
- *
- Description
tiktok,youtube, orinstagram, in lowercase. YouTube reads Shorts only, so a channel with only long videos fails (and is refunded). Instagram reads the whole feed, but photos and carousels have no views, so view stats and outliers use only the videos.
- Name
username- Type
- string
- Required
- *
- Description
The handle, with or without the
@. It can't contain/,?,#,%, or spaces.
Query parameters
All optional. To turn an option on, send lowercase true. True, 1, or yes count as off, with no error. A misspelled option name returns 400 and isn't billed.
- Name
include- Type
- string
- Description
videos(the video list),outliers(videos that beat the creator's usual views), or both, comma-separated. Without it you get the profile, stats, and hashtags.
- Name
max_videos- Type
- integer
- Description
How many recent videos to analyze, from 1 to 100 (default
20). It doesn't change the price.
- Name
outlier_threshold- Type
- number
- Description
A video is an outlier when its views are more than this many times the creator's median views. Default
2(double), minimum0.1. Use3or5to see only the biggest hits.
- Name
cross_links- Type
- boolean
- Description
Find the creator's profiles on other platforms (YouTube, TikTok, Instagram, X, Spotify). Free.
- Name
trend_analysis- Type
- boolean
- Description
+$0.50. The formats the creator keeps repeating. Reads up to 300 videos and ignores
max_videos. Includes the video list. See Creator trend analysis.
Request
curl -G https://api.virlo.ai/v1/satellite/creator/tiktok/khaby.lame \
-H "Authorization: Bearer YOUR_API_KEY" \
-d include=videos,outliers \
-d cross_links=true \
-d max_videos=30 \
-d outlier_threshold=2.5
Response
{
"data": {
"job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "processing"
}
}
Creator trend analysis
Add trend_analysis=true to see the formats a creator keeps repeating, when they ran, and whether each is growing or fading. It adds a trends object to the result. Without it, there's no trends key.
summarysums up the creator's playbook in a sentence or two.result.trends.trendslists each format:name,description,tactics,confidence(0 to 1),video_count,evidence_video_ids(matchingidinvideos), andtime_windows(the date ranges it ran, with view and engagement totals).resurgedistruewhen the creator dropped a format and brought it back.momentumcompares average views in the latest date range with the one before:stronger(15% or more up),weaker(15% or more down), orsimilar. It'snullif the format ran only once.statusisok, orinsufficient_corpuswhen fewer than 10 videos could be read. The trend fee is refunded forinsufficient_corpus.- An empty list with
status: "ok"means no clear pattern. Ifsummaryis also empty and the result carriescredits_refunded, the analysis failed and the trend fee was refunded. You can run it again after the 6-hour window. - Ignore
analyzed. It only echoes that you asked for trends.
Full example: Creator lookup add-ons.
Check lookup status
Shows the lookup's progress, then the full result once it's done. Check every 15 seconds, or whatever retry_after_seconds says. It's free.
When is it done?
- Basic lookup: stop when
statusiscompletedorfailed. - With an audience add-on: stop when
finalizedistrue. A failed snapshot never makes ittrue, so if an audience field still readsprocessingafter 15 minutes, check its job atpending_jobs[].poll_url. It endscompletedorfailed, and a failed snapshot is refunded. - With
data_intelligence: the AI breakdown isn't in this response. Aftercompleted, check the saved run untilintelligence_statusisready,failed, orskipped, usually a few minutes.
Most take 20 to 40 seconds, more with a high max_videos. Trend analysis and busy periods can take a few minutes, so don't hard-code a timeout. status still processing after 15 minutes? It's delayed, not lost. A stuck lookup is marked failed on its saved run within a few hours, with no automatic refund. For help sooner, email [email protected] with the job ID.
This check works for 24 hours, then returns 404. The result stays in the saved run under the same ID.
Path parameters
- Name
job_id- Type
- string
- Required
- *
- Description
The job ID from the start call.
What you get back
- Name
status- Type
- string
- Description
processing,completed, orfailed.
- Name
result- Type
- object
- Description
The creator data, once
completed.
- Name
error- Type
- string
- Description
Why the lookup failed, if it did.
- Name
credits_refunded- Type
- integer
- Description
Only on a failed lookup that was refunded: the credits paid back (1 credit = $0.01).
- Name
pending_jobs- Type
- array
- Description
Work still running after the main result: here, only a new audience snapshot. See pending_jobs.
- Name
finalized- Type
- boolean
- Description
trueonce the lookup and any audience snapshot are done. A failed snapshot keeps itfalse(see above).
What's in result
- Name
username, platform- Type
- string
- Description
What you looked up.
- Name
profile- Type
- object
- Description
Followers, bio, avatar, profile link, and content category. Missing if it couldn't be fetched.
- Name
stats- Type
- object
- Description
Averages across the analyzed videos: views, median views, likes, comments, engagement rate, and how often they post.
- Name
hashtags- Type
- object[]
- Description
The top 10 hashtags by total views.
- Name
content_tags- Type
- string[]
- Description
2 to 5 AI-written tags for the creator's niche, like
["asmr", "budget-meals"].
Full field reference
Some fields exist only on some platforms. A missing value can come back as null, as 0, or not at all, so handle all three.
profile
- Name
followers- Type
- number
- Description
Followers or subscribers.
- Name
following- Type
- number
- Description
Accounts they follow. Always
0on YouTube.
- Name
avatar_url, url, description- Type
- string | null
- Description
Profile picture, profile link, and bio.
- Name
is_verified- Type
- boolean | null
- Description
Verified badge. Often
nullon YouTube.
- Name
total_videos, total_posts- Type
- number | null
- Description
Totals on the account, when the platform reports them. On TikTok they're equal.
stats
- Name
videos_analyzed- Type
- number
- Description
Posts with a view count that went into the view math.
- Name
posts_analyzed- Type
- number
- Description
All posts analyzed. Differs only on Instagram, where photos and carousels have no views.
- Name
post_mix- Type
- object
- Description
Instagram mixed feeds only: how many
video,carousel, andimageposts were analyzed.
- Name
avg_views, median_views- Type
- number
- Description
Average and median (middle) views per video.
- Name
avg_likes, avg_comments- Type
- number
- Description
Average likes and comments per post.
- Name
engagement_rate- Type
- number
- Description
Likes plus comments, divided by views, rounded to 2 decimals (
0.07= 7%). Don't compare it across platforms.
- Name
top_performing_views, lowest_performing_views- Type
- number
- Description
Highest and lowest views among the analyzed videos.
- Name
posting_frequency_days- Type
- number
- Description
Average days between posts. Needs at least 2 dated posts.
hashtags
Each entry has hashtag (lowercase, no #), total_views, avg_views, avg_likes, avg_comments, and used_count. They come from titles and descriptions.
videos
Each video has id, title, description, views, likes, comments, publish_date, url, hashtags, thumbnail_url, is_duet, and is_stitch (always false off TikTok). Some keys only exist on some platforms:
shares,bookmarks, andis_pinned: TikTok only.duration(seconds): TikTok and Instagram. Missing on YouTube.is_videoandcontent_type(reel,video,carousel, orimage): Instagram only. Photos and carousels showviews: 0.publishDateandisPinnedare old duplicates. Usepublish_dateandis_pinned.
outliers
threshold_multiplier is the threshold used. outlier_videos lists every video above it, sorted by weighted_score, highest first. Each has all the video fields, plus:
- Name
outlier_ratio- Type
- number
- Description
Views divided by the creator's median views.
6.56means 6.56 times their usual.
- Name
weighted_score- Type
- number
- Description
ln(outlier_ratio) × ln(median_views), always present. The same jump scores higher for a creator with bigger usual views, so use it to compare across creators.
cross_links
- Name
discovered- Type
- object[]
- Description
Confident matches only, so it can be empty. Each is
{ platform, username, url, source }.platformisyoutube,tiktok,instagram,twitter, orspotify.sourceis where it was found:bio_link,bio_text,linktree,spotify_api, orai_search.
- Name
sources_checked- Type
- string[]
- Description
Where Virlo searched. Includes
timeoutif the search hit its 8-second limit. You still get the links found so far.
- Name
bio_link_url- Type
- string
- Description
The link-in-bio page checked, if any. May be missing.
Audience snapshot
Both audience fields read one snapshot, built from the creator's commenters (on TikTok, followers too when comments are thin). Each has snapshot_id, sample_size (people analyzed), confidence_level (low, medium, or high), confidence_per_signal, data_source, signal_breakdown, and model_version.
audience_demographicsaddssnapshot_at,evidence_summary(a short written summary), andage_distribution,gender_distribution, andlanguage_distribution. Shares add up to about 1 (0.46= 46%).audience_geographyaddscountry_distributionandcity_distribution: lists of{ code, name, pct, confidence }, largest first. The last entry groups places with only one person,{ name: "Other (N countries)", pct }(orOther (N cities)), with nocodeorconfidence.data_source: "profile_only"is a guess from the creator's own profile: always low confidence, no age or gender, and always refunded. See Audience data for every source.
Request
curl https://api.virlo.ai/v1/satellite/creator/status/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"data": {
"status": "completed",
"result": {
"username": "khaby.lame",
"platform": "tiktok",
"stats": {
"videos_analyzed": 30,
"posts_analyzed": 30,
"avg_views": 45000000,
"median_views": 32000000,
"avg_likes": 3200000,
"avg_comments": 18000,
"engagement_rate": 0.07,
"top_performing_views": 210000000,
"lowest_performing_views": 5000000,
"posting_frequency_days": 3.2
},
"hashtags": [
{ "hashtag": "comedy", "total_views": 890000000, "avg_views": 59333333, "avg_likes": 4100000, "avg_comments": 22000, "used_count": 15 }
],
"content_tags": ["silent-comedy", "life-hacks", "reaction"],
"profile": {
"followers": 162400000,
"following": 78,
"url": "https://www.tiktok.com/@khaby.lame",
"is_verified": true,
"total_videos": 1203,
"total_posts": 1203,
"total_likes": 2400000000,
"category": "comedy",
"bio_link": null,
"country": null
},
"videos": [
{
"id": "7234567890123456789",
"title": "When people overcomplicate things...",
"views": 85000000,
"likes": 6200000,
"comments": 31000,
"shares": 120000,
"bookmarks": 95000,
"duration": 21,
"publish_date": "2025-03-15T12:00:00.000Z",
"url": "https://www.tiktok.com/@khaby.lame/video/7234567890123456789",
"hashtags": ["comedy", "reaction"],
"is_pinned": false,
"is_duet": false,
"is_stitch": true
}
],
"outliers": {
"threshold_multiplier": 2.5,
"outlier_videos": [
{
"id": "7229876543210987654",
"title": "Why make it hard?",
"views": 210000000,
"url": "https://www.tiktok.com/@khaby.lame/video/7229876543210987654",
"outlier_ratio": 6.56,
"weighted_score": 32.51
}
]
},
"cross_links": {
"discovered": [
{ "platform": "youtube", "username": "khaby.lame", "url": "https://www.youtube.com/@khaby.lame", "source": "bio_link" }
],
"sources_checked": ["structured_fields", "bio_text", "linktree", "spotify_api", "ai_search"]
},
"run_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"credits_charged": 50
},
"pending_jobs": [],
"finalized": true
}
}
Re-read past runs
Every lookup is saved as a "run" that you can read again for free, with no 24-hour limit. The run ID is the job ID you got at the start. Sound lookups, hashtag lookups, and video outlier checks are saved the same way. A run shows the numbers from when it ran. For fresh numbers, start a new lookup, which is billed.
Every paid lookup is saved as its own run, with a new run ID. Older runs are never overwritten. A repeat within the 6-hour free window returns the existing run instead.
Get one run
GET /v1/satellite/runs/:run_id returns the saved run.
Full field reference
- Name
run_id- Type
- string
- Description
Same as the job ID.
- Name
type- Type
- string
- Description
creator_lookup,sound_lookup,hashtag_lookup, orvideo_outlier.
- Name
platform, status- Type
- string
- Description
The platform, and
processing,completed, orfailed.
- Name
subject- Type
- string | null
- Description
The handle, sound ID, or hashtag.
nullfor video outliers.
- Name
created_at- Type
- string
- Description
When the run was created.
List your runs
GET /v1/satellite/runs lists your team's runs, newest first. Each paid lookup is its own row, so a creator you looked up twice appears twice. Free.
- Name
type- Type
- string
- Description
creator_lookup,sound_lookup,hashtag_lookup, orvideo_outlier. Creators from a batch show up ascreator_lookup.
- Name
platform- Type
- string
- Description
tiktok,youtube, orinstagram.
- Name
limit- Type
- integer
- Description
Runs per page, from 1. Default
25. Anything above 100 counts as 100.
- Name
offset- Type
- integer
- Description
How many runs to skip. Default
0.
Each row has run_id, type, platform, status, subject, created_at, completed_at, and credits_used. The response also has total, limit, and offset.
Page through a run's videos
GET /v1/satellite/runs/:run_id/videos returns a run's videos a page at a time. Free.
- Name
limit- Type
- integer
- Description
From 1 to 200, default
25. Above 200 returns400.
- Name
offset- Type
- integer
- Description
How many videos to skip. Default
0.
- Name
sort- Type
- string
- Description
recentorpopular(views, likes, comments, shares, and saves combined). Leave it out to keep the saved order.
- Name
content_type- Type
- string
- Description
all(default),video, orslideshow(photo carousels). On TikTok,slideshowonly finds carousels ondata_intelligencelookups, andvideocurrently returns carousels too.
The response has videos, total (after the content_type filter), limit, offset, sort, and content_type.
Request
curl https://api.virlo.ai/v1/satellite/runs/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"data": {
"run_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"type": "creator_lookup",
"platform": "tiktok",
"status": "completed",
"subject": "khaby.lame",
"created_at": "2026-09-24T17:23:37.665014+00:00",
"completed_at": "2026-09-24T17:24:05.374+00:00",
"credits_used": null,
"request": {
"context": "which hooks drive their most-viewed videos",
"max_videos": 30,
"data_intelligence": true,
"trend_analysis": false
},
"result": {
"username": "khaby.lame",
"platform": "tiktok",
"videos": [
{
"id": "7234567890123456789",
"views": 85000000,
"intelligence_status": "ready",
"intelligence": {
"hook_type": "relatable_scenario",
"content_format": "reaction",
"is_sponsored": false,
"brand_safety_tier": "safe"
}
}
],
"run_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"credits_charged": 50
},
"analysis": {
"key_insight": "Silent reactions to overcomplicated life hacks drive his biggest videos.",
"what_works": [
{
"insight": "Reaction videos that undo a needlessly complex hack beat his median by 6x.",
"evidence_video_ids": ["7229876543210987654"]
}
],
"winning_hooks": ["Relatable scenario: someone overcomplicating a simple task"],
"best_formats": "Short silent reactions under 25 seconds.",
"top_subjects": ["Life hacks", "Everyday tasks"],
"relevance": "Lead with the overcomplicated version, then the simple fix.",
"degraded": false
},
"intelligence_status": "ready",
"error": null
}
}
Batch creator lookup
Starts lookups for up to 25 creators in one request. You get a batch ID plus a job ID for each creator, and each creator gets the same result as a single lookup. The differences:
- No trend analysis or Data Intelligence. Sending
trend_analysis,data_intelligence,context, orslideshow_sortreturns400. - Free 6-hour repeats. A creator your team looked up in the last 6 hours, with at least these options, comes back
completedat once, free, with the saved result (samejob_id). - No 5-per-minute limit. Batches don't count toward the limit on single lookups.
Your balance must cover the whole batch, or it's rejected with 402 and nothing runs. A creator whose lookup fails, such as a handle that doesn't exist, is refunded like a single lookup. If Virlo can't start one creator's lookup (a problem on Virlo's side), it shows "status": "failed" with an empty job_id, and you aren't charged for it, audience fee included.
Body parameters
- Name
creators- Type
- array
- Required
- *
- Description
1 to 25 entries like
{ "platform": "tiktok", "username": "khaby.lame" }.
Optional: include, max_videos, outlier_threshold, cross_links, audience_demographics, audience_geography, and freshness_days. They work as on a single lookup and apply to every creator.
Request
curl -X POST https://api.virlo.ai/v1/satellite/creators/batch \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"creators": [
{ "platform": "tiktok", "username": "khaby.lame" },
{ "platform": "youtube", "username": "mkbhd" },
{ "platform": "instagram", "username": "therock" }
],
"include": "videos,outliers",
"cross_links": true,
"max_videos": 30
}'
Response
{
"data": {
"batch_id": "b7e1c2d3-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
"status": "partial",
"total": 3,
"completed": 1,
"failed": 0,
"processing": 2,
"creators": [
{ "platform": "tiktok", "username": "khaby.lame", "job_id": "3f2a9c1e-6b7d-4e8f-9a0b-1c2d3e4f5a6b", "status": "processing" },
{ "platform": "youtube", "username": "mkbhd", "job_id": "8c7d6e5f-4a3b-4c2d-9e1f-0a9b8c7d6e5f", "status": "completed" },
{ "platform": "instagram", "username": "therock", "job_id": "d4c3b2a1-9f8e-4d7c-8b6a-5f4e3d2c1b0a", "status": "processing" }
]
}
}
Check batch status
Shows progress only: one status per creator, plus totals. For each creator's data, check its job_id with Check lookup status. Free, for 24 hours.
processing: nothing has finished yet.partial: some creators are done (or failed) and some are still running.completed: nothing is still running. Some creators may have failed, so check thefailedcount.failed: every creator failed.
A creator can also show expired once its 24-hour record is gone. It counts as failed, but if it finished, its result is still in its saved run (its job_id is the run ID). The batch itself isn't saved, and it doesn't show refunds: check each creator's job for credits_refunded.
Path parameters
- Name
batch_id- Type
- string
- Required
- *
- Description
The batch ID from the batch call.
Request
curl https://api.virlo.ai/v1/satellite/creators/batch/b7e1c2d3-4f5a-4b6c-8d7e-9f0a1b2c3d4e \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"data": {
"batch_id": "b7e1c2d3-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
"status": "completed",
"total": 3,
"completed": 2,
"failed": 1,
"processing": 0,
"creators": [
{ "platform": "tiktok", "username": "khaby.lame", "job_id": "3f2a9c1e-6b7d-4e8f-9a0b-1c2d3e4f5a6b", "status": "completed" },
{ "platform": "youtube", "username": "mkbhd", "job_id": "8c7d6e5f-4a3b-4c2d-9e1f-0a9b8c7d6e5f", "status": "completed" },
{ "platform": "instagram", "username": "therock", "job_id": "d4c3b2a1-9f8e-4d7c-8b6a-5f4e3d2c1b0a", "status": "failed" }
]
}
}
Errors
- Name
400 Bad Request- Description
Something in the request is wrong. Not billed.
- Lookup: an unknown platform (it must be lowercase), a handle with
/,?,#,%, or spaces,max_videosoutside 1 to 100,outlier_thresholdbelow 0.1,freshness_daysoutside 0 to 365,contextover 600 characters, or an unknown parameter. - Batch: no creators, more than 25, or an option batches don't support.
- Run endpoints: a run ID that isn't a valid ID, a
limitout of range, or an unknowntype,sort, orcontent_type.
- Lookup: an unknown platform (it must be lowercase), a handle with
- Name
401 Unauthorized- Description
The API key is missing or invalid. Send it as
Authorization: Bearer YOUR_API_KEY.
- Name
402 Payment Required- Description
Your balance is too low. The message says how much is needed. Add funds at dev.virlo.ai/dashboard/billing. See Billing and pricing.
- Name
404 Not Found- Description
The job ID is unknown or older than 24 hours (read the saved run instead), the batch or run ID doesn't exist, or the username is missing from the path.
- Name
429 Too Many Requests- Description
Too many lookups started too fast. Single lookups allow 5 per minute, 100 per hour, and 1,000 per day, and rejected
400requests count too. Status checks, batches, and run reads use the general daily limit. Waitretry_afterseconds. Ignore the old duplicates (resetAt,resetAtFormatted,retryAfter) and use the underscore names. See Rate limits.
A creator that can't be found isn't an error response. The start call succeeds and is billed $0.50. The status check then returns failed, and the charge is refunded. With an audience add-on, the lookup doesn't fail: it completes with empty stats and just the audience data.
A failed status carries error_code, so you can tell a typo from a temporary problem. Branch on error_code, not on the error text, which can change.
error_code | What it means | What to do |
|---|---|---|
creator_not_found | There is no account under this handle | Fix the handle |
no_public_posts | The account exists but has no posts to analyze (on YouTube, no Shorts) | Nothing to retry |
creator_unavailable | The profile could not be read: private, age-restricted or region-blocked | Nothing to retry |
provider_unavailable | The profile shows posts, but they could not be loaded right now | Try again in a few minutes |
lookup_failed | Any other error | Try again; contact us if it keeps failing |
New codes may be added, so treat an unknown one like lookup_failed.
Other lookups
The same start, check, and re-read flow works for:
- Sound lookup: the TikTok videos or Instagram reels using a sound, with top creators, hashtags, and how fast it's spreading. $0.50, or $1.00 with trend analysis. No YouTube.
- Hashtag lookup: videos posted under a hashtag on TikTok, Instagram, or YouTube Shorts, with top creators, related hashtags, and top sounds. $0.50, up to $2.50 with
depth=fulland trend analysis. - Video outlier check: whether one video beat its creator's usual views. $0.50 per check.

