# Instagram Transcript Scraper (`dami_studio/instagram-transcript-scraper`) Actor

Instagram transcript scraper: the transcript of Instagram reels and videos from Instagram's own captions: text, timed segments, SRT and VTT, language and the first three seconds, with each reel's views, likes and creator. Paste reel links, or read a profile's latest reels or a search.

- **URL**: https://apify.com/dami_studio/instagram-transcript-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Social media, Videos, AI
- **Features:** Limited permissions
- **Stats:** 9 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.93 / 1,000 reels

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

**Get the transcript of Instagram reels from Instagram's own captions**: paste reel links, or name profiles, search words or hashtags, and get one row per reel with the transcript, timed segments, SRT and WebVTT, the language and what is said in the first three seconds, next to the reel's plays, likes, comments and creator.

The transcript is the captions track Instagram itself shows on the reel, read as text. A reel without one comes back with its details and `hasTranscript: false`, and you pay only the reel's price for it.

| | |
|---|---|
| **Input** | Reel or post links, profiles, search words, hashtags, or another run's dataset |
| **Output** | One row per reel: transcript, segments with start and end times, SRT, WebVTT, language, first three seconds, word count, plays, likes, comments, shares, creator, sound, posting time |
| **Ceiling** | 2,000 reels per run, 1,000 links, 50 profiles, 20 searches and 20 hashtags |
| **Account needed** | None from you |
| **Price** | $0.93 per 1,000 reels plus $1.85 per 1,000 transcripts, the same on every plan. The free plan's $5 a month covers about 5,300 reels, or about 1,790 that all have a transcript |

| Using an AI agent? | |
|---|---|
| Actor | `dami_studio/instagram-transcript-scraper` |
| Set one field | `reelUrls`, labelled "Reel links" in the Console |
| Cap the bill | `maxTotalChargeUsd` on the run, for example `0.10`: it never charges past that |
| MCP, one link | `https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/instagram-transcript-scraper` |
| How often | Daily on a creator's profile with "Only reels not delivered before" on |

### 🔍 What Instagram Transcript Scraper does

It takes reels from four places: links you paste, the latest reels of profiles you name, the reels Instagram's search returns for a word or a hashtag, and the reel links in another run's dataset. Each reel becomes one row.

When Instagram has captions for the reel, the row carries them as plain text, as timed segments, and as ready-made SRT and WebVTT subtitle files. `hook` is what is said in the first three seconds, and `wordsPerMinute` is the speaking pace over the whole reel.

Nothing is downloaded: no video, no audio. A reel two of your inputs found arrives once.

### 📋 What data you get from each Instagram reel

| What you get | Field |
|---|---|
| Transcript and whether there is one | `transcript`, `hasTranscript`, `transcriptSource` |
| Timed segments | `segments` (each `start`, `end` in seconds, `text`) |
| Subtitle files | `srt`, `vtt` |
| Language of the captions | `transcriptLanguage` |
| First three seconds, length, pace | `hook`, `wordCount`, `wordsPerMinute` |
| Reel link, shortcode, media id | `url`, `shortcode`, `id` |
| Caption, hashtags, handles | `caption`, `hashtags`, `mentions` |
| Plays, likes, comments, shares | `playCount`, `igPlayCount`, `fbPlayCount`, `likeCount`, `commentCount`, `shareCount` |
| Length and posting time | `durationSeconds`, `postedAt` |
| Creator | `authorUsername`, `authorFullName`, `authorId`, `authorIsVerified` |
| Sound | `audioTitle`, `audioArtist`, `audioId`, `isOriginalAudio` |
| Collaborators, tagged accounts, place | `coauthors`, `taggedUsers`, `locationName` |
| Pinned and paid partnership flags | `isPinned`, `isPaidPartnership` |
| Cover and video links | `thumbnailUrl`, `videoUrl` |
| Where the reel came from | `sourceType`, `sourceInput` |

### ▶️ How to scrape Instagram reel transcripts

1. Open the actor and go to the **Input** tab.
2. Paste reel links into **Reel links**, one per line, or fill **Profiles**, **Search words** or **Hashtags**.
3. Set **Maximum reels in all** to what you need. Keep it small on a first try.
4. Press **Start**, then open the **Output** tab. The **Transcripts** view shows the text first.

