# Instagram Reel Scraper (`badr_xba/instagram-reel-scraper`) Actor

Scrape the latest reels of any public Instagram profile, or any reel URL, without an account: plays, views, likes, comments, caption, hashtags, mentions, tagged users, sponsors, music, location and the latest comments. Optional MP4 download. Pay per reel.

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

## Pricing

from $1.00 / 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 Reel Scraper – Views, Likes, Comments & Music

Extract data from **public Instagram reels without an account or API key**. Add Instagram **usernames, profile URLs or reel URLs** and get, for every reel: **plays, views, likes, comments**, caption, hashtags, mentions, tagged users, sponsors and paid partnership, co-authors, **music** (artist, song, original audio), location, duration, pinned status and the **10 latest comments**. Optionally add the **shares count** and **download each reel as an MP4**. **Pay per reel** — inputs that give nothing are never billed.

### What can Instagram Reel Scraper do?

- 🎥 Stats of the latest reels of any public profile: likes, comments, views, plays, date
- 🧩 Metadata: caption, hashtags, mentions, tagged users, pinned status, paid partnership and sponsors, co-authors, music, location, dimensions, duration
- 💬 The 10 latest comments of each reel, with author, likes and date
- ⬇️ MP4 download of each reel to your run storage (add-on), before Instagram's links expire
- 📆 Date filter and skip pinned reels
- Export to JSON, CSV, Excel, XML or HTML, or use the API, webhooks, Make, Zapier, n8n or the Apify MCP server

Use it for influencer research, campaign tracking, competitor monitoring and content audits.

### How to scrape Instagram reels in 3 steps

1. **Add** usernames (`natgeo`), profile URLs or reel URLs (`https://www.instagram.com/reel/DX7lzTOJ1p6/`).
2. **Set** the number of reels per profile (optional: date filter, skip pinned reels, shares count, video download).
3. **Click Start**, then open the **Reels** table or download JSON, CSV or Excel.

The prefilled run (natgeo, 12 reels) takes about half a minute and costs about three cents on the Free plan.

Paste inputs the way you have them: `@natgeo`, mobile links, links with `?igsh=…`, the profile's `/reels/` tab, or a comma-separated list on one line. The same profile given twice is read (and billed) once. Anything that is not a profile or reel (a hashtag, an audio page, a typo) is listed in **FAILED_INPUTS** with the reason, never billed, and the run carries on.

### Input example

```json
{
  "username": ["natgeo", "https://www.instagram.com/reel/DX7lzTOJ1p6/"],
  "resultsLimit": 12,
  "onlyPostsNewerThan": "2 months",
  "skipPinnedPosts": true,
  "includeSharesCount": false,
  "includeDownloadedVideo": false
}
```

### Output example

```json
{
  "inputUrl": "natgeo",
  "id": "3889868956217334394",
  "type": "Video",
  "shortCode": "DX7lzTOJ1p6",
  "caption": "this is your sign to stop neglecting your scalp 🤭 #ad",
  "hashtags": ["ad"],
  "mentions": ["dysonusa", "sephora"],
  "url": "https://www.instagram.com/reel/DX7lzTOJ1p6/",
  "commentsCount": 24,
  "firstComment": "Yes to scalp care!! 👏🏼",
  "latestComments": [{ "text": "Yes to scalp care!! 👏🏼", "ownerUsername": "travelingwithjessica", "likesCount": 1, "timestamp": "2026-05-07T23:29:01.000Z" }],
  "likesCount": 286,
  "videoViewCount": 4073,
  "videoPlayCount": 10977,
  "timestamp": "2026-05-04T21:05:19.000Z",
  "ownerUsername": "lyssamariexo",
  "productType": "clips",
  "videoDuration": 51.15,
  "isPinned": false,
  "paidPartnership": true,
  "sponsors": [{ "id": "23818608", "username": "sephora" }],
  "taggedUsers": [{ "username": "sephora", "full_name": "Sephora", "is_verified": true }],
  "musicInfo": { "artist_name": "lyssamariexo", "song_name": "Original audio", "uses_original_audio": true },
  "isCommentsDisabled": false
}
```

Every run also writes **RUN_SUMMARY** (reels saved, add-ons, amount charged) and **FAILED_INPUTS** (inputs that gave nothing, with the reason — never billed).

### How much does it cost to scrape Instagram reels?

Pay per event. Platform usage is included.

| Event | Free | Starter | Scale | Business |
|---|---|---|---|---|
| **Reel** | $2.60 / 1,000 | $2.30 / 1,000 | $1.40 / 1,000 | $1.00 / 1,000 |
| Add-on: **Shares count** (per reel with a count) | $7.00 / 1,000 | $6.00 / 1,000 | $5.00 / 1,000 | $4.00 / 1,000 |
| Add-on: **Video download** (per MB saved) | $20.00 / 1,000 | $15.00 / 1,000 | $12.00 / 1,000 | $10.00 / 1,000 |
| Actor start (per GB of run memory, once per run) | $0.001 | $0.001 | $0.001 | $0.001 |

Example: 100 reels on the Free plan = $0.26, plus a start fee of a few tenths of a cent. With the video download, a typical 5 MB reel adds 5 × $0.02 = $0.10 on the Free plan. Cap any run with **Maximum reels for the whole run** or a maximum cost per run.

### Limits (logged-out data)

The Actor reads Instagram exactly as a visitor who is not signed in. That means:

