# Instagram Audio Scraper — Reels Using a Sound, with Transcripts (`steadyfetch/instagram-audio-reels-scraper`) Actor

Instagram audio scraper: paste a sound page link and get the sound (title, artist, song or original audio, reel count) plus the reels using it, with caption, author, plays, likes and comments, and what each reel says on request. No login. A row that cannot be delivered is never charged.

- **URL**: https://apify.com/steadyfetch/instagram-audio-reels-scraper.md
- **Developed by:** [Steadyfetch Team](https://apify.com/steadyfetch) (community)
- **Categories:** Social media, Automation, Videos
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 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.
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 Audio Scraper — Reels Using a Sound, with Transcripts

**Instagram audio scraper: paste a sound's page link and get the sound itself (title, artist or owner, song or original audio, how many reels Instagram counts on it) plus the reels that use it, with caption, author, posted time, plays, likes and comments. Switch on transcripts and each reel also comes back with what the creator says over the sound. Reels from $0.60 per 1,000.**

Paste one or more Instagram sound links (tap the sound name at the bottom of any reel and copy the page link, it contains `/reels/audio/`), or just the number at the end of the link. Songs from Instagram's music library and "Original audio" both work. No login, no cookies, no proxy to set up. A sound that could not be read, a reel that could not be delivered and a transcript that was not produced are never charged, and nothing is charged for starting a run.

**Coming back for fresh reels?** Save the same input as a task and run it on Apify's Schedules, for example `{ "audioUrls": ["https://www.instagram.com/reels/audio/1467739367151376/"] }`. With "New reels only" on (the default), reels already delivered to your account are skipped and not charged, so each run brings back the sound's new reels and its current reel count. Weekly suits a song's long tail; daily suits a sound that is trending now.

**Using an AI agent?** Pin this actor in Apify's MCP server with one link: `https://mcp.apify.com?tools=steadyfetch/instagram-audio-reels-scraper`

- **Actor id:** `steadyfetch/instagram-audio-reels-scraper`
- **Input:** `{ "audioUrls": ["https://www.instagram.com/reels/audio/1467739367151376/"], "maxReelsPerAudio": 50, "includeTranscripts": true }` — `audioUrls` is the one field you have to set.
- **Cap the bill:** set `maxTotalChargeUsd` on the run (a run option, not Actor input), e.g. `0.50` — the run stops when it reaches it.
- **Price:** $0.004 per sound read, $0.0015 per reel on the Apify free plan and from $0.0006 on paid plans, $0.006 per transcript produced. Full table below.

*Unofficial. Not affiliated with, endorsed by, or sponsored by Instagram or Meta Platforms, Inc.*

### What you get

First one **sound row** for each sound (`rowType: "sound"`):

| Column | What it holds |
|---|---|
| `soundTitle` · `soundArtist` · `soundOwnerUsername` | the sound's name, and its artist (a song) or the account that posted it (an original audio) |
| `soundType` | `music` (a song from Instagram's music library) or `original` (an "Original audio") |
| `reelCount` · `reelCountText` | how many reels Instagram counts on the sound, exact and as Instagram shows it ("2.5M reels") |
| `soundDurationSeconds` · `isExplicit` · `isTrending` | length, the explicit flag, and whether Instagram marks it trending |
| `soundUrl` · `audioId` · `spotifyUrl` | the sound's page, its id, and for a song the Spotify track |

Then one **reel row** per reel using the sound (`rowType: "reel"`):

| Column | What it holds |
|---|---|
| `shortCode` · `url` · `takenAt` | the reel and when it was posted |
| `caption` · `hashtags` · `mentions` | what the creator wrote |
| `ownerUsername` · `ownerFullName` · `ownerIsVerified` | who posted it |
| `playCount` · `likeCount` · `commentCount` · `videoDuration` | how it is doing, and how long it is |
| `transcript` · `transcriptLanguage` · `transcriptSegments` | what the creator says, timestamped (transcripts on) |
| `charged` · `chargedEvents` · `status` · `statusReason` | what the row was charged, and why it says what it says |

Every column is always present; a value Instagram does not show is `null`, never missing. The sound file itself is never part of a row.

### What a row looks like

```json
{
  "rowType": "reel",
  "audioId": "1467739367151376",
  "soundUrl": "https://www.instagram.com/reels/audio/1467739367151376/",
  "shortCode": "DSAMPLE0001",
  "url": "https://www.instagram.com/p/DSAMPLE0001/",
  "caption": "Morning routine, this song on repeat",
  "takenAt": "2026-10-16T14:52:47.000Z",
  "playCount": 58720,
  "likeCount": 1201,
  "commentCount": 6,
  "videoDuration": 12.003,
  "ownerUsername": "sample_account",
  "transcript": "Three things I do before eight every morning…",
  "transcriptLanguage": "English",
  "charged": true,
  "chargedEvents": { "reel": 1, "reel-transcript": 1, "sound": 0 },
  "status": "delivered"
}
```

### Price

You pay per event, and only for what was delivered:

| Event | When it is charged | Apify free plan | Bronze | Silver | Gold and up |
|---|---|---|---|---|---|
| `sound` | once per sound read in a run — its own row | $0.004 | $0.004 | $0.004 | $0.004 |
| `reel` | each new reel using the sound, delivered | $0.0015 | $0.0012 | $0.0009 | $0.0006 |
| `reel-transcript` | each transcript actually produced (opt-in) | $0.006 | $0.006 | $0.006 | $0.006 |

Examples: one sound with 50 reels is $0.079 on the Apify free plan and $0.034 from Gold. The same with transcripts is $0.379 / $0.334. No start fee, ever. Reels up to 180 seconds are transcribed; a longer one, or one whose video is too large to fetch at its length, is delivered without a transcript and says so.

**For a faster run, raise the memory.** A run starts at 512 MB by default. With transcripts on, more memory lets each reel's audio be read faster; the price per reel is the same at any memory.

### What a second run costs

Only reels new to your account are charged. Every run remembers, in a key-value store in your own Apify account (`ig-audio-reels-account`), which reels it delivered. With **"New reels only"** on (the default), a later run of the same sound skips them: no row and no charge, and the next new reel takes the slot. After two pages in a row that hold only reels you already have, the sound is closed on a bounded number of pages and its row says so. Turn the switch off and the reels you already have come back, marked `repeat: true`, with no result fee and no second transcript.

The sound's own row is delivered and charged on every run, a repeat run included: its reel count and trending flag are what moves between runs, and its fee is what reading the sound costs. A transcript is charged only when one was actually produced.

### Honest rows: what "not charged" actually means

Every sound that returns fewer reels than you asked for gets one row saying which of these happened:

- `no_reels` — the sound's list ended, Instagram counts no reels on it, or this actor's own read depth or repeat backstop closed it; the row says which.
- `stopped_at_limit` — your own limit (reels per sound, maximum cost, run seconds) stopped it.
- `source_unavailable` — the read did not go through; a re-run is the fix.
- `source_refused` — Instagram shows no page for that sound (a mistyped or removed sound); the same answer every time.
- `unsupported_shape` — Instagram answered in a shape this actor does not read yet; on us, and also the same every time.
- `limit_reached` — this run reached its limit; the row says whether a new run continues now.
- `user_input` — a value that is not a sound (a reel link, a profile link, a song name); the row says how to find the sound's link.

None of these is charged, and the run still finishes successfully. A time limit ends the collecting, never the delivering: rows already in hand are always written out. The last row is the run's own summary: sound rows and reels delivered, what was asked for, and what stopped it. Results may fail when Instagram changes; failed items are never charged.

### How often this data changes

A trending sound gains reels every hour and its reel count moves daily; a song's long tail moves weekly. Instagram lists a sound's reels in its own order, so a later run finds the reels posted since as well as ones the earlier pages did not reach. Play, like and comment counts on a reel move most in its first days. For tracking a sound, a daily or weekly run of the same input with "New reels only" on is what most buyers need: it delivers the new reels and the current reel count, and your memory of what you already have lives in `ig-audio-reels-account`.

### Use it as an API endpoint (Standby)

Every input above also works as one HTTP request to this actor's endpoint (also on its Endpoints tab), by GET with the fields in the query string or by POST with the same fields as a JSON body:

```bash
curl -H "Authorization: Bearer <YOUR_APIFY_TOKEN>" \
  "https://steadyfetch--instagram-audio-reels-scraper.apify.actor/?audioUrls=1467739367151376&maxReelsPerAudio=20&includeTranscripts=true"
```

| Setting | What it does |
|---|---|
| `audioUrls` | A sound page link (URL-encoded) or the sound's number. Repeat it for more than one. |
| `maxReelsPerAudio` | How many reels for each sound. 50 if you leave it out. |
| `includeTranscripts` | `true` adds what each reel says. |

The sound rows and the reels come back in the response as JSON, with the same columns as dataset rows, charged at the same prices as a run. One request takes up to 5 sounds and 100 reels in all, 20 with transcripts (1 sound and 50 reels, 5 with transcripts, on the Apify free plan). The endpoint keeps no memory of what you already have, so every request reads fresh. A request whose first charge cannot be completed sends nothing.

### Limits and good manners

- **Max reels per sound:** 50 by default, up to 480 (40 pages of 12). Above that the run continues at 480 and one uncharged row says so.
- **Reel links and song names are not this actor's input.** It reads a sound's page; a reel link is refused on an uncharged row that says how to open its sound. To get one reel's words, use the Instagram Reel Transcript Scraper.
- Only public data: what Instagram shows any visitor on a sound's page.

### Related actors

- [Instagram Reel Transcript Scraper](https://apify.com/steadyfetch/instagram-reel-transcript-scraper) — the words of reels you already have links to.
- [Instagram Reels Keyword Search Scraper](https://apify.com/steadyfetch/instagram-keyword-reels-scraper) — reels found by a search phrase, with transcripts.
- [Instagram Hashtag Scraper](https://apify.com/steadyfetch/instagram-hashtag-scraper) — the posts under a hashtag or keyword.
- [Instagram Profile Posts Scraper](https://apify.com/steadyfetch/instagram-profile-posts) — one account's own posts and reels.

### Reliability

Every row says what it was charged. A read that fails is tried again before it is reported; a row that cannot be delivered is never charged; and the run never ends on a limit it set itself without saying so on the last row.

### Support

Questions, a sound that returns something odd, or a column you need: open an issue on the Issues tab and it will be looked at.

If it earned its keep, a rating helps other buyers find it, and saving the actor keeps it one click away.

# Changelog

This Actor's version history is a separate document: https://apify.com/steadyfetch/instagram-audio-reels-scraper/changelog.md

# Actor input Schema

## `audioUrls` (type: `array`):

Instagram sound page links, one per entry, e.g. \["https://www.instagram.com/reels/audio/1467739367151376/"] — or just the number at the end of the link. Each sound is read once per run and costs one `sound` event. A reel link, a profile link or a song name is refused with an uncharged row that says how to find the sound's link. Leave it empty and the run returns built-in sample rows instead of collecting anything, so you can see the output shape at no result fee.

## `maxReelsPerAudio` (type: `integer`):

Hard cap on the reels delivered for EACH sound, in the order Instagram lists them on the sound's page (12 a page). A sound with fewer reels leaves an uncharged row saying so. At most 480 per sound in one run: ask for more and the run continues at 480, with an uncharged row saying so.

## `includeTranscripts` (type: `boolean`):

OFF (default): reel rows carry the caption and metadata only. ON: every delivered reel also carries `transcript`, `transcriptLanguage` and timestamped `transcriptSegments`, at $0.006 per produced transcript on top of the reel price. Reels longer than 180 seconds, or too large to fetch at their length, are delivered without a transcript and say so. Give "Max run seconds" over 2 minutes with this on, or the run may stop before it reads anything.

## `newReelsOnly` (type: `boolean`):

ON (default): a reel already delivered to your account is skipped — no row, no charge — and the next new reel takes its place; after two pages in a row with nothing new the sound is closed and an uncharged row says so. OFF: those reels are delivered again anyway, marked `repeat: true`, without a transcript leg and not charged. The sound's own row is delivered and charged on every run either way. Reels older than 90 days in your account's memory count as new again.

## `maxRunSeconds` (type: `integer`):

The run stops cleanly before this many seconds and reports what is left, instead of being killed by a timeout. A time limit ends the collecting, never the delivering: rows in hand are always written out. With transcripts on, budget 4-6 seconds per reel and over 2 minutes in total — up to 90 seconds are held back for the last transcript, so a short window reads nothing. At most 3,600 seconds and at least 30: ask outside that and the run continues at the nearest, with an uncharged row saying so.

## `resumeFromDatasetId` (type: `string`):

The dataset ID of a previous run of this actor. Reels already in it are treated as reels you already have and are skipped, so a follow-up run collects only what is new even from a different Apify account. Selecting it here is what grants this run permission to read it.

## Actor input object example

```json
{
  "audioUrls": [],
  "maxReelsPerAudio": 50,
  "includeTranscripts": false,
  "newReelsOnly": true,
  "maxRunSeconds": 600
}
```

# Actor output Schema

## `rows` (type: `string`):

First a `sound` row for each sound (`rowType: "sound"`): title, artist (a song) or owner (an original audio), `soundType`, length, explicit and trending flags, the reel count Instagram shows, the sound page link and, for a song, the Spotify track — charged as one `sound` event, on every read of that sound. Then one `reel` row per reel using it: caption, hashtags, mentions, engagement, media links, author and the permalink — and, with transcripts on, the spoken words with language and timestamped segments. Every row carries `charged` and `chargedEvents` naming `sound`, `reel` and `reel-transcript`; `transcriptCharged` is true only on a reel whose `transcriptStatus` is `transcribed`. A reel with no speech, no audio track, an expired media link, a speech-service problem a length over 180 seconds, or a video too large to fetch at its length is delivered with `transcript: null`, its `transcriptStatus` naming which, and no transcript charge. Reels your account already had are skipped and never charged again — that check reads a key-value store in your own account, so a run on a scoped API token without key-value store permission cannot make it and says so on its status line and on an uncharged row. The sound file itself is never part of a row.

## `sounds` (type: `string`):

The sound rows only — one per sound read, each charged one `sound` event.

## `misses` (type: `string`):

One uncharged row for every sound that returned less than it was asked for, saying which of six things happened: `no_reels` (the sound's list ended, Instagram counts no reels on it, or this actor's own read depth or repeat backstop closed it — the row says which), `stopped_at_limit` (one of your own limits or the run clock stopped it first), `source_unavailable` (the read failed and a re-run is the fix), `source_refused` (Instagram shows no page for that sound — the same answer every time), `unsupported_shape` (Instagram answered in a shape this actor does not read yet — on us, and also the same every time), `limit_reached` (this run reached its limit — the row says whether a new run continues now or this actor has paused collection until next month). A value that is not a sound gets a `user_input` row naming how to find the sound's link; a limit you typed above this actor's own ceiling adds one `input_note` row. None of these is charged.

## `summary` (type: `string`):

Sound rows and reels delivered, transcripts produced, what was asked for, reels your account already had, reels that appeared under more than one sound, what stopped the run, the charged-event totals for `sound`, `reel` and `reel-transcript`, and — when this run's token could not open the repeat memory — `repeatCheck: "unavailable_scope"`.

# 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 = {
    "audioUrls": []
};

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

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

```

## MCP server setup

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