# Instagram Reels Transcript Scraper - Hooks, Text & Scripts (`webdatalabs/instagram-reels-transcript`) Actor

Transcribe public Instagram Reels into timestamped text, pull the 3-second hook that decides whether viewers stay, and optionally break down script structure, CTA, topics and format. No login, no cookies, no account.

- **URL**: https://apify.com/webdatalabs/instagram-reels-transcript.md
- **Developed by:** [WebDataLabs](https://apify.com/webdatalabs) (community)
- **Categories:** For creators, Social media, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $9.80 / 1,000 reel transcribeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Instagram Reels Transcript Scraper — Hooks, Text & Scripts

Turn any public Instagram Reel into its transcript, its timestamped script and the 3-second hook
that decides whether people keep watching. No login, no cookies, no account.

### What you get

This Instagram Reels transcript scraper gives you the **words**, not just the metrics. For every
Reel you get the full spoken transcript, timestamped segments you can jump to, the text burned onto
the cover frame, and the **3-second hook** — the exact words in the opening seconds where Reels are
won or lost. Turn on AI script analysis and each Reel also comes back with its script structure,
call to action, topics and format.

It is built for the thing people actually do with it: hand it **one Reel link** from an automation
and get a usable answer back in about ten seconds. It also takes a list of accounts when you want
to study a creator's last N Reels in one go.

### What data can it extract?

| Field | What it is |
|---|---|
| `hook3s` | Everything spoken in the first 3 seconds — the retention decision |
| `onScreenText` | Text burned into the cover frame, read with vision |
| `transcript` | The full spoken text |
| `segments` | The transcript split into `{start, end, text}` chunks |
| `plays` · `likes` · `comments` | Engagement, when Instagram publishes it |
| `durationSeconds` · `language` | Length and detected language |
| `scriptStructure` · `cta` · `topics` · `format` | AI script analysis (optional) |
| `transcriptStatus` · `statusReason` | Why a Reel has no transcript, in plain English |

### Example output

```json
{
  "hook3s": "NASA just launched",
  "onScreenText": null,
  "url": "https://www.instagram.com/reel/DcuQVFLvJMX/",
  "shortcode": "DcuQVFLvJMX",
  "username": "nasa",
  "postedAt": "2026-08-31T23:23:27.000Z",
  "plays": null,
  "likes": 218056,
  "comments": 1095,
  "durationSeconds": 63.42,
  "language": "English",
  "transcript": "NASA just launched Nancy Grace Roman, the most powerful telescope the world has ever known...",
  "segments": [
    { "start": 0, "end": 8, "text": "NASA just launched Nancy Grace Roman, the most powerful telescope the world has ever known." },
    { "start": 8, "end": 18, "text": "And when she opens her eyes, nearly a million miles from Earth..." }
  ],
  "scriptStructure": "Hook (bold claim) -> three proof points -> closing vision statement",
  "cta": null,
  "topics": ["nasa", "telescope", "space", "discovery"],
  "format": "announcement",
  "caption": "Roman is on her way, and the Golden Age of Exploration is just the beginning.",
  "hasAudio": true,
  "transcriptStatus": "ok",
  "statusReason": null,
  "discoveredVia": "reelUrls",
  "scrapedAt": "2026-09-22T17:05:31.749Z"
}
```

That Reel speaks its hook, so `onScreenText` is `null`. Plenty of Reels do the opposite — they say
nothing and put the hook on screen. Those still come back useful:

```json
{
  "hook3s": null,
  "onScreenText": "T-38 TALONS FROM JOHNSON SPACE CENTER IN HOUSTON\nFIRST NASA NFL FLYOVER",
  "shortcode": "DdPDuIepVPf",
  "transcript": null,
  "hasAudio": false,
  "transcriptStatus": "no_audio",
  "statusReason": "This Reel has no spoken audio. The on-screen text from its cover frame is included instead."
}
```

### How to use it

Paste a Reel link and press Start. That is the whole setup.

**One Reel** — the common case, and what you would call from n8n, Make or an agent:

```json
{ "reelUrls": ["https://www.instagram.com/reel/DcuQVFLvJMX/"] }
```

Links, `/reel/CODE/` paths, `/p/CODE/` paths and bare codes all work.

**A creator's latest Reels**, with view counts and the AI breakdown:

```json
{
  "usernames": ["nasa", "@garyvee"],
  "maxReelsPerProfile": 10,
  "includeAiAnalysis": true
}
```

**A scheduled watch** that only returns and bills for what is new:

```json
{
  "usernames": ["nasa"],
  "maxReelsPerProfile": 25,
  "postedWithinDays": 7,
  "onlyNewSinceLastRun": true
}
```

### How much does it cost to transcribe Instagram Reels?

Pay per result: you are charged per Reel that actually comes back with a transcript or on-screen
text, plus an optional add-on when you turn on AI script analysis. Reels that turn out to be silent
with no text, deleted or private are still returned so you can see what happened — and they are
**not** billed. See the pricing box above for current rates.

### Use cases

- **Turn a competitor's Reel into a script outline.** Filter `format` and read `scriptStructure` to
  see how a winning Reel is built before you write your own.
- **Build a hook swipe file.** Run a handful of creators weekly, sort by `plays`, and keep the
  `hook3s` and `onScreenText` columns. The "Hooks and structure" view is made for this.
- **Repurpose to other channels.** `transcript` plus `segments` gives you subtitle timings, blog
  copy and newsletter excerpts without rewatching anything.
- **Automate it.** Send one Reel URL per workflow run from n8n, Make or an agent and get the hook
  and script back in a few seconds.
- **Accessibility and archiving.** Keep a searchable text record of your own Reels.

### FAQ

#### Do I need an Instagram login or cookies?

No. It only reads publicly available Reels, with no account, no credentials and no cookies from
your own profile.

#### Why is `plays` empty for some Reels?

Instagram does not publish a view count on an individual Reel page — only on an account's Reels
feed. So `plays` is filled in for Reels found through the **Usernames** input, and `null` for Reels
you supplied as a URL. If you need view counts, pass the username rather than the link. The same
applies to the `minViews` filter, which is ignored for Reel URLs.

#### Can it search by hashtag, keyword or location?

No, and deliberately. Those results require a logged-in session on Instagram, and this Actor never
uses an account. It takes Reel URLs and usernames only.

#### What happens with Reels that have no speech?

You still get a row. Many Reels carry their hook as text on screen rather than saying it, so the
cover frame is read with vision and returned as `onScreenText`. If a Reel has neither speech nor
cover text, the row comes back with `transcriptStatus` explaining why and is not billed.

#### Does it read text that appears later in the Reel?

Not yet. `onScreenText` is read from the **cover frame**, which is where creators put the opening
hook. Captions that appear later in the video are not captured.

#### How accurate is the transcript?

It uses Whisper large v3 turbo. Accuracy is high for clear speech and degrades with heavy
background music, crosstalk or strong accents — as any speech model does. Set **Spoken language**
explicitly if a Reel is being transcribed into the wrong language.

#### Is it legal to scrape Instagram Reels?

This Actor reads only public content, without logging in, and collects no follower lists and no
commenter data. Transcripts of someone else's video are still their creative work: use them for
research, analysis and your own content planning, and take your own advice before republishing
someone's words verbatim or at scale. You are responsible for how you use the output, including
under GDPR and local copyright law.

#### How many Reels can I get from one account?

As many as you ask for. Instagram serves them 12 at a time and this Actor pages through
automatically, so `maxReelsPerProfile` is limited only by your patience and budget.

### Related actors

- [YouTube Transcript & RAG Scraper](https://apify.com/webdatalabs/youtube-transcript-rag) — the
  same idea for YouTube, with chapters and summaries.
- [Meta Threads Scraper](https://apify.com/webdatalabs/meta-threads-scraper) — posts, replies,
  profiles and keyword search on Threads.
- [YouTube Shorts Scraper](https://apify.com/webdatalabs/youtube-shorts-scraper) — short-form video
  data from YouTube.

### Support

Found a bug or need a field that is missing? Open an issue on the Actor's **Issues** tab and it will
be picked up.

# Actor input Schema

## `reelUrls` (type: `array`):

One Reel per entry. A full link, a /reel/CODE/ or /p/CODE/ path, or just the bare code all work. Leave empty if you are using Usernames instead.

## `usernames` (type: `array`):

Public accounts whose newest Reels you want. Works as nasa, @nasa or a full profile link. View counts are only available through this input - see Max Reels per profile below.

## `maxReelsPerProfile` (type: `integer`):

How many of the newest Reels to take from each username. Instagram serves these 12 at a time, so higher numbers simply take longer.

## `includeAiAnalysis` (type: `boolean`):

Adds script structure, the call to action, topics and the content format to every transcribed Reel. Billed as a separate event per Reel analysed.

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

Leave on Detect automatically unless the speech is being transcribed into the wrong language. Setting it explicitly also improves accuracy on short Reels.

## `postedWithinDays` (type: `integer`):

Only keep Reels published in this many days. Applies to the Usernames input: the Actor checks each Reel's date and stops as soon as it reaches older ones, so you are never charged for a Reel outside the window.

## `minViews` (type: `integer`):

Only keep Reels with at least this many views. Instagram does not publish view counts on individual Reel pages, so this filter applies to the Usernames input only and is ignored for Reel URLs.

## `onlyNewSinceLastRun` (type: `boolean`):

Remembers which Reels this input already returned and skips them next time, so a scheduled run only pays for and returns what is new.

## `proxyConfiguration` (type: `object`):

Off by default, and that is the fast path - Instagram serves Apify's own servers directly, which is several times faster and cheaper than proxying. If a Reel comes back gated the Actor automatically retries through a proxy, so turn this on only if you want every request proxied from the start.

## Actor input object example

```json
{
  "reelUrls": [
    "https://www.instagram.com/reel/DcuQVFLvJMX/",
    "DdhFkS7KGkZ"
  ],
  "usernames": [
    "nasa",
    "@garyvee"
  ],
  "maxReelsPerProfile": 6,
  "includeAiAnalysis": false,
  "language": "auto",
  "onlyNewSinceLastRun": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `hooks` (type: `string`):

No description

## `full` (type: `string`):

No description

## `runSummary` (type: `string`):

No description

# 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 = {
    "reelUrls": [
        "https://www.instagram.com/reel/DcuQVFLvJMX/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("webdatalabs/instagram-reels-transcript").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 = { "reelUrls": ["https://www.instagram.com/reel/DcuQVFLvJMX/"] }

# Run the Actor and wait for it to finish
run = client.actor("webdatalabs/instagram-reels-transcript").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 '{
  "reelUrls": [
    "https://www.instagram.com/reel/DcuQVFLvJMX/"
  ]
}' |
apify call webdatalabs/instagram-reels-transcript --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,webdatalabs/instagram-reels-transcript"
        }
    }
}
```

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/Ry6KQCTQWdVqIpgqf/builds/7ffRUHadNBEbcW9Ce/openapi.json