- **12 latest reels per profile** at most — Instagram does not show more to logged-out visitors;
- **profile IDs and audio pages** cannot be used as input (use the username or the reel URL);
- **transcripts** are not available (`includeTranscript` is accepted, ignored and never billed);
- **trial reels** never appear on profile pages, so they are never in the results;
- **plays** come from the profile's reels list: a reel given by URL alone has likes and comments but often no play count;
- **video duration** is not shown to logged-out visitors (`videoDuration` is usually empty);
- the **shares count** is only returned when Instagram includes it in the page, which is rare for logged-out visitors; you pay only for reels that have one;
- counts can be lower than what you see signed in (Instagram hides some engagement from visitors) and keep changing after the run.

### Use it via API

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("badr_xba/instagram-reel-scraper").call(run_input={
    "username": ["natgeo", "https://www.instagram.com/reel/DX7lzTOJ1p6/"],
    "resultsLimit": 12,
    "onlyPostsNewerThan": "30 days",
})
for reel in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(reel["url"], reel["videoPlayCount"], reel["likesCount"])
```

**JavaScript** (`npm install apify-client`):

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('badr_xba/instagram-reel-scraper').call({
    username: ['natgeo'],
    resultsLimit: 12,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**cURL** (runs the Actor and returns the reels in one call):

```bash
curl -X POST "https://api.apify.com/v2/acts/badr_xba~instagram-reel-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username": ["natgeo"], "resultsLimit": 12}'
```

### Integrations

- **Make**, **Zapier** and **n8n**: use the Apify app or node with `badr_xba/instagram-reel-scraper` to send new reels to Google Sheets, Airtable, Slack or a database.
- **AI agents (MCP)**: add `https://mcp.apify.com/?actors=badr_xba/instagram-reel-scraper` to Claude, Cursor or any MCP client.
- **Schedules and webhooks**: track a list of creators every day and get notified when each run ends.

### Troubleshooting

| What you see | What to do |
|---|---|
| Type `input` in FAILED_INPUTS | Not a username, profile URL or reel URL (hashtags, places, audio pages and share links are not handled). The reason says which. |
| Type `private` | The profile is private: its reels are not public. |
| Type `notFound` | The reel was deleted or the account does not exist. Check it in a private browser window. |
| Type `filtered` | Every reel was older than your date filter, or pinned while **Skip pinned reels** is on. |
| Type `blocked` | Instagram refused every address tried. Keep the **RESIDENTIAL** proxy group and run again; never billed. |
| `videoPlayCount` is empty | The reel was given by URL: plays come from the profile's reels list. Add the profile instead. |
| Only 12 reels per profile | That is all Instagram shows logged-out visitors. Schedule the Actor to collect new reels as they appear. |

### FAQ

**Can I scrape private accounts?** No, only public reels.

**Can I skip pinned reels?** Yes, with **Skip pinned reels**. Combined with a date filter, pinned reels newer than the date are kept.

**How is the video returned?** `videoUrl` is Instagram's own MP4 link (it expires). With the download add-on, `downloadedVideo` points to a copy in your run storage.

**Is it legal?** The Actor only collects publicly available data. Public data can still be personal data under laws such as the GDPR: scrape it only for a legitimate purpose.

**Something does not work?** Open an issue on the **Issues** tab with the run ID and your input.

# Actor input Schema

## `username` (type: `array`):

One per line: a username (natgeo or @natgeo), a profile URL (https://www.instagram.com/natgeo/) or a reel URL (https://www.instagram.com/reel/DX7lzTOJ1p6/). Mobile links, ?igsh=… tracking and lists pasted on one line (comma separated) are understood; duplicates are read once.

## `resultsLimit` (type: `integer`):

How many of the latest reels to get per profile. Instagram shows logged-out visitors up to 12 reels per profile. Ignored for reel URLs.

## `onlyPostsNewerThan` (type: `string`):

Keeps reels published after this date (UTC): 2026-09-01, 2026-09-01T10:02:01, or a period such as "1 day", "2 weeks", "3 months".

## `skipPinnedPosts` (type: `boolean`):

Leaves out the reels pinned at the top of the profile (often old). With a date filter, a pinned reel newer than the date is still kept.

## `skipTrialReels` (type: `boolean`):

Trial reels are shown only to non-followers in their feed, never on the profile page that this Actor reads: results never include them, whatever this setting.

## `includeSharesCount` (type: `boolean`):

Paid add-on. Adds the shares count of each reel when Instagram shows it. Billed only for reels where a count was returned.

## `includeDownloadedVideo` (type: `boolean`):

Paid add-on, billed per MB. Saves each reel as an MP4 in the run's storage before Instagram links expire, and adds its link in "downloadedVideo".

## `includeTranscript` (type: `boolean`):

Not available in this Actor: accepted for compatibility, ignored and never billed.

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

Hard ceiling on reels saved (and billed) across all inputs. 0 = no ceiling.

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

Instagram blocks datacenter addresses. Keep the residential group.

## Actor input object example

```json
{
  "username": [
    "natgeo"
  ],
  "resultsLimit": 12,
  "skipPinnedPosts": false,
  "skipTrialReels": false,
  "includeSharesCount": false,
  "includeDownloadedVideo": false,
  "includeTranscript": false,
  "maxItems": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `reels` (type: `string`):

Plays, views, likes, comments, caption and date.

## `details` (type: `string`):

Music, hashtags, tagged users, sponsors, location and video links.

## `allFields` (type: `string`):

Every field, as JSON, CSV or Excel.

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

Reels saved, add-ons, stop reason and amount charged.

## `failedInputs` (type: `string`):

Inputs that gave nothing, with the reason.

# 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 = {
    "username": [
        "natgeo"
    ],
    "resultsLimit": 12,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("badr_xba/instagram-reel-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 = {
    "username": ["natgeo"],
    "resultsLimit": 12,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("badr_xba/instagram-reel-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 '{
  "username": [
    "natgeo"
  ],
  "resultsLimit": 12,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call badr_xba/instagram-reel-scraper --silent --output-dataset

```

## MCP server setup

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