Hooks
The hook is what a short-form post says or shows in its first seconds. Virlo has the hooks of about 980,000 videos and 440,000 photo slideshows from TikTok, YouTube and Instagram, with how each post did.
- What it does
- Shows which openings work on short-form video, with real examples and templates for writing your own.
- You send
- Optional filters. Search also needs a phrase or a hook type, and agent hooks needs your agent's ID.
- You get back
- Real hooks with their posts (views, creator, link), a scoreboard of hook types, or templates.
- Cost
- Free: hook type stats and library categories. $0.10: templates. $0.25: everything else (agent hooks are free with Data Intelligence, or before any are found). Each page of results is charged.
Which one do I need?
- Which kinds of hooks win: hook types and stats
- Top hooks of the last 7, 14 or 30 days: trending
- Search a phrase, find who posted a hook, or see a type's best: search
- The best hooks in your Content Research Agent's videos: agent hooks
- Templates for writing your own: the library
Key terms
- Hook (
hook_text): the opening, word for word. For a video, the first line spoken in about the first 6 seconds, else the on-screen text in the opening shot. For a slideshow, the first slide's text. - Virality Score (
weighted_score): how far a post beat its creator's follower count, with extra credit for big accounts, so every creator size and platform shares one scale. Formula: ln(views ÷ followers) × ln(followers).- 35 and up: exceptional
- 25 to 35: very strong
- 18 to 25: strong
- 10 to 18: promising
- 0 to 10: more views than followers, but not a standout
- Below 0: fewer views than followers (about half of all videos)
- Outlier ratio (
outlier_ratio): views ÷ followers. - Usage count (
usage_count): how many posts across Virlo open with the same words.1means an original line. - Strong hit rate (
strong_hit_rate): the share of a hook type's videos scoring 18 or more.0.28means 28%.
Hook types, explained
Every hook has a hook_type (what the opening line does). Videos usually also have a visual_hook_type (what the opening shot shows). Slideshows and some videos have no visual type (null or none) but still appear in results. Videos with no clear hook get hook_type none, shown only in the stats and never filterable.
The 16 hook types: question, bold_claim, shock_statement, story_tease, tutorial_promise, controversy (takes a side), before_after (a transformation reveal), pov_setup ("POV:"), statistic, direct_address ("If you have oily skin…"), trend_reference, cliffhanger (holds back the payoff), negation ("Stop doing this"), relatable_scenario, comparison and mystery_setup (a puzzle to solve).
The 11 visual hook types: text_hook (big on-screen text), extreme_closeup, before_state, shocking_image, aesthetic_setup, person_speaking_to_camera, motion_action, crowded_scene, mystery_object, dramatic_zoom and animal_pet.
Content categories
The category filter takes only these 28 values. The template library has its own categories.
art_design, automotive, beauty, business_career, crafts_diy, education, entertainment, fashion, finance, fitness, food_beverage, gaming, health_wellness, home_garden, kids_content, lifestyle, music, news_politics, parenting_family, pets, real_estate, relationships_dating, religion_spirituality, science_nature, sports, tech, travel, other
Hook types and stats
Which kinds of hooks win most often, overall or on one platform or category. It lists every type plus none, minus types with no videos in your platform or category.
- Sort by
strong_hit_rateto see what works. Common is not the same as effective: across all videos, the two most-used types,tutorial_promiseandbold_claim, have the two lowest hit rates. - Check
video_count. A rare type can top the list on a tiny sample:cliffhangerleads overall with only 268 videos. - Videos only, not slideshows, refreshed daily.
share_of_corpusis each type's share of the slice you asked for, so the rows add up to 1.
Query parameters
All optional. page and limit are rejected (400).
- Name
dimension- Type
- string
- Description
hook_type(default) orvisual_hook_type.
- Name
platform- Type
- string
- Description
tiktok,youtubeorinstagram.
- Name
category- Type
- string
- Description
One of the 28 content categories.
- Name
sort- Type
- string
- Description
Highest first:
video_count(default),strong_hit_rate,median_weighted_scoreorp90_weighted_score.
Request
curl "https://api.virlo.ai/v1/hooks/types?sort=strong_hit_rate" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"data": {
"dimension": "hook_type",
"platform": "all",
"category": "all",
"snapshot_date": "2026-09-24",
"types": [
{
"value": "cliffhanger",
"video_count": 268,
"share_of_corpus": 0.0003,
"total_views": 189174617,
"avg_views": 705875,
"median_views": 8817,
"avg_weighted_score": 5.77,
"median_weighted_score": 8.65,
"p90_weighted_score": 35.95,
"strong_hit_rate": 0.2786
},
{
"value": "pov_setup",
"video_count": 43974,
"share_of_corpus": 0.0449,
"total_views": 32986509016,
"avg_views": 750137,
"median_views": 19811,
"avg_weighted_score": 2.95,
"median_weighted_score": 5.05,
"p90_weighted_score": 35.93,
"strong_hit_rate": 0.2729
}
]
}
}
Trending hooks
The top hooks from posts published in the last 7, 14 or 30 days, ranked by Virality Score.
Query parameters
All optional.
- Name
days- Type
- integer
- Description
7(default),14or30.
- Name
category- Type
- string
- Description
One of the 28 content categories.
- Name
platform- Type
- string
- Description
tiktok,youtubeorinstagram.
- Name
content_type- Type
- string
- Description
video(default),slideshoworall. Slideshows currently time out here with a503. Use search withcontent_type=slideshowand ahook_typeinstead (all time, not just recent).
- Name
hook_type, visual_hook_type- Type
- string
- Description
One of the hook types.
visual_hook_typeleaves out all slideshows.
Details for developers
Search and agent hooks use this shape too. Each hook appears once, from its strongest post.
brand_safety_tierissafe,low_riskormedium_risk(riskier and adult posts are left out). It can benullon some slideshows.usage_countmatches words, ignoring capitals and spacing but not punctuation.video.sharesisnullon almost all YouTube posts, andvideo.durationon slideshows.- Only YouTube
author_handlevalues start with@.
Request
curl "https://api.virlo.ai/v1/hooks/trending?category=fitness&days=7&limit=10" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"data": [
{
"hook_text": "10 signals your body is losing FAT",
"hook_type": "tutorial_promise",
"visual_hook_type": "text_hook",
"content_type": "video",
"platform": "tiktok",
"category": "fitness",
"language": "en",
"brand_safety_tier": "safe",
"outlier_ratio": 64.43,
"weighted_score": 35.88,
"usage_count": 1,
"video": {
"video_id": "7570d1bc-f0c6-4aa1-8f13-98fa919bcc2f",
"url": "https://www.tiktok.com/@scully_fitness/video/7686773818983042325",
"thumbnail_url": "https://auth.virlo.ai/storage/v1/object/public/thumbnails/8ed30a72cd9c1f9ab952eca2a4cf6462e9583076bd2f69f43e572f790dd0ae77.jpg",
"views": 354321,
"likes": 10851,
"comments": 34,
"shares": 271,
"duration": 6,
"publish_date": "2026-09-18T07:28:22+00:00",
"author_handle": "scully_fitness",
"author_followers": 5499
}
}
],
"pagination": { "page": 1, "limit": 10, "total": 11, "total_pages": 2, "has_next_page": true, "has_prev_page": false }
}
Search hooks
Finds hooks by phrase or by type, across all time: the top hooks built on a phrase like "nobody talks about", or the post a pasted hook came from (a reverse lookup). Needs a phrase (q) or a type (hook_type, visual_hook_type). Other filters alone are rejected (400).
Searching by phrase
Results come in three groups, in this order, named in match_type:
exact: the hook is your text, ignoring capitals and spacing but not punctuation. Always first, even if the post did poorly.contains: your words, whole and side by side, ignoring punctuation, emoji and line breaks between them. Highest Virality Score first.similar: near-matches, closest first. Only for aqof 12+ characters, when the page isn't full.
A paste whose punctuation between words differs lands in contains. Punctuation inside a word counts: dont won't find "don't". match_score (0 to 1) rates the whole hook against your text, so long hooks score low. Only similar is sorted by it.
Browsing by type
Without q, you get the strongest hooks of a type, all time, in mixed languages unless you set language. match_type and match_score are null.
Query parameters
days and sort are rejected (400).
- Name
q- Type
- string
- Description
3 to 200 characters, including a word of 3 or more letters or digits.
- Name
content_type- Type
- string
- Description
video(default),slideshoworall.
- Name
hook_type, visual_hook_type, platform, category, language, min_views, page, limit- Type
- string | integer
- Description
As on trending.
Request
curl "https://api.virlo.ai/v1/hooks/search?q=nobody%20talks%20about&language=en&limit=10" \
-H "Authorization: Bearer YOUR_API_KEY"
Phrase search
{
"data": [
{
"hook_text": "NOBODY TALKS ABOUT",
"match_type": "exact",
"match_score": 1,
"weighted_score": -0.43,
"usage_count": 1,
"video": { "views": 2863, "author_handle": "hello.inertia" }
},
{
"hook_text": "Nobody talks about\nhow hard\nit is\nto go from this...",
"match_type": "contains",
"match_score": 0.422222,
"weighted_score": 61.21,
"usage_count": 4,
"video": { "views": 7014838, "author_handle": "naysnetwork" }
},
{
"hook_text": "Nobody talks about hard it is\nto go from this...",
"match_type": "contains",
"match_score": 0.452381,
"weighted_score": 53.64,
"usage_count": 1,
"video": { "views": 3838283, "author_handle": "mmadsgains" }
}
],
"pagination": { "page": 1, "limit": 10, "total": 11, "total_pages": 2, "has_next_page": true, "has_prev_page": false }
}
Hook template library
More than 4,100 hand-picked hook templates in 33 categories, each with an example and a note on why it works. Most have [blanks] to fill in, and some are complete lines. They come in a fixed order, not ranked by performance.
You pay even when nothing matches. tags is currently always empty.
Query parameters
All optional.
- Name
category- Type
- string
- Description
A
slugfrom library categories, likeeducational-hooks. A misspelled slug returns an empty list.
- Name
psychology_tag- Type
- string
- Description
One tag, matched exactly, spaces and capitals included:
social proofworks,social_prooffinds nothing. There are about 3,500 tags and no list. If a tag finds nothing, tryq: it skips tags but searches the psychology note.
- Name
q- Type
- string
- Description
Text in the template, example or psychology note, any case. 2 to 200 characters.
- Name
page, limit- Type
- integer
- Description
Defaults 1 and 20,
limitup to 100.totalis exact.
Request
curl "https://api.virlo.ai/v1/hooks/library?psychology_tag=curiosity&limit=5" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"data": [
{
"hook_text": "Here's what happened when I [took big risk].",
"example": "Here's what happened when I quit my job without a backup plan.",
"psychology": "Fear + curiosity about bold decisions.",
"psychology_tags": ["fear", "curiosity"],
"tags": [],
"library_category": { "slug": "case-studies-proof-hooks", "name": "Case Studies & Proof Hooks" }
}
],
"pagination": { "page": 1, "limit": 5, "total": 115, "total_pages": 23, "has_next_page": true, "has_prev_page": false }
}
Library categories
The 33 library categories, each with its template count. Pass a slug as the library's category. description is always null.
Request
curl "https://api.virlo.ai/v1/hooks/library/categories" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"data": [
{ "slug": "educational-hooks", "name": "Educational Hooks", "description": null, "hook_count": 200 }
]
}
Agent hooks
The strongest hooks in the videos your Content Research Agent has collected, ranked by Virality Score.
$0.25 per request. Free while coverage.videos_with_hooks is 0, and always free when the agent has Data Intelligence on (data_intelligence_enabled: true).
- Videos only. Each video counts once.
usage_countcounts matching hooks across all of Virlo, not just this agent.pagination.totalis exact, with no 1,000-result cap.- Unknown or someone else's agent:
404. A malformed ID currently gives a500instead.
Coverage
coverage.videos_collected counts the agent's distinct videos, and videos_with_hooks those with an analyzed hook. Agents have hooks with or without Data Intelligence, but only analyzed videos have one. Off-topic, year-old and underperforming videos are not analyzed, so the second number is normally well below the first. videos_with_hooks: 0 usually means a new agent or nothing analyzed yet: try trending meanwhile.
Parameters
category, visual_hook_type, language and content_type are rejected (400) here.
- Name
id- Type
- string
- Required
- *
- Description
Your agent's full 36-character ID (a UUID), from
GET /v1/agents.
- Name
platform, hook_type, min_views, sort- Type
- string | integer
- Description
As on trending.
- Name
page, limit- Type
- integer
- Description
Defaults 1 and 20,
limitup to 100.
Request
curl "https://api.virlo.ai/v1/agents/{agent_id}/hooks?limit=30" \
-H "Authorization: Bearer YOUR_API_KEY"
Response
{
"data": {
"agent_id": "c1e483c3-...",
"coverage": { "videos_collected": 311, "videos_with_hooks": 65 },
"hooks": [
{
"hook_text": "Have you ever wondered what all these espresso tools actually do?",
"hook_type": "question",
"visual_hook_type": "text_hook",
"platform": "youtube",
"weighted_score": 41.55,
"usage_count": 1,
"video": { "views": 24275222, "author_handle": "@Ethanrodecoffee", "author_followers": 1260000 }
}
]
},
"pagination": { "page": 1, "limit": 30, "total": 65, "total_pages": 3, "has_next_page": true, "has_prev_page": false }
}
Paging, costs and errors
- Top 1,000. Trending and search stop at the top 1,000 results (page 50 at
limit=20). - Trending and search
totalisn't a full count. It counts results through this page, plus one if more exist (page 1 atlimit=10shows11). Keep paging whilehas_next_pageistrue. - Charges. Empty results are charged, except agent hooks with
videos_with_hooks: 0. Errors never are.X-Costshows the charge in dollars andX-Credits-Usedin credits (1 credit = $0.01).
Errors come back with message, error, statusCode and code (more on errors):
400: a bad value, an unknown parameter (library categories ignores them) or a page past the top 1,000. The message lists valid values.402: your balance is too low.503: the query ran past about 8 seconds. Retrying the same call usually fails again. For trending slideshows, use search instead.
