Satellite - Creator Lookup
Look up any creator by platform and username. This endpoint uses an async polling pattern: submit a request, receive a job ID, then poll a status endpoint for results. Each creator lookup costs $0.50 per request (deducted from your prepaid balance).
All Satellite V1 endpoints use the base URL https://api.virlo.ai/v1/satellite. All parameter names and response fields use snake_case. All responses are wrapped in a { "data": { ... } } envelope.
Start Creator Lookup
Queue a creator lookup job. The endpoint returns immediately with a job_id that you use to poll for results. All heavy work (fetching videos, computing stats) happens in the background.
Path parameters
- Name
platform- Type
- string
- Required
- *
- Description
Social media platform. One of:
youtube,tiktok,instagram
- Name
username- Type
- string
- Required
- *
- Description
Creator's handle (with or without leading
@). Example:mkbhd,khaby.lame,therock
Query parameters
- Name
include- Type
- string
- Description
Comma-separated optional sections to include in the response:
videos,outliers. Example:include=videos,outliers
- Name
cross_links- Type
- boolean
- Description
Enable cross-platform link discovery. Finds the same creator on other platforms (YouTube, TikTok, Instagram, Twitter/X, Spotify). Default
false.
- Name
max_videos- Type
- integer
- Description
Number of videos to fetch and analyze (1-100). Default is
20. More videos = better stats but slower response.
- Name
outlier_threshold- Type
- number
- Description
Multiplier for outlier detection. A video is an outlier when
views > median_views * threshold. Default is2.0. Only relevant wheninclude=outliers.
- Name
audience_demographics- Type
- boolean
- Description
Include engaged-audience age + gender + language distributions in the response — derived from the creator's commenters rather than the raw follower base. Default
false. Whentrue, a cached snapshot is used if it's fresher thanfreshness_days; otherwise a fresh collection job is queued and the response contains aprocessingpointer instead of the snapshot. Adds a flat $0.50 per fresh snapshot on any platform. Cache hits cost nothing. Auto-refunded when the snapshot lands on theprofile_onlyfallback OR failsINSUFFICIENT_SAMPLE.
- Name
audience_geography- Type
- boolean
- Description
Include engaged-audience country + city distributions. Default
false. Shares cost withaudience_demographics— passing both flags on the same call does not double-charge.
- Name
freshness_days- Type
- integer
- Description
Max age of an acceptable cached audience snapshot, in days. Default
30. Only relevant whenaudience_demographicsoraudience_geographyistrue.
- Name
trend_analysis- Type
- boolean
- Description
Run AI trend detection over this creator's body of work. Default
false. Whentrue: forces a deep fetch (max_videosis floored to 100), implicitly includes thevideos[]payload, and adds an extra $0.50 surcharge on top of the $0.50 base. Returns atrendsblock on the completed response with a corpussummaryplus per-trendtime_windows[],resurged,momentum, andevidence_video_ids(which map back to thevideos[]array in the same response). Trends are persisted with the run — re-reading viaGET /v1/satellite/runs/:run_idis free. See the full reference at Creator Trend Analysis →.
Request
curl -G https://api.virlo.ai/v1/satellite/creator/tiktok/khaby.lame \
-H "Authorization: Bearer {token}" \
-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"
}
}
Poll Lookup Status
Poll for the results of a creator lookup job. Returns processing while the job is running, and the full creator data when completed.
Path parameters
- Name
job_id- Type
- string
- Required
- *
- Description
The job ID returned from the start endpoint.
Response fields (when completed)
The result object contains the full creator data:
- Name
username- Type
- string
- Description
The looked-up username.
- Name
platform- Type
- string
- Description
The platform queried.
- Name
profile- Type
- CreatorProfile
- Description
Creator's profile data. Omitted if the profile API call fails.
- Name
stats- Type
- CreatorStats
- Description
Computed statistics from analyzed videos.
- Name
hashtags- Type
- HashtagStats[]
- Description
Top 10 hashtags by total views (descending).
- Name
content_tags- Type
- string[]
- Description
AI-generated content tags (e.g.
["asmr", "mukbang", "budget-meals"]). 2-5 tags per creator.
- Name
videos- Type
- CreatorVideo[]
- Description
Only present when
include=videoswas specified.
- Name
outliers- Type
- OutliersResponse
- Description
Only present when
include=outlierswas specified.
- Name
cross_links- Type
- CrossLinksResult
- Description
Only present when
cross_links=truewas specified. Contains discovered cross-platform social profiles for this creator.
- Name
audience_demographics- Type
- AudienceDemographics | { processing: true, job_id: string }
- Description
Only present when
audience_demographics=truewas specified. Returns the cached snapshot when one exists withinfreshness_days, otherwise returns aprocessingpointer with ajob_idyou can poll viaGET /v1/audience/snapshot/:job_id— the unified audience-job poll endpoint — or via the MCPcheck_job_statustool withjob_type: "audience"(nocreator_idrequired). Theaudience.snapshot.completedwebhook fires either way. See audience tracking docs for the full pipeline behaviour, fallback policy, and refund rules.
- Name
audience_geography- Type
- AudienceGeography | { processing: true, job_id: string }
- Description
Only present when
audience_geography=truewas specified. Same shape and behaviour asaudience_demographicsbut scoped to country + city distributions. When both flags are passed, the snapshot is collected once and projected into both blocks — no double charge.
AudienceDemographics
Returned in audience_demographics when a cached or fresh snapshot is available. Describes the creator's engaged audience — read it as "who's showing up in the replies," with a TikTok-only follower fallback when comments are sparse (see data_source below for the exact source mix).
- Name
snapshot_id- Type
- string
- Description
Unique snapshot identifier. Reuse it to deduplicate snapshots across calls.
- Name
snapshot_at- Type
- string
- Description
ISO 8601 timestamp of when the snapshot finished collecting.
- Name
sample_size- Type
- number
- Description
Number of distinct profiles that contributed signals to this snapshot.
- Name
age_distribution- Type
- Record<string, number>
- Description
Bucketed age distribution (e.g.
{ "18-24": 0.46, "25-34": 0.32, ... }). Values sum to ~1.0.
- Name
gender_distribution- Type
- Record<string, number>
- Description
{ "female": 0.55, "male": 0.45 }. Non-binary signals are bucketed underotherwhen present.
- Name
language_distribution- Type
- Record<string, number>
- Description
ISO 639-1 language code → share (e.g.
{ "en": 0.62, "it": 0.18 }).
- Name
confidence_per_signal- Type
- Record<string, number>
- Description
Per-dimension model confidence (
age,gender,country,city,language). Values in[0, 1]. Coarse aggregateconfidence_levelis preferred for at-a-glance gating.
- Name
confidence_level- Type
- 'low' | 'medium' | 'high'
- Description
Coarse aggregate signal quality.
lowsnapshots are safe to surface but should be flagged in UI. Snapshots that fall back to followers-only data are capped atmedium.
- Name
data_source- Type
- 'comments' | 'mixed' | 'followers' | 'comments_extended' | 'profile_only'
- Description
How the underlying sample was assembled, in roughly descending order of signal quality:
comments— derived from the creator's public commenters. The default and strongest path.comments_extended— same source, but the comment collection window was widened to reach the minimum sample size on lower-engagement creators (Instagram + YouTube path).mixed/followers— TikTok-only fallback that blends in (or relies entirely on) the public follower list when comments are too sparse.profile_only— last-resort hint synthesized from the creator's own declared profile (country, language, bio) when no audience signal could be harvested. Alwaysconfidence_level: 'low', age/gender are alwaysnull, and the snapshot is always refunded (not billed). Filter these out if you only want statistically-backed snapshots.
- Name
signal_breakdown- Type
- { comments: number, followers: number }
- Description
Counts of distinct sources behind
sample_size. Useful whendata_sourceismixedto see how the blend was weighted.
- Name
evidence_summary- Type
- string | null
- Description
Short natural-language summary of the audience composition, generated alongside the snapshot. Suitable for direct surfacing in dashboards.
- Name
model_version- Type
- string
- Description
Snapshot pipeline version (
v1,v1.3, ...). Use this for cache invalidation when consumers depend on a specific generation.
AudienceGeography
Returned in audience_geography. Shares snapshot_id, sample_size, confidence_per_signal, confidence_level, data_source, signal_breakdown, and model_version semantics with AudienceDemographics. Geography-specific fields:
- Name
country_distribution- Type
- CountryShare[]
- Description
Top countries by share. Each entry:
{ code: string, name: string, pct: number, confidence: number }. Pre-sorted descending bypct. Low-volume tail entries (those backed by fewer than 2 underlying commenter signals) are consolidated into a single trailing bucket{ name: "Other (N countries)", pct: <sum> }(nocodeorconfidence) so the head of the distribution stays readable on small samples.
- Name
city_distribution- Type
- CityShare[]
- Description
Top cities by share. Each entry:
{ code: string, name: string, pct: number, confidence: number }wherecodeis the parent country. Pre-sorted descending bypct. Long-tail consolidation matchescountry_distribution— singletons are rolled into a trailing{ name: "Other (N cities)", pct: <sum> }bucket.
CreatorProfile
Unified across all platforms. Fields unavailable for a given platform return null.
- Name
followers- Type
- number
- Description
Follower/subscriber count.
- Name
following- Type
- number
- Description
Following count (
0for YouTube).
- Name
avatar_url- Type
- string | null
- Description
Profile picture URL.
- Name
url- Type
- string
- Description
Full profile URL.
- Name
description- Type
- string | null
- Description
Bio/description.
- Name
is_verified- Type
- boolean | null
- Description
Verified badge status.
- Name
total_videos- Type
- number | null
- Description
Total video count on the account.
- Name
total_likes- Type
- number | null
- Description
Total likes received (TikTok only).
- Name
total_views- Type
- number | null
- Description
Total channel views (YouTube only).
- Name
total_posts- Type
- number | null
- Description
Total posts/media count (Instagram only).
- Name
category- Type
- string | null
- Description
Content category slug from the Virlo category registry (e.g.
comedy,gaming,beauty). AI-classified from video titles, hashtags, and creator bio. New categories are automatically created when existing ones don't fit. May benullif classification is unavailable.
Content Tags
In addition to the structured category, each lookup returns AI-generated content tags -- 2-5 lowercase, specific descriptors of the creator's content niche.
- Name
content_tags- Type
- string[]
- Description
AI-generated content tags (e.g.
["asmr", "mukbang", "budget-meals"]). More specific than category -- use for precise filtering and analytics. Only present on completed lookups.
CreatorStats
Computed from the fetched videos.
- Name
videos_analyzed- Type
- number
- Description
Number of videos used to compute stats.
- Name
avg_views- Type
- number
- Description
Mean view count.
- Name
median_views- Type
- number
- Description
Median view count.
- Name
avg_likes- Type
- number
- Description
Mean like count.
- Name
avg_comments- Type
- number
- Description
Mean comment count.
- Name
engagement_rate- Type
- number
- Description
(total_likes + total_comments) / total_views, rounded to 2 decimals.
- Name
top_performing_views- Type
- number
- Description
Highest view count among analyzed videos.
- Name
lowest_performing_views- Type
- number
- Description
Lowest view count among analyzed videos.
- Name
posting_frequency_days- Type
- number | undefined
- Description
Average days between posts. Only present if 2+ videos have publish dates.
HashtagStats
Top 10 hashtags sorted by total_views descending. Normalized to lowercase.
- Name
hashtag- Type
- string
- Description
The hashtag (lowercase, without
#).
- Name
total_views- Type
- number
- Description
Sum of views across all videos using this hashtag.
- Name
avg_views- Type
- number
- Description
Average views per video using this hashtag.
- Name
avg_likes- Type
- number
- Description
Average likes per video using this hashtag.
- Name
avg_comments- Type
- number
- Description
Average comments per video using this hashtag.
- Name
used_count- Type
- number
- Description
Number of videos that used this hashtag.
CreatorVideo
Returned in the videos array when include=videos.
- Name
id- Type
- string
- Description
Platform-specific video ID.
- Name
title- Type
- string
- Description
Video title or caption.
- Name
description- Type
- string
- Description
Video description.
- Name
views- Type
- number
- Description
View count.
- Name
likes- Type
- number
- Description
Like count.
- Name
comments- Type
- number
- Description
Comment count.
- Name
shares- Type
- number | null
- Description
Share count. Available on TikTok;
nullon other platforms.
- Name
bookmarks- Type
- number | null
- Description
Bookmark/save count. Available on TikTok;
nullon other platforms.
- Name
is_duet- Type
- boolean
- Description
Whether this video is a TikTok duet (side-by-side response to another video). Always
falsefor YouTube and Instagram.
- Name
is_stitch- Type
- boolean
- Description
Whether this video is a TikTok stitch (plays a clip from another video as a hook, then the creator's response). Always
falsefor YouTube and Instagram.
- Name
publishDate- Type
- string | null
- Description
ISO 8601 date string, or
nullif unavailable.
- Name
url- Type
- string
- Description
Direct URL to the video.
- Name
hashtags- Type
- string[]
- Description
Hashtags extracted from title/description.
OutliersResponse
Returned when include=outliers. Identifies which of the creator's own videos significantly outperform their median.
- Name
threshold_multiplier- Type
- number
- Description
The multiplier used (default
2.0, or theoutlier_thresholdquery param).
- Name
outlier_videos- Type
- ContentOutlier[]
- Description
Videos exceeding the threshold, sorted by
outlier_ratiodescending.
ContentOutlier
Same fields as CreatorVideo plus:
- Name
outlier_ratio- Type
- number
- Description
video_views / median_views, rounded to 2 decimals. E.g.,5.23means 5.23x the median.
- Name
weighted_score- Type
- number
- Description
Optional. Size-weighted outlier score (Virality Score) for the video; present when computed.
CrossLinksResult
Returned when cross_links=true. Discovers the same creator's profiles on other social platforms using a multi-tiered approach: structured bio links, link-in-bio page resolution (Linktree, Beacons, etc.), Spotify API search, and AI-powered web search as a fallback.
- Name
discovered- Type
- CrossPlatformLink[]
- Description
Array of discovered cross-platform profiles. Empty if none were found with high confidence.
- Name
bio_link_url- Type
- string | null
- Description
The link-in-bio URL detected in the creator's profile (e.g., a Linktree link), if any.
- Name
sources_checked- Type
- string[]
- Description
Which discovery methods were attempted. Possible values:
structured_fields,bio_text,linktree,spotify_api,ai_search.
CrossPlatformLink
A single discovered cross-platform profile.
- Name
platform- Type
- string
- Description
Target platform. One of:
youtube,tiktok,instagram,twitter,spotify.
- Name
username- Type
- string
- Description
Username/handle on the target platform.
- Name
url- Type
- string
- Description
Normalized profile URL on the target platform.
- Name
source- Type
- string
- Description
How this link was discovered. One of:
bio_link(from profile's structured link field),bio_text(URL found in bio/description text),linktree(extracted from a link-in-bio page),spotify_api(matched via Spotify's official API),ai_search(found via AI web search).
Request
curl https://api.virlo.ai/v1/satellite/creator/status/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"status": "processing"
}
}
Batch Creator Lookup
Submit multiple creator lookups in a single request. Returns a batch_id and per-creator job_ids. Each creator in the batch is processed independently -- poll individual job statuses for results.
Body parameters
- Name
creators- Type
- array
- Required
- *
- Description
Array of creator objects, each with
platformandusername. Max 25 per request.
- Name
include- Type
- string
- Description
Comma-separated sections to include:
videos,outliers. Applied to all lookups in the batch.
- Name
cross_links- Type
- boolean
- Description
Enable cross-platform link discovery for all creators in the batch. Default
false.
- Name
max_videos- Type
- integer
- Description
Videos per creator (1-100). Default
20.
- Name
outlier_threshold- Type
- number
- Description
Outlier detection multiplier. Default
2.0.
Request
curl -X POST https://api.virlo.ai/v1/satellite/creators/batch \
-H "Authorization: Bearer {token}" \
-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": "b1c2d3e4-f5g6-7890-hijk-lm1234567890",
"status": "processing",
"total": 3,
"completed": 0,
"failed": 0,
"processing": 3,
"creators": [
{
"platform": "tiktok",
"username": "khaby.lame",
"job_id": "a1b2c3d4-...",
"status": "processing"
},
{
"platform": "youtube",
"username": "mkbhd",
"job_id": "e5f6g7h8-...",
"status": "processing"
},
{
"platform": "instagram",
"username": "therock",
"job_id": "i9j0k1l2-...",
"status": "processing"
}
]
}
}
Poll Batch Status
Poll the aggregate status of a batch. Returns a batch-level status (processing, partial, completed, or failed) plus per-creator statuses. Batch results expire after 24 hours.
Path parameters
- Name
batch_id- Type
- string
- Required
- *
- Description
The batch ID returned from the batch lookup endpoint.
Each individual creator result can also be polled via the standard GET /v1/satellite/creator/status/:job_id endpoint using the per-creator job_id.
Request
curl https://api.virlo.ai/v1/satellite/creators/batch/b1c2d3e4-f5g6-7890-hijk-lm1234567890 \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"batch_id": "b1c2d3e4-f5g6-7890-hijk-lm1234567890",
"status": "partial",
"total": 3,
"completed": 2,
"failed": 0,
"processing": 1,
"creators": [
{
"platform": "tiktok",
"username": "khaby.lame",
"job_id": "a1b2c3d4-...",
"status": "completed"
},
{
"platform": "youtube",
"username": "mkbhd",
"job_id": "e5f6g7h8-...",
"status": "completed"
},
{
"platform": "instagram",
"username": "therock",
"job_id": "i9j0k1l2-...",
"status": "processing"
}
]
}
}
Error responses
The Satellite Creator Lookup endpoints may return the following error codes:
- Name
400 Bad Request- Description
Invalid parameters provided. Common causes include: Invalid platform (must be
youtube,tiktok, orinstagram), missing username, invalidmax_videos(must be a positive integer), invalidoutlier_threshold(must be a positive number), or no videos found for the given creator.
- Name
401 Unauthorized- Description
Missing or invalid API key. Ensure you're including your API key in the Authorization header.
- Name
402 Payment Required- Description
Insufficient prepaid balance to complete the request. Add funds at dev.virlo.ai/dashboard/billing. See Billing & Pricing.
- Name
404 Not Found- Description
Job ID not found or expired. Results expire after 24 hours.
Async Workflow & State Machine
Status Flow
processing → completed
→ failed
Timing Expectations
Response times vary based on platform, max_videos, and current server load. Never hardcode timeouts.
| Configuration | Typical Duration |
|---|---|
| Default (max_videos=20) | 20-40 seconds |
| max_videos=50 | 30-60 seconds |
| max_videos=100 | 40-90 seconds |
| Under high traffic | Up to several minutes |
These are typical times but not guaranteed. Always continue polling until
status reaches completed or failed. If no change after 15 minutes, the job
may be experiencing delays but is still running.
Recommended polling interval: Every 10-15 seconds. Polling is always free.
On Failure
If status is "failed", common causes include: creator not found, platform temporarily unavailable, or invalid username. Retry with corrected parameters.
Notes
- The start endpoint returns within 1-2 seconds. All heavy work happens in the background.
- Results expire after 24 hours. Poll promptly after starting a job.
- Response time scales with
max_videos. Default (20) is fastest. Higher values require more pagination. - Instagram pagination is limited by what the API returns per page. Requesting
max_videos=100may return fewer if the creator has limited public reels. - Outlier detection compares a creator's videos against their own median. This is different from Comet's creator-outliers which compares creators against each other by follower/view ratio.
- Hashtags are extracted from video titles and descriptions, normalized to lowercase and deduplicated. Only the top 10 by total views are returned.
- Rate limits (5/min, 100/hour, 1,000/day) apply to the start endpoint. The status polling endpoint is not rate limited separately.
- Cross-platform links (
cross_links=true) discovers the same creator on other platforms using a tiered approach: structured bio link fields, URL extraction from bio text, link-in-bio page resolution (Linktree, Beacons, etc.), Spotify artist search via the official API, and AI-powered web search as a final fallback. Only links with high confidence are returned. Runs in parallel with other computations and does not add significant latency. Supported target platforms: YouTube, TikTok, Instagram, Twitter/X, and Spotify.
Creator Trend Analysis
The creator lookup also supports an optional AI trend block that surfaces the recurring formats, hooks, eras, and thematic pillars defining a creator's body of work. Same shape as sound trends (single shared engine, single shared rendering).
- $0.50 base + $0.50 trend surcharge when
trend_analysis=true. Stackable with the audience surcharge — all three (audience_demographics,audience_geography,trend_analysis) can ride on one call. - Forces a deep fetch (
max_videosfloored to 100) so the model has enough signal to detect eras and resurgences. Implicitly returns thevideos[]payload soevidence_video_idsmap back to videos in the same response. - Returns a
trendsblock on the polledcompletedresponse:summary— 1-2 sentences describing the creator's overall playbook.trends[]— each trend hasname,description,tactics[],confidence(0-1),evidence_video_ids[],time_windows[],resurged(true when 2+ disjoint windows), andmomentum(stronger|weaker|similar|null).status—ok,insufficient_corpus(fewer than 10 videos available), orskipped(analysis not requested).model_used,cost_usd,tokens_used— operational diagnostics.
- Time windows are computed mechanically from real publish dates after the LLM picks
evidence_video_ids— date hallucination is impossible. A trend isresurged: truewhen its phases land in ≥2 disjoint windows (e.g. a format the creator did in 2025, dropped, then revived in 2026). - Persisted with the run. Re-reading via
GET /v1/satellite/runs/:run_idis free, forever — even years later.
Example request:
curl -G https://api.virlo.ai/v1/satellite/creator/youtube/mkbhd \
-H "Authorization: Bearer {token}" \
-d trend_analysis=true
Full reference, response shape, and worked example: Creator Trend Analysis →.
Sound Lookups (TikTok)
Satellite also supports sound lookups — the same deep-dive treatment, but applied to every video using a specific TikTok sound. Returns sound metadata, the full normalized video list, aggregated stats (views, engagement, velocity, top creators, top hashtags, duration distribution), and an optional LLM-derived trends block with time_windows[], resurged, and momentum per trend.
- Currently TikTok only. Other platforms have no equivalent endpoint upstream.
- $0.50 base + $0.50 surcharge when
trend_analysis=true. When trends are on, the lookup forces a deeper fetch (~300 videos) and ignoresmax_videos. - Same async polling pattern as creator lookups. Status route:
/v1/satellite/sounds/status/:job_id. - Time windows are computed mechanically from real publish dates — no LLM date hallucination is possible. Trends are flagged
resurged: truewhen they appear in ≥2 disjoint windows.
Full reference: Sound Lookups →.
Re-read Past Runs (durable resource)
Every satellite run — creator, sound, video, batch — is persisted as a durable satellite_run row owned by your team. You can re-read any past run for free via the run-id endpoints below. You only pay when you create new runs. To refresh data, start a new lookup; that will cost credits again.
- Name
GET /v1/satellite/runs/:run_id- Description
Re-read a previously paid-for run by its
run_id. Returns the persisted result in full plus metadata (type, platform, status, created_at, completed_at, credits_used). Free.
- Name
GET /v1/satellite/runs- Description
Paginated history of your team's satellite runs. Optionally filter by
type(creator_lookup,sound_lookup,video_outlier,batch_creator) and/orplatform. Free.
- Name
GET /v1/satellite/runs/:run_id/videos- Description
Paginated
videos[]sub-resource for any run that carries a video list. Useful for sound lookups whosevideos[]can reach ~300 entries whentrend_analysis=true. Free.
The run_id is included on every completed satellite job result. Save it — it never expires, unlike the 24-hour poll cache.
