# Instagram Reel Transcript Scraper - Speech to Text, No Login (`benthepythondev/instagram-reel-transcript-scraper`) Actor

Transcripts of public Instagram reels: the spoken text with timed segments, the detected language and the length, plus caption, date, likes and plays, one row per reel. Paste reel links or usernames. No login, no cookies. A reel without speech comes back with the reason and is not charged.

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

## Pricing

from $5.10 / 1,000 transcript minutes

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 Reel Transcript Scraper

Returns what is said in public Instagram reels, without a login or cookies. Paste reel links, or name accounts and get their newest reels: one row per reel with the transcript, the spoken lines with start and end times, the language, the length, and the reel's caption, date, likes and plays. A reel in which nobody speaks comes back with the reason instead of a made-up text.

**Price:** $0.006 per started minute of a transcribed reel on the Apify Free plan, down to $0.0051 from the Gold plan up. A reel of up to 60 seconds is one minute. Reels without a transcript (music, no audio, not found) cost nothing. Export to JSON, CSV or Excel, run on a schedule, call via API, or connect to Make, Zapier or n8n.

### 🔎 What is the Instagram Reel Transcript Scraper?

Instagram shows a visitor who is not logged in no subtitles, so this Actor listens. Instagram serves a reel's sound as a separate audio-only stream of a few hundred kilobytes. The Actor fetches that stream instead of the video file and reads it with a Whisper speech model that is built into the Actor. Nothing is sent to a third-party speech service, and there is no key to buy.

Two ways to use it:

- **Reel links.** Links to reels or video posts, or bare shortcodes. Every link gives one row.
- **Usernames.** The newest reels of each account, up to your limit. A pinned reel is placed by its real date, so three old pinned reels do not take the place of this week's reels.

#### What data does it extract?

- **Speech:** `transcript`, `segments` (each spoken line with `start`, `end` and `text`), `language`, `languageProbability`
- **Reel:** `shortCode`, `postUrl`, `caption`, `takenAt`, `durationSeconds`, `isPinned`
- **Author:** `ownerUsername`, `ownerFullName`, and `handle` (the account from your input under which the reel was listed)
- **Reach:** `likes`, `comments`, `plays`
- **Files:** `thumbnailUrl`, `videoUrl`, `audioUrl`
- **Outcome:** `status` and, when there is no transcript, `statusReason`

#### What users of Instagram transcript Actors report, and what this Actor does

The issue tabs of the six most used Instagram transcript Actors on Apify were read on October 6, 2026. They are short, and they say the same few things:

| Reported there | Here |
|---|---|
| "It did not return any data" | Every link and every username gets a row. A row without a transcript names the reason in `status` and `statusReason` |
| "Got an error, still charged" | Only rows with the status `transcribed` are charged. A reel that could not be read is a free row |
| "Duplicate transcripts" | A reel named twice, or by link and under its account, is read once. A run that is restarted reads its own dataset first: a test run killed after 24 seconds and started again ended with 12 rows, none twice |
| "It started crawl items that I didnt input" | Only the links and usernames of the input are read. An empty input reads nothing and costs nothing |

Two limits that other listings state for themselves do not apply here: there is no cap on links per run for Free plan users, and usernames lead to transcripts in the same run, with no second Actor in between.

### ⬇️ Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `usernames` | array | | Usernames, @handles or profile links. The newest reels of each account are transcribed |
| `reelUrls` | array | | Links to reels or video posts (`/reel/…`, `/p/…`, `/tv/…`) or bare shortcodes. Of a carousel the first video is transcribed |
| `maxReelsPerUsername` | integer | 3 | Newest reels per username, up to 500. Links are always read, whatever this number says |
| `language` | string | empty | Two-letter code of the spoken language (`en`, `es`, `pt`, `de`, `fr`, `hi`, `ar`, …). Empty: detected for each reel |

Both lists can be filled in one run. A profile link in `reelUrls` or a reel link in `usernames` is sorted by what it is.

#### Example input

Three links:

```json
{
  "reelUrls": [
    "https://www.instagram.com/reel/DeCPVhERA8e/",
    "https://www.instagram.com/p/DeJ6wzUsvau/",
    "DeHuihtEay1"
  ]
}
```

The ten newest reels of two accounts:

```json
{
  "usernames": ["ted", "https://www.instagram.com/bbcnews/"],
  "maxReelsPerUsername": 10
}
```

Reels of a German account, with the language given:

```json
{
  "usernames": ["tagesschau"],
  "maxReelsPerUsername": 20,
  "language": "de"
}
```

#### When to set the language

Detection listens to the first 30 seconds of speech. On a reel that opens with music, noise or a second language it can pick the wrong one, and the text is then worthless. In the tests a news reel was detected as Swahili and came back as `unclear_speech`; with `"language": "en"` the same reel gave an English transcript that fits its caption. If all reels of a run share one language, set it.

#### Coming from another Instagram transcript Actor?

The input names `handles`, `maxReelsPerHandle`, `startUrls`, `bulkUrls`, `videoUrl` and `resultsLimit` are read as well, so an input written for one of the two most used transcript Actors runs here unchanged. The output columns `status`, `statusReason`, `shortCode`, `postUrl`, `handle`, `ownerUsername`, `caption`, `transcript`, `language`, `durationSeconds`, `segments`, `takenAt`, `isPinned`, `plays`, `likes`, `comments`, `thumbnailUrl`, `videoUrl` and `audioUrl` carry the names the most used one gives them. Three differences: `language` is a code (`en`) and not a name, the opening line is `segments[0]` and has no column of its own, and text shown on screen is not read.

### ⬆️ Output

One row per reel. A real row (links shortened):

```json
{
  "status": "transcribed",
  "statusReason": null,
  "shortCode": "DeCPVhERA8e",
  "postUrl": "https://www.instagram.com/reel/DeCPVhERA8e/",
  "handle": null,
  "ownerUsername": "astro_jessica",
  "ownerFullName": "Jessica Meir",
  "caption": "Room with a view. Check out my new digs as I camp out in Dragon until our departure. With Crew-13’s arrival we have a very full house on the @iss. Luke is living in my previous crew quarters, and I’ve pitched a tent in Dragon.",
  "transcript": "Good morning from my dragon there. Now that Koo 13 has arrived, I've given up my crew quarters and I'm camping out in my dragon vehicle. Here's my view right next to my sleeping bag outside my window here, the earth and the Koo 13 dragon. A gorgeous view reminds me of my best piece of advice to them. Remember to look out the window and realize where you are. And I think that kind of advice goes for everybody down on Earth as well. Have a good day.",
  "language": "en",
  "languageProbability": 1.0,
  "durationSeconds": 27.56,
  "segments": [
    {"start": 0.0, "end": 2.44, "text": "Good morning from my dragon there."},
    {"start": 2.44, "end": 5.92, "text": "Now that Koo 13 has arrived, I've given up my crew quarters"}
  ],
  "takenAt": "2026-10-03T14:10:18+00:00",
  "isPinned": null,
  "plays": null,
  "likes": 177730,
  "comments": 1849,
  "thumbnailUrl": "https://scontent-fra3-1.cdninstagram.com/v/t51.82787-15/8347…",
  "videoUrl": "https://scontent-fra3-1.cdninstagram.com/o1/v/t2/f2/m86/AQMJ…",
  "audioUrl": "https://scontent-fra5-1.cdninstagram.com/o1/v/t2/f2/m78/AQMP…",
  "scrapedAt": "2026-10-06T15:21:21.627304+00:00"
}
```

The row is left as the model wrote it: the astronaut says "Crew-13" and the transcript has "Koo 13". That is the kind of mistake to expect, see the limits below. `plays` and `isPinned` are filled for reels listed by username; Instagram's answer for a single link has neither.

A row without a transcript has the same columns, with `transcript` empty:

| `status` | What it means |
|---|---|
| `transcribed` | The row has a transcript. The only status that is charged |
| `no_speech` | Nobody speaks: music, ambient sound or silence |
| `no_audio` | Instagram gives a visitor no audio track for this reel, usually because of licensed music |
| `unclear_speech` | Voices were found, but the text failed the model's own confidence check: noise, singing, or a language it reads poorly |
| `not_video` | The link is a post without a video |
| `not_found` | Not public: it does not exist, is private, or is shown to logged-in users only. Also the row of a username that does not exist |
| `private`, `no_reels` | The row of an account that is private or has no reels |
| `too_long` | Longer than 20 minutes |
| `failed` | Instagram or its file server did not answer. Run it again |

