# Instagram Reels Transcript Scraper: Speech to Text (`wheaten_steelpan/instagram-reel-transcript-scraper`) Actor

Transcribe Instagram reels to text, timestamped segments, SRT and VTT from reel URLs or a profile's newest reels, logged out. Music-only, private, removed and unsupported-language reels are never charged.

- **URL**: https://apify.com/wheaten_steelpan/instagram-reel-transcript-scraper.md
- **Developed by:** [Vanja V](https://apify.com/wheaten_steelpan) (community)
- **Categories:** Social media, Videos, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 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.

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: Speech to Text

Turn Instagram reels into text. Paste reel links or profile handles and get each reel's spoken words as plain text, timestamped segments, SRT and WebVTT subtitles, with the caption, posting time and like count. No Instagram account or cookies needed.

**$0.008 per transcribed reel** up to 3 minutes, plus $0.003 for each started minute beyond that. No start fee. Music-only reels, photo posts, private or removed reels and reels in an unsupported language cost nothing.

![Output rows from a real run: reel code, account, status, language, length, transcript, and the reason a reel wasn't charged](https://api.apify.com/v2/key-value-stores/yahOaOYfw9AeeeEse/records/output-example.png)

### What it's for

- **Repurpose video into text.** Turn your own or a client's reels into blog posts, newsletters, captions or show notes.
- **Study what works in a niche.** Pull a creator's newest reels and read what they say, next to likes and posting time.
- **Subtitles.** Get SRT or VTT files ready to load into a video editor or upload with a re-post.
- **Search and analysis.** Feed transcripts to an LLM, a search index or a spreadsheet.
- **Give an AI agent Instagram video content**, through Apify's MCP server or the API (examples below).

### Example

Input:

```json
{
    "profiles": ["natgeo"],
    "maxReelsPerProfile": 5
}
```

One output row (shortened):

```json
{
    "url": "https://www.instagram.com/reel/De1S3KpCXf0/",
    "shortcode": "De1S3KpCXf0",
    "profile": "natgeo",
    "ownerUsername": "natgeo",
    "caption": "…@joelsartore loves these little creatures, and so do we…",
    "postedAt": "2026-10-23T10:01:35Z",
    "durationSec": 23.75,
    "viewCount": null,
    "likeCount": 67508,
    "status": "ok",
    "language": "en",
    "languageProbability": 0.999,
    "text": "You are looking at nudibranx. You've never seen anything that crazy looking? Every color in the rainbow. These are marine snails basically that have lost their shells over time…",
    "segments": [
        { "start": 0, "end": 2, "text": "You are looking at nudibranx." },
        { "start": 2, "end": 3.76, "text": "You've never seen anything that crazy looking?" }
    ],
    "srt": "1\n00:00:00,000 --> 00:00:02,000\nYou are looking at nudibranx.\n\n2\n…",
    "vtt": "WEBVTT\n\n00:00:00.000 --> 00:00:02.000\nYou are looking at nudibranx.\n\n…",
    "error": null
}
```

### What you get

| Field | What it is |
|---|---|
| `url`, `shortcode` | Reel link and Instagram's short code |
| `profile` | The profile from your input this reel came from; `null` for reel links you gave directly |
| `ownerUsername` | Account that posted the reel (a collab reel on a profile can belong to another account) |
| `caption`, `postedAt` | Caption and posting time (UTC) |
| `durationSec` | Audio length in seconds |
| `viewCount`, `likeCount` | Counts when Instagram shows them to logged-out visitors |
| `status` | `ok` or the reason there's no transcript (below) |
| `language`, `languageProbability` | Spoken language and detection confidence (`null` when you set the language) |
| `text` | Full transcript |
| `segments` | Transcript in timestamped pieces: `start`, `end` (seconds), `text` |
| `srt`, `vtt` | Subtitles in SRT and WebVTT |
| `error` | Why there's no transcript, in a plain sentence |

Every reel gets a row, including the ones that fail, so you can see what happened to each link. The dataset has two views: **Transcripts** (reel, account, status, transcript) and **Subtitles**.

#### Statuses

| Status | Meaning | Charged |
|---|---|---|
| `ok` | Transcribed | Yes |
| `no_speech` | Silence or music only | No |
| `no_video` | A photo or carousel post | No |
| `unsupported_language` | Auto-detect found a language outside the supported list; `language` shows which | No |
| `private_or_removed` | The reel is private, deleted or the link is wrong | No |
| `login_required` | Instagram showed this reel or profile only to logged-in visitors | No |
| `unreachable` | Instagram kept refusing the request after retries | No |
| `too_long` | Longer than your *Longest video* setting | No |
| `skipped_budget` | Not processed because the run reached your maximum cost | No |
| `failed` | Something else went wrong; `error` says what | No |

### Input

- **Reel URLs**: links to reels or video posts (`/reel/`, `/reels/` or `/p/`). Duplicates are removed.
- **Profiles**: handles (`natgeo`, `@natgeo`) or profile links. The Actor transcribes the newest reels of each public profile.
- **Reels per profile** (default 12, up to 200): how many of the newest reels to take from each profile. A pinned reel counts only if it's among the newest.
- **Language** (default auto-detect): English, Spanish, German, Portuguese, French, Italian, Indonesian or Arabic. With auto-detect, reels in any other language are marked `unsupported_language`. Setting a language skips detection and transcribes every reel in that language.
- **Output formats** (default all four): plain text, timestamped segments, SRT, WebVTT. Formats you leave out are `null`.
- **Longest video (minutes)** (default 15, up to 60): longer videos are marked `too_long`.

You can mix reel links and profiles in one run.

### Pricing

| Reels (up to 3 minutes each) | Price |
|---|---|
| 100 | $0.80 |
| 1,000 | $8.00 |
| 10,000 | $80.00 |

- A reel longer than 3 minutes adds $0.003 for each started minute past 3. A 4-minute reel costs $0.011, and a 10-minute video costs $0.029.
- Apify's platform usage is included, and there's no start fee.
- You pay only for `ok` rows. Every other status is free, so a profile full of music reels costs nothing.
- To cap what a run can cost, set a maximum cost when you start it (`maxTotalChargeUsd` in the API). Reels the Actor doesn't get to are listed as `skipped_budget`, free.

### Use it through the API

Run it and get the rows back in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/wheaten_steelpan~instagram-reel-transcript-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"reelUrls": ["https://www.instagram.com/reel/DehZj9wggt0/"], "outputFormats": ["text"]}'
```

That call waits at most 5 minutes. For bigger runs, the Apify clients start the run and wait for it to finish.

JavaScript (`npm install apify-client`):

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('wheaten_steelpan/instagram-reel-transcript-scraper').call({
    profiles: ['natgeo', 'nasa'],
    maxReelsPerProfile: 10,
    outputFormats: ['text', 'srt'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const reel of items) console.log(reel.url, reel.status, reel.text);
```

Python (`pip install apify-client`):

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("wheaten_steelpan/instagram-reel-transcript-scraper").call(run_input={
    "reelUrls": ["https://www.instagram.com/reel/DehZj9wggt0/"],
    "language": "en",
})
for reel in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(reel["url"], reel["status"], reel["text"])
```

### Use it from an AI agent (MCP)

Add Apify's MCP server with this Actor as its tool, for example in Claude Desktop, Cursor or VS Code:

```json
{
  "mcpServers": {
    "instagram-transcripts": {
      "url": "https://mcp.apify.com?tools=wheaten_steelpan/instagram-reel-transcript-scraper"
    }
  }
}
```

Clients that support OAuth sign you in to Apify on first use. Other clients can send your token in a header: `"headers": { "Authorization": "Bearer <APIFY_TOKEN>" }`.

### Speed and limits

- In our tests on Apify, 52 reels took about 11 minutes, roughly 12 seconds per reel. Rows appear in the dataset as each reel finishes.
- Every run downloads and transcribes each reel fresh, with no cached results.
- Instagram reels carry no subtitle tracks for logged-out visitors, so the Actor transcribes the audio itself with OpenAI's Whisper model. Clear speech comes out well. Rare words and names can be misspelled (in the example, "nudibranchs" became "nudibranx"), and heavy background music lowers accuracy.
- Reels with music and a few spoken words can come back as `no_speech` when the speech is too short or unclear to transcribe reliably. That keeps song lyrics and noise out of your data, and those reels are free.
- The Actor reads Instagram logged out. Some accounts and reels are shown only to logged-in visitors; those come back as `login_required`, free.
- Profiles list reels newest first. Profile mode needs a public profile.
- Captions, likes and views are what Instagram shows logged-out visitors at run time. Instagram often hides views.

### Notes

- This Actor reads public Instagram pages and isn't affiliated with Meta or Instagram.
- Transcripts and captions contain personal data (usernames, what people say). You're responsible for using the data lawfully, including data-protection laws such as the GDPR where they apply, and for respecting the creators' copyright when you republish their words.
- Found a problem or need a field or language? Open an issue in the Issues tab.

# Actor input Schema

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

Links to Instagram reels or video posts (/reel/, /reels/ or /p/). Each reel becomes one row. Duplicates are removed.

## `profiles` (type: `array`):

Instagram handles (natgeo or @natgeo) or profile URLs. The newest reels of each public profile are transcribed, one row per reel.

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

How many of the newest reels to transcribe from each profile. Pinned reels count only if they are among the newest.

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

With auto-detect, reels in any other language are reported as unsupported_language and not charged. Setting a language skips detection and transcribes every reel in that language.

## `outputFormats` (type: `array`):

What each row contains: plain text, timestamped segments, SRT subtitles, WebVTT subtitles. Fields you leave out are null.

## `maxReelMinutes` (type: `integer`):

Videos longer than this are reported as too_long and not charged.

## Actor input object example

```json
{
  "reelUrls": [
    "https://www.instagram.com/reel/DehZj9wggt0/"
  ],
  "maxReelsPerProfile": 12,
  "language": "auto",
  "outputFormats": [
    "text",
    "segments",
    "srt",
    "vtt"
  ],
  "maxReelMinutes": 15
}
```

# Actor output Schema

## `transcripts` (type: `string`):

One row per reel with account, posting date, status, language, duration and the plain-text transcript.

## `data` (type: `string`):

Every field of every row, including timestamped segments, SRT and VTT.

# 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/DehZj9wggt0/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("wheaten_steelpan/instagram-reel-transcript-scraper").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/DehZj9wggt0/"] }

# Run the Actor and wait for it to finish
run = client.actor("wheaten_steelpan/instagram-reel-transcript-scraper").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/DehZj9wggt0/"
  ]
}' |
apify call wheaten_steelpan/instagram-reel-transcript-scraper --silent --output-dataset

```

## MCP server setup

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

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/cV48vBMKgc67bpSvp/builds/rRMhKVoaQwH6YMNf3/openapi.json