### 💰 How much does it cost to scrape Instagram reel transcripts?

$0.93 per 1,000 reels, plus $1.85 per 1,000 transcripts, on every plan. A reel with a transcript costs $0.00278; one without costs $0.00093. The free plan's $5 a month covers about 5,300 reels, or about 1,790 that all have a transcript.

Not charged: note rows (a dead link, a photo post, a private account, a search with nothing), reels an earlier run already delivered when "Only reels not delivered before" is on, and duplicates inside a run.

### 📥 What you give it

| Field | What it does | Default |
|---|---|---|
| `reelUrls` | Reel or post links, bare shortcodes or share links. Up to 1,000 | none |
| `usernames` | Profiles whose latest reels you want: `nasa`, `@nasa` or a profile link. Up to 50 | none |
| `maxReelsPerProfile` | Reels read from each profile, newest first | 10 |
| `searchQueries` | Words or phrases searched on Instagram's reels search. Up to 20 | none |
| `hashtags` | Hashtags searched the same way. Up to 20 | none |
| `maxReelsPerSearch` | Reels read for each search word and hashtag | 10 |
| `datasetId` | Another run's dataset to take reel links from (`url`, `reelUrl`, `postUrl`, `inputUrl`, `shortCode`, `code`) | none |
| `maxItems` | The most reels a run delivers, across everything | 50 |
| `postedAfter`, `postedBefore` | Date window for profiles, searches and hashtags: `2026-03-01` or a span like `3 weeks` | none |
| `minViews` | Least plays a reel needs, for profiles, searches and hashtags | none |
| `skipPinnedReels` | Leave out a profile's pinned reels | false |
| `onlyNewReels` | Skip reels an earlier run with the same watchlist delivered | false |
| `watchlistName` | Name of the store in your account that remembers delivered reels | `instagram-transcripts-seen` |

Dates take `YYYY-MM-DD`, a full timestamp, or a number with day, week, month or year. Anything else stops the run before it looks anything up, with a free note saying which field to fix.

```json
{
  "reelUrls": ["https://www.instagram.com/reel/DeSM5CYPDfd/"],
  "usernames": ["nasa"],
  "maxReelsPerProfile": 5,
  "maxItems": 20
}
```

### 📤 What you get back

A real row from a run on 7 November 2026, trimmed:

```json
{
  "recordType": "reel",
  "ok": true,
  "charged": true,
  "shortcode": "DeSM5CYPDfd",
  "url": "https://www.instagram.com/reel/DeSM5CYPDfd/",
  "hasTranscript": true,
  "transcript": "For splash down. Space Flight is a beautiful symbol of humanity. Then it was time to step outside. A short time later, t ...",
  "transcriptLanguage": "en_US",
  "transcriptSource": "instagram_captions",
  "segments": [
    { "start": 0, "end": 5.421, "text": "For splash down. Space Flight is a beautiful symbol of" },
    { "start": 5.421, "end": 11.381, "text": "humanity. Then it was time to step outside. A short time" }
  ],
  "srt": "1\n00:00:00,000 --> 00:00:05,421\nFor splash down. Space Flight is a beautiful symbol of\n...",
  "hook": "For splash down. Space Flight is a beautiful symbol of",
  "wordCount": 80,
  "wordsPerMinute": 43,
  "durationSeconds": 110.766,
  "postedAt": "2026-10-09T19:02:56.000Z",
  "playCount": 3899187,
  "igPlayCount": 3746370,
  "fbPlayCount": 152817,
  "likeCount": 66849,
  "commentCount": 1011,
  "shareCount": 2677,
  "authorUsername": "nasajohnson",
  "authorFullName": "NASA’s Johnson Space Center",
  "authorIsVerified": true,
  "audioTitle": "Original audio",
  "isOriginalAudio": true,
  "coauthors": ["soph_astro", "iss", "astro_jessica", "nasa"],
  "sourceType": "profile",
  "sourceInput": "nasa"
}
```