The run also writes a `SUMMARY` record with the number of rows per status, the minutes charged and the reason a run stopped early.

### 💰 What a run costs

| Apify plan | Per started minute of a transcribed reel |
|---|---|
| Free | $0.0060 |
| Bronze | $0.0057 |
| Silver | $0.0054 |
| Gold, Platinum, Diamond | $0.0051 |

A reel of up to 60 seconds is one minute, up to 120 seconds two, and so on. Of 88 reels from 20 accounts looked at in October 2026, 61 were a minute or shorter and the median was 36 seconds. Apify's standard start event ($0.00005 per GB of memory) is the only other charge. Speech recognition and proxies are included.

Not charged: every row whose status is not `transcribed`. Set the run's maximum charge and the Actor stops before the first reel that would pass it, with the rows it has saved.

### ⏱️ Measured on Apify (October 6, 2026)

| Run | Memory | Rows | Time |
|---|---|---|---|
| Default input: the three newest reels of one account, 4.3 minutes of audio | 2 GB | 3 | 80 s |
| One reel of 45 seconds and one link that does not exist | 2 GB | 2 | 25 s |

In a test container held to the processor share of the other sizes, two reels of 45 and 55 seconds and one with music only took 18 s at 4 GB and 64 s at 1 GB.

Memory is speed here and nothing else: a run gets a quarter of a processor core per GB, the model uses one core at most, and the test runs used about half a gigabyte at most. The price is the same at every size.

Eleven links of every kind plus one account gave 13 rows: seven transcripts in English, German, French and Arabic, two reels without speech, one without audio, a photo post, a link that does not exist and a reel with unclear speech.

### 🤖 For AI agents

Smallest useful call:

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

Each row is one reel with `status`, `transcript`, `segments`, `language`, `durationSeconds`, `caption`, `ownerUsername`, `takenAt`, `likes` and `postUrl`. `reelUrls` and `usernames` take several entries at once; with `usernames`, `maxReelsPerUsername` sets how many of the newest reels are read. Check `status`: only `transcribed` rows carry a transcript, every other row says in `statusReason` why it has none and is free. No credentials are needed.

### 💡 Use cases

- ✍️ **Repurposing:** turn your own or a client's reels into posts, newsletters and scripts without typing them out.
- 🔍 **Creator and competitor research:** search what the accounts of a niche say for hooks, claims, products and calls to action.
- 🤖 **Input for language models:** spoken text of hundreds of reels for summaries, topic tags or brand-safety checks.
- 🎬 **Subtitles:** the timed `segments` as a first draft of captions.

### ⚠️ Limits, stated plainly

- **The text is a machine transcript from a small model.** It is the base size of Whisper, chosen so that a transcript costs half a cent. On nine reels with clear speech in English and German its text differed from that of a model three times as large in 0 to 10 percent of the words. Names, brands and rare words are where it goes wrong: "Koo 13" for "Crew-13", "PSW" for the German party BSW.
- **Not every language works.** The model knows 99 languages and reads the large ones best. English, German, French and Arabic reels gave text that fits their captions in the tests. A Hindi news reel did not and came back as `unclear_speech`.
- **Speech only.** Text that is shown on screen is not read, and a reel that tells its story in captions over music is `no_speech`.
- **No audio for some reels.** 7 of 88 reels looked at came without an audio track for a visitor who is not logged in. They are returned as `no_audio`.
- **Do not count on lyrics.** Reels with music only came back as `no_speech` in the tests. Sung words were not tested.
- **Parts can be left out.** A stretch whose text fails the confidence check is dropped. `statusReason` then says how many seconds are missing. If more than half of the speech fails, the reel is `unclear_speech` and free.
- **Times per line, not per word.** `segments` are sentences or parts of sentences of a few seconds.
- **Public reels only.** The Actor does not log in. Private accounts and reels that Instagram shows to logged-in users only are not reachable.
- **20 minutes per video, 500 reels per account.**
- **One video per carousel.** Of a carousel with several videos the first is transcribed.
- **A run that finds almost nothing to transcribe stops.** After 50 rows without a transcript, plus four for every transcript, the run ends with a message, so a list of music reels does not run for hours.
- **File links expire.** `videoUrl`, `audioUrl` and `thumbnailUrl` are signed by Instagram and stop working after some hours.

### ❓ FAQ

**Do I need an Instagram account or cookies?** No. The Actor reads what Instagram shows any visitor.

**Is the transcript the same as the caption?** No. The caption is the text the author typed under the reel. The transcript is what is said in the audio. Each row has both.

**How good is the text?** Good enough to search, summarise and tag clear speech. Do not quote it without checking: names and numbers are often wrong. The limits above give the measured figures.

**Which languages?** The language is detected for each reel and returned in `language`. If you know it, set `language`: that is more reliable and a little faster.

**What happens to a reel with music only?** It becomes a `no_speech` row and costs nothing. Speech models tend to invent a few words over music; here a voice detector checks the audio first, and the model is only asked when it finds a voice.

**How are long videos charged?** By the started minute, like every reel. A video of 2 minutes and 10 seconds is three minutes. Videos longer than 20 minutes are returned as `too_long`.

**How does the username mode pick reels?** It reads the account's reels tab and takes the newest by upload time, up to `maxReelsPerUsername`. Pinned reels are marked with `isPinned` and are only included when they are among the newest.

**Can I get the newest reels of an account every day?** Yes, put the run on a schedule. A reel that was transcribed yesterday is transcribed and charged again today when it is still among the newest; keep `maxReelsPerUsername` close to what the account posts between two runs.

**How fast is it?** See the table above. Raise the memory to 4 GB for the fastest run; it costs you the same.

**Does it download the video?** No, only the audio stream: 363 KB against 6.4 MB of video for one 45-second reel. The video link is in the row if you want the file.

**Is it legal to transcribe Instagram reels?** The Actor reads only what Instagram shows publicly and does not log in. What a creator says is their content, and names in a transcript can be personal data: copyright law, GDPR, CCPA and Meta's terms apply to what you do with the text. If in doubt, ask a lawyer.

**Something is missing or broken?** Open an issue on the Actor's Issues tab with the run ID. Issues are answered within one business day.

### 🔗 You might also like

- [Instagram Reels Scraper](https://apify.com/benthepythondev/instagram-reels-scraper)
- [Instagram Posts Scraper](https://apify.com/benthepythondev/instagram-posts-scraper)
- [Instagram Comments Scraper](https://apify.com/benthepythondev/instagram-comments-scraper)
- [Instagram Profile Scraper](https://apify.com/benthepythondev/instagram-profile-scraper)
- [TikTok Transcript Scraper](https://apify.com/benthepythondev/tiktok-transcript-scraper)
- [YouTube Transcript Scraper](https://apify.com/benthepythondev/youtube-transcript-scraper)

**Keywords:** instagram reel transcript, instagram transcript scraper, instagram reels to text, instagram video to text, reel transcript generator, transcribe instagram reels, instagram speech to text, instagram transcript api, instagram reel script extractor, instagram reels subtitles, instagram captions from audio, reel transcripts in bulk, instagram creator research, instagram content repurposing, instagram transcript without login, instagram reel transcript csv

# Actor input Schema

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

Usernames, @handles or profile links. The newest reels of each account are transcribed, up to the maximum below. A pinned reel is taken at its real date, so old pinned reels do not push out new ones.

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

Links to reels or video posts (instagram.com/reel/…, /p/… or /tv/…) or bare shortcodes. Every link gives one row. Of a carousel the first video is transcribed.

## `maxReelsPerUsername` (type: `integer`):

How many of the newest reels to read for each username. It does not apply to links: every link is read.

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

Two-letter code of the language spoken in the reels, for example en, es, pt, de, fr, it, hi or ar. Leave it empty and the language is detected for each reel. Set it when all reels share one language: detection can go wrong on a reel that opens with music or noise.

## Actor input object example

```json
{
  "usernames": [
    "ted"
  ],
  "maxReelsPerUsername": 3
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (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 = {
    "usernames": [
        "ted"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("benthepythondev/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 = { "usernames": ["ted"] }

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,benthepythondev/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/qiRSgFARJPgPmjnr0/builds/ZVqY51t47lcEC2TLv/openapi.json
