# Hooks

> See which opening lines work on short-form video. Look up real hooks from about 1.4M TikTok, YouTube and Instagram posts with their views and Virality Score, find which hook types win in your niche, and browse 4,100+ hook templates.

Source: https://dev.virlo.ai/docs/hooks
Markdown: https://dev.virlo.ai/docs/hooks.md
Section: Explore data

## About the Virlo API (applies to every page)

- Base URL: `https://api.virlo.ai/v1`. Every request needs the header `Authorization: Bearer YOUR_API_KEY` (keys start with `virlo_tkn_`).
- Responses are JSON inside a `data` field, except the `/v1/webhooks` endpoints, which return the object or array directly. Field names are snake_case.
- Prices are in US dollars from a prepaid balance. 1 credit = $0.01. The `X-Cost` response header on each successful response is the exact charge. Errors are free.
- Slow jobs return an ID. Check its status every 15 seconds (or whatever `retry_after_seconds` says) until `finalized` is `true`.
- All docs pages: https://dev.virlo.ai/llms.txt. Every page in one file: https://dev.virlo.ai/llms-full.txt. MCP server for AI assistants: https://dev.virlo.ai/api/mcp/mcp.

---

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.

**At a glance**

- **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](https://dev.virlo.ai/docs/hooks#hook-taxonomy-stats)
- **Top hooks of the last 7, 14 or 30 days:** [trending](https://dev.virlo.ai/docs/hooks#trending-hooks)
- **Search a phrase, find who posted a hook, or see a type's best:** [search](https://dev.virlo.ai/docs/hooks#search-hooks)
- **The best hooks in your [Content Research Agent](https://dev.virlo.ai/docs/agents)'s videos:** [agent hooks](https://dev.virlo.ai/docs/hooks#agent-hooks)
- **Templates for writing your own:** the [library](https://dev.virlo.ai/docs/hooks#hook-template-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. `1` means an original line.
- **Strong hit rate** (`strong_hit_rate`): the share of a hook type's videos scoring 18 or more. `0.28` means 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](https://dev.virlo.ai/docs/hooks#library-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

**Endpoint:** `GET https://api.virlo.ai/v1/hooks/types`

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.

Cost per request: Free

- **Sort by `strong_hit_rate`** to see what works. Common is not the same as effective: across all videos, the two most-used types, `tutorial_promise` and `bold_claim`, have the two lowest hit rates.
- **Check `video_count`.** A rare type can top the list on a tiny sample: `cliffhanger` leads overall with only 268 videos.
- **Videos only**, not slideshows, refreshed daily. `share_of_corpus` is 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`).

- `dimension` (string, optional): `hook_type` (default) or `visual_hook_type`.
- `platform` (string, optional): `tiktok`, `youtube` or `instagram`.
- `category` (string, optional): One of the [28 content categories](https://dev.virlo.ai/docs/hooks#content-categories).
- `sort` (string, optional): Highest first: `video_count` (default), `strong_hit_rate`, `median_weighted_score` or `p90_weighted_score`.

**cURL request:**

```bash
curl "https://api.virlo.ai/v1/hooks/types?sort=strong_hit_rate" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json
{
  "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

**Endpoint:** `GET https://api.virlo.ai/v1/hooks/trending`

The top hooks from posts published in the last 7, 14 or 30 days, ranked by Virality Score.

Cost per request: $0.25

### Query parameters

All optional.

- `days` (integer, optional): `7` (default), `14` or `30`.
- `category` (string, optional): One of the [28 content categories](https://dev.virlo.ai/docs/hooks#content-categories).
- `platform` (string, optional): `tiktok`, `youtube` or `instagram`.
- `content_type` (string, optional): `video` (default), `slideshow` or `all`. Slideshows currently time out here with a `503`. Use [search](https://dev.virlo.ai/docs/hooks#search-hooks) with `content_type=slideshow` and a `hook_type` instead (all time, not just recent).
- `hook_type, visual_hook_type` (string, optional): One of the [hook types](https://dev.virlo.ai/docs/hooks#hook-types-explained). `visual_hook_type` leaves out all slideshows.
- `language` (string, optional): Like `en` or `es`.
- `min_views` (integer, optional): Minimum views.
- `sort` (string, optional): `weighted_score` (default) or `views`.
- `page, limit` (integer, optional): Defaults 1 and 20, `limit` up to 100. Only the top 1,000 results.

**Details for developers**

Search and agent hooks use this shape too. Each hook appears once, from its strongest post.

- `brand_safety_tier` is `safe`, `low_risk` or `medium_risk` (riskier and adult posts are left out). It can be `null` on some slideshows.
- `usage_count` matches words, ignoring capitals and spacing but not punctuation.
- `video.shares` is `null` on almost all YouTube posts, and `video.duration` on slideshows.
- Only YouTube `author_handle` values start with `@`.

**cURL request:**

```bash
curl "https://api.virlo.ai/v1/hooks/trending?category=fitness&days=7&limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json
{
  "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

**Endpoint:** `GET https://api.virlo.ai/v1/hooks/search`

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`).

Cost per request: $0.25

### Searching by phrase

Results come in three groups, in this order, named in `match_type`:

1. **`exact`**: the hook is your text, ignoring capitals and spacing but not punctuation. Always first, even if the post did poorly.
2. **`contains`**: your words, whole and side by side, ignoring punctuation, emoji and line breaks between them. Highest Virality Score first.
3. **`similar`**: near-matches, closest first. Only for a `q` of 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`).

- `q` (string, optional): 3 to 200 characters, including a word of 3 or more letters or digits.
- `content_type` (string, optional): `video` (default), `slideshow` or `all`.
- `hook_type, visual_hook_type, platform, category, language, min_views, page, limit` (string | integer, optional): As on [trending](https://dev.virlo.ai/docs/hooks#trending-hooks).

**Phrase request:**

```bash
curl "https://api.virlo.ai/v1/hooks/search?q=nobody%20talks%20about&language=en&limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Browse by type request:**

```bash
curl "https://api.virlo.ai/v1/hooks/search?hook_type=question&category=finance" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Phrase search:**

```json
{
  "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

**Endpoint:** `GET https://api.virlo.ai/v1/hooks/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.

Cost per request: $0.10

You pay even when nothing matches. `tags` is currently always empty.

### Query parameters

All optional.

- `category` (string, optional): A `slug` from [library categories](https://dev.virlo.ai/docs/hooks#library-categories), like `educational-hooks`. A misspelled slug returns an empty list.
- `psychology_tag` (string, optional): One tag, matched exactly, spaces and capitals included: `social proof` works, `social_proof` finds nothing. There are about 3,500 tags and no list. If a tag finds nothing, try `q`: it skips tags but searches the psychology note.
- `q` (string, optional): Text in the template, example or psychology note, any case. 2 to 200 characters.
- `page, limit` (integer, optional): Defaults 1 and 20, `limit` up to 100. `total` is exact.

**cURL request:**

```bash
curl "https://api.virlo.ai/v1/hooks/library?psychology_tag=curiosity&limit=5" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json
{
  "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

**Endpoint:** `GET https://api.virlo.ai/v1/hooks/library/categories`

The 33 library categories, each with its template count. Pass a `slug` as the [library](https://dev.virlo.ai/docs/hooks#hook-template-library)'s `category`. `description` is always `null`. Cost per request: Free

**cURL request:**

```bash
curl "https://api.virlo.ai/v1/hooks/library/categories" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json
{
  "data": [
    { "slug": "educational-hooks", "name": "Educational Hooks", "description": null, "hook_count": 200 }
  ]
}
```

---

## Agent hooks

**Endpoint:** `GET https://api.virlo.ai/v1/agents/:id/hooks`

The strongest hooks in the videos your [Content Research Agent](https://dev.virlo.ai/docs/agents) 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](https://dev.virlo.ai/docs/intelligence) on (`data_intelligence_enabled: true`).

- Videos only. Each video counts once.
- `usage_count` counts matching hooks across all of Virlo, not just this agent.
- `pagination.total` is exact, with no 1,000-result cap.
- Unknown or someone else's agent: `404`. A malformed ID currently gives a `500` instead.

### 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](https://dev.virlo.ai/docs/hooks#trending-hooks) meanwhile.

### Parameters

`category`, `visual_hook_type`, `language` and `content_type` are rejected (`400`) here.

- `id` (string, required): Your agent's full 36-character ID (a UUID), from [`GET /v1/agents`](https://dev.virlo.ai/docs/agents#list-agents).
- `platform, hook_type, min_views, sort` (string | integer, optional): As on [trending](https://dev.virlo.ai/docs/hooks#trending-hooks).
- `page, limit` (integer, optional): Defaults 1 and 20, `limit` up to 100.

**cURL request:**

```bash
curl "https://api.virlo.ai/v1/agents/{agent_id}/hooks?limit=30" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json
{
  "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 `total` isn't a full count.** It counts results through this page, plus one if more exist (page 1 at `limit=10` shows `11`). Keep paging while `has_next_page` is `true`.
- **Charges.** Empty results are charged, except agent hooks with `videos_with_hooks: 0`. Errors never are. `X-Cost` shows the charge in dollars and `X-Credits-Used` in credits (1 credit = $0.01).

Errors come back with `message`, `error`, `statusCode` and `code` ([more on errors](https://dev.virlo.ai/docs/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](https://dev.virlo.ai/docs/hooks#search-hooks) instead.

---

More in Explore data:

- [Trends](https://dev.virlo.ai/docs/trends.md)
- [Sounds](https://dev.virlo.ai/docs/sounds.md)
- [Hashtags](https://dev.virlo.ai/docs/hashtags.md)
- [Videos](https://dev.virlo.ai/docs/videos.md)