| Field | Worth knowing |
|---|---|
| `transcript`, `segments`, `srt`, `vtt` | Empty when `hasTranscript` is false |
| `hook` | Null when nobody speaks in the first three seconds |
| `wordsPerMinute` | Words over the whole length, so a reel with long silent stretches reads slow |
| `transcriptLanguage` | The captions' language, such as `en_US` |
| `playCount` | Plays on Instagram and Facebook together; the split is `igPlayCount` and `fbPlayCount` |
| `thumbnailUrl`, `videoUrl` | Links on Instagram's servers that expire after a few days |

### 🧾 Reading the output

Real rows carry `recordType: "reel"`, `ok: true` and `charged: true`. Every one is billed as a reel, and the ones with `hasTranscript: true` are billed a transcript as well, so the dataset is its own invoice.

Note rows carry `recordType: "note"`, `ok: false` and an `errorCode`, and are never billed:

| Code | Meaning |
|---|---|
| `BAD_INPUT` | A field couldn't be read, or some entries were left out (listed in `details`) |
| `NOT_FOUND` | The reel or account isn't on Instagram |
| `NOT_A_VIDEO` | The link is a photo or carousel |
| `PRIVATE_ACCOUNT` | The profile is private |
| `NO_RESULTS` | A profile, search or hashtag gave no reels that match your filters |
| `NOT_SERVED` | Instagram didn't serve this one in this run; re-run it later |
| `ALREADY_SEEN` | How many reels the watchlist skipped |
| `MAX_ITEMS`, `COST_LIMIT`, `TIME_LIMIT` | The run stopped at your reel limit, spending limit or time limit |
| `FREE_PLAN_LIMIT` | A free-plan run stopped early; a paid plan runs the whole input |
| `UNEXPECTED_ERROR` | The run stopped on an error on our side; rows before it are kept |

To keep only transcripts, filter on `hasTranscript == true`.

### 💡 What people use it for

- Content teams studying what top creators in their niche actually say: a profile's last 50 reels, sorted by `playCount`, read through `hook`.
- Turning a brand's own reels into blog drafts or newsletter text without retyping them.
- Subtitles for reposting a reel elsewhere: take `srt` or `vtt` as they are.
- Feeding reel text to a language model for topic or sentiment tagging, with `segments` when timing matters.

