# TikTok, Reels & Shorts Video Analyzer: hooks, scenes, text (`frameprobe/reel-teardown`) Actor

Every scraper hands you the metadata. This one watches the video and tells you why it worked.

- **URL**: https://apify.com/frameprobe/reel-teardown.md
- **Developed by:** [FrameProbe](https://apify.com/frameprobe) (community)
- **Categories:** Videos, Social media, AI
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## TikTok, Reels & Shorts Video Analyzer: hooks, scenes, on-screen text

**Last verified: 2026-08-12**

Every scraper hands you the metadata. This one watches the video and tells you why it worked.

### What it does

Point it at short-form videos and get one structured record per video: the production stack, the
hook style, the structure and pacing, scene count and cut cadence, the on-screen text read
straight off the frames, an asset list, a plain-language explanation of why the video worked, and
a 0 to 10 "worth copying" score. Built for creators, agencies, and growth teams who
reverse-engineer what performs instead of guessing.

Output is a full structured record per video, ready to export or feed into your own tools.

### How it works: two inputs

This Actor analyzes videos. It does not scrape social sites. Feed it one of two ways.

**1. Chain a scraper's dataset (recommended).** Run a TikTok, Instagram, or YouTube scraper, then
pick its dataset. This Actor reads the media URLs the scraper already collected and analyzes each
one. This is the reliable path for all three platforms, because they block video fetching from
cloud servers.

**2. Direct media URLs.** Already have direct video file URLs? Pass them in `videoUrls` and it
analyzes them right away.

Pasting a `tiktok.com`, `instagram.com`, or `youtube.com` page link will not work. Those need a
scraper first, and the Actor tells you exactly which one to chain when it sees a page link.

### Try it free, no key

Run it with **no API key** and it still downloads each video and measures it: duration,
resolution, scene count, cut cadence, plus the sampled frames in the key-value store. You get
real records and pay nothing per video. The model-read fields (hook, structure, on-screen text,
score) come back empty and `status` is `preview`, so a preview row is never mistaken for an
analysis. Keyless runs process up to 3 videos.

Add a key to get the full teardown.

### Bring your own vision key

Analysis runs on your own Anthropic API key, so you control the model and the cost. Default model
is `claude-sonnet-5`; set `claude-opus-5` for the most capable read or `claude-haiku-4-5` to spend
less. Your key is used for the run and never stored or logged. More providers are coming; v1
supports Anthropic.

Your key and model id are checked against your own account before the run starts, so a wrong key
or a mistyped model fails immediately and costs you nothing.

### Quickstart

0. Optional: hit **Start** with the default input first. No key needed, and you get a
   measured record plus frames back in seconds.
1. Run a scraper Actor for the platform you care about.
2. Get an Anthropic key at [console.anthropic.com](https://console.anthropic.com/settings/keys)
   and paste it into **Your vision model API key**.
3. Pick the scraper's dataset in **Dataset from a scraper run**.
4. Set **Maximum videos** to cap your spend.
5. Run it. Records land in the dataset; sampled frames land in the key-value store.

```json
{
  "datasetId": "aBcDeFgHiJkLmNoP",
  "maxVideos": 25,
  "framesPerVideo": 6,
  "includeOnScreenText": true,
  "language": "en",
  "visionProvider": "anthropic",
  "visionApiKey": "sk-ant-..."
}
```

### What you get per video

```json
{
  "url": "https://cdn.example.com/clip.mp4",
  "platform": "tiktok",
  "status": "ok",
  "durationSeconds": 52.21,
  "width": 854,
  "height": 480,
  "sceneCount": 6,
  "cutCadenceSeconds": 4.96,
  "productionStack": "motion-graphics",
  "hookStyle": "story-frame",
  "hookNotes": "Opens on black then a dark foggy shot to build atmosphere before revealing characters.",
  "structureStyle": "story-arc",
  "onScreenText": ["http://jell.yfish.us"],
  "captionTreatment": "Burned in, word timed, white with a yellow accent word, lower third.",
  "visualSystem": "Consistent dark frame with a torn-paper title card between steps.",
  "assets": ["torn-paper title card", "warm cinematic grade"],
  "formatScore": 5,
  "whyItWorked": "Moody open with a slow reveal, relying on visual spectacle and curiosity rather than a spoken claim.",
  "confidence": "med",
  "likelyTools": "3D animation software, video editor",
  "frameKeys": ["frame-9f2a1c7d4e6b8a03-00.jpg"],
  "analysisStatus": "ok"
}
```

**Measured from the file** by ffprobe and ffmpeg, never by the model: `durationSeconds`, `width`,
`height`, `sceneCount`, `cutCadenceSeconds`. The scene detector fires on hard cuts, overlays
and kinetic text alike, so read the cadence as a measured proxy for pace.

**Read from the frames**, pinned to these exact values:

| Field | Values |
|---|---|
| `productionStack` | `real-camera`, `generated-avatar`, `screen-recording`, `motion-graphics`, `mixed` |
| `hookStyle` | `contrarian-claim`, `problem-promise`, `demo-first`, `list-tease`, `data-shock`, `story-frame`, `identity-call` |
| `structureStyle` | `demo-walkthrough`, `numbered-list`, `problem-solution`, `before-after`, `tutorial-steps`, `commentary-overlay`, `story-arc`, `rapid-tips`, `reframe-explainer`, `statement-psa`, `unclassified` |
| `confidence` | `low`, `med`, `high` |
| `formatScore` | Integer 0 to 10, how strong the format is as a model to copy |

Free text in your chosen `language`: `hookNotes`, `captionTreatment`, `visualSystem`,
`whyItWorked`, `likelyTools`. Lists: `onScreenText` (max 12), `assets` (max 8).

### Pricing

| What | Price |
|---|---|
| Actor start | $0.01 per run, charged after your input validates |
| Preview (no key) | **$0.04 events never fire.** Measured fields only, up to 3 videos |
| Video analyzed | $0.04 per video that produced a record |
| Videos that failed | **Free.** They appear in the dataset with a reason and are not charged |
| Vision model tokens | Billed by Anthropic, directly to your account, at their rates |

A keyless preview run costs one $0.01 start event and nothing else.
If a link is dead or a platform blocks it, you pay nothing for that video. `maxVideos` is your
hard ceiling: at 100 videos a run cannot cost more than $4.01 from us.

### Limits

- **Social page URLs need a scraper chain.** See "How it works" above.
- **Direct URLs must be publicly fetchable** from a cloud server.
- **Instagram and TikTok media links are short-lived signed URLs.** Pass a fresh dataset rather
  than stored links, or expect `download-403`.
- **Videos are capped** at 60 MB, 180 seconds, and 2160px on the long edge. Anything larger is
  reported as failed rather than silently truncated.
- **Frames, not audio.** The analysis reads what is on screen. It does not transcribe speech, so
  a video whose whole point is spoken gets its visual format scored, not its script.
- **Analysis depth scales with `framesPerVideo`** (default 6).

### Maintained

Actively maintained. Broken inputs get diagnosed with a specific reason and a fix, not a stack
trace: a deleted video, an age-gated one, and a platform blocking our IP each say so and each
tell you what to do next.

See [CHANGELOG.md](CHANGELOG.md).

# Actor input Schema

## `videoUrls` (type: `array`):

Direct media file URLs (ending in .mp4 and similar), analyzed straight away. Social page links (tiktok.com, instagram.com, youtube.com) will NOT work: those platforms block video fetching from cloud servers, so chain a scraper and use the dataset field above. If you paste a page link anyway, the Actor tells you which scraper to run.

## `datasetId` (type: `string`):

The recommended input. Run a TikTok, Instagram or YouTube scraper first, then pick its dataset here: this Actor reads the media URLs the scraper already collected and analyzes each one. Recognised fields include videoUrl, videoUrlNoWaterMark, mediaUrl, webVideoUrl and url.

## `maxVideos` (type: `integer`):

Hard stop on how many videos this run analyzes, so a large input list cannot spend more than you expect. At $0.04 per analyzed video, 100 videos is a $4.00 ceiling.

## `framesPerVideo` (type: `integer`):

How many stills are sampled and sent to the vision model. More frames means a more accurate read of structure and on-screen text, and a higher bill from your model provider. Frames are always dense over the opening seconds and spread across the rest.

## `includeOnScreenText` (type: `boolean`):

Transcribe the text visible in the frames into the onScreenText field. Turning this off trims what the model writes back, which slightly lowers your model bill. It does not change how many frames are read.

## `language` (type: `string`):

The language for the written fields (hookNotes, whyItWorked, visualSystem, and so on). Classification values such as hookStyle stay in English so they can be filtered and counted.

## `visionApiKey` (type: `string`):

Your own Anthropic API key, from console.anthropic.com/settings/keys. Analysis runs on your account and you pay Anthropic directly, at their rates. The key is used for the run and is never stored or logged. Leave this empty for a free preview: the videos are still downloaded and measured (duration, resolution, scene count, cut cadence) and you are charged nothing per video.

## `visionProvider` (type: `string`):

Which API your key belongs to. v1 supports Anthropic only; more providers are planned.

## `visionModel` (type: `string`):

Leave blank for claude-sonnet-5, the balanced default. Set claude-opus-5 for the most capable read, or claude-haiku-4-5 to lower your own inference bill. The id is checked against your account before the run starts, and an invalid one fails immediately with the list of models you can use.

## Actor input object example

```json
{
  "videoUrls": [
    "https://media.w3.org/2010/05/sintel/trailer.mp4"
  ],
  "maxVideos": 10,
  "framesPerVideo": 6,
  "includeOnScreenText": true,
  "language": "en",
  "visionProvider": "anthropic"
}
```

# Actor output Schema

## `teardowns` (type: `string`):

One record per input video, including the ones that failed. Successful records carry the production stack, hook style, structure style, on-screen text, asset list, measured scene count and cut cadence, and a written read of why the format worked. Failed records carry a specific reason and what to do about it, and are never charged.

## `frames` (type: `string`):

The JPEG stills sampled from each video, keyed frame-<videoId>-NN.jpg and referenced by the frameKeys field on each record. Sampling is dense over the opening seconds and spread across the rest.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "videoUrls": [
        "https://media.w3.org/2010/05/sintel/trailer.mp4"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("frameprobe/reel-teardown").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "videoUrls": ["https://media.w3.org/2010/05/sintel/trailer.mp4"] }

# Run the Actor and wait for it to finish
run = client.actor("frameprobe/reel-teardown").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "videoUrls": [
    "https://media.w3.org/2010/05/sintel/trailer.mp4"
  ]
}' |
apify call frameprobe/reel-teardown --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,frameprobe/reel-teardown"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/AGJwhrvhSc1EK0QcF/builds/MQSHq0k54936ewoD4/openapi.json