A recipe that chains our actors: find reels with [Instagram Reels Search Scraper](https://apify.com/dami_studio/instagram-reels-search-scraper), pass its dataset ID to `datasetId` here, and run [Instagram Comments Scraper](https://apify.com/dami_studio/instagram-comments-scraper) on the reels whose `hook` you liked.

### 🚧 What it does not do

- No transcript for a reel Instagram has no captions for. For those, give the row's `videoUrl` to [Video Audio Transcriber](https://apify.com/dami_studio/video-audio-transcriber), which works from the audio.
- No translation of the transcript.
- No private accounts, stories or direct messages.
- No downloads of the video or the audio.
- It is not an official Instagram tool. Dami's Studio is independent and is not affiliated with or endorsed by Instagram or Meta, or by any other company named on this page.

### 🧭 Which Instagram scraper do you need?

| If you want | Use |
|---|---|
| Transcripts of reels, with their numbers | This one, [Instagram Transcript Scraper](https://apify.com/dami_studio/instagram-transcript-scraper) |
| Reels for a keyword or hashtag, without transcripts | [Instagram Reels Search Scraper](https://apify.com/dami_studio/instagram-reels-search-scraper) |
| Comments under a reel or post | [Instagram Comments Scraper](https://apify.com/dami_studio/instagram-comments-scraper) |
| Bio, follower counts and contact details of the creators | [Instagram Profile Scraper](https://apify.com/dami_studio/instagram-profile-scraper) |
| A transcript from the audio of any video link | [Video Audio Transcriber](https://apify.com/dami_studio/video-audio-transcriber) |
| Transcripts of TikTok videos | [TikTok Transcript Scraper](https://apify.com/dami_studio/tiktok-transcript-scraper) |

### ❓ Questions people ask

#### Do I need an Instagram account to get reel transcripts?

No, you don't need one, and there's no cookie to paste.

#### Why does a reel have no transcript?

Instagram makes captions for many reels, not all of them. The row still comes with the reel's details. To check a reel by hand, open it in the Instagram app and look for the captions button.

#### Why are the numbers different from what I see in the app?

Plays, likes and comments keep moving, and the app rounds them ("1.2M"). The row has the exact count at the moment it was read.

#### Can I call it from code or connect it to an AI assistant?

Yes. The **API** tab on the actor page has ready code. For an assistant, use the MCP link `https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/instagram-transcript-scraper`.

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("dami_studio/instagram-transcript-scraper").call(
    run_input={"reelUrls": ["https://www.instagram.com/reel/DeSM5CYPDfd/"], "maxItems": 10},
    max_total_charge_usd=0.10,
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row.get("ok") is False:
        continue
    print(row["url"], row["transcript"])
```

#### Is scraping Instagram legal?

This reads public reels only, never private accounts or messages, and you need no account. Results can still contain personal data, which GDPR and similar laws cover, so keep only what you need. Instagram's own terms still apply to what you do with the data. Apify's write-up on [the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) is a good starting point, and we are not lawyers.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Include the run ID and one of the links or names you used.

# Actor input Schema

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

Reel or post links, one per line, such as https://www.instagram.com/reel/DeSM5CYPDfd/. A bare shortcode (DeSM5CYPDfd) and share links work too. Up to 1,000 a run.

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

Accounts whose latest reels you want, as nasa, @nasa or a profile link. Up to 50 a run. Private accounts come back as a free note row.

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

How many of each profile's most recent reels to read. The date, views and pinned filters below apply to these.

## `searchQueries` (type: `array`):

Words or short phrases. The run reads the reels Instagram's search returns for each one, from any creator. Up to 20.

## `hashtags` (type: `array`):

Hashtags, with or without the #. The run reads the reels Instagram's search returns for each tag. Up to 20.

## `maxReelsPerSearch` (type: `integer`):

How many reels to read for each search word and each hashtag.

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

A dataset in your account, for example an Instagram scraper's results. The run reads the reel and post links from its url, reelUrl, postUrl, inputUrl, shortCode or code fields and adds them to the reel links above. It only reads that dataset.

## `maxItems` (type: `integer`):

The run stops after this many reels, across every input above, so a long list can't cost more than you expect. Keep it small while testing.

## `postedAfter` (type: `string`):

Profiles, searches and hashtags only: keep reels posted on or after this date (UTC). A date like 2026-03-01, or a span back from today like "3 weeks" or "7 days". Leave empty for no start date.

## `postedBefore` (type: `string`):

Profiles, searches and hashtags only: keep reels posted on or before this date (UTC), the whole day included. A date like 2026-03-31, or a span like "1 week". Leave empty for no end date.

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

Profiles, searches and hashtags only: keep reels with at least this many plays. Leave empty to keep every reel.

## `skipPinnedReels` (type: `boolean`):

Profiles only: leave out the reels an account has pinned to the top of its profile, which are often old.

## `onlyNewReels` (type: `boolean`):

Skip reels that an earlier run with the same watchlist name already delivered. They're not looked up again and not charged. Handy on a schedule. The list lives in a key-value store of that name in your own account.

## `watchlistName` (type: `string`):

The name of the store that remembers delivered reels, used with "Only reels not delivered before". Letters, digits and dashes. Use one name per job you schedule.

## `speechToText` (type: `boolean`):

For reels without Instagram captions, make the transcript from the reel's speech. Paid as a transcript. Reels up to 90 seconds long.

## Actor input object example

```json
{
  "reelUrls": [
    "https://www.instagram.com/reel/DeSM5CYPDfd/"
  ],
  "maxReelsPerProfile": 10,
  "maxReelsPerSearch": 10,
  "maxItems": 50,
  "skipPinnedReels": false,
  "onlyNewReels": false,
  "watchlistName": "instagram-transcripts-seen",
  "speechToText": false
}
```

# Actor output Schema

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

Every row in the default dataset. recordType is reel for a reel and note for a free row that explains something.

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

The reels with their transcripts, in the Transcripts view.

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

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/instagram-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/DeSM5CYPDfd/"] }

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

```

## MCP server setup

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