# Instagram Reel Scraper — Captions, Likes & Hashtags (`andronixmd/instagram-reel-scraper`) Actor

Scrape Instagram Reel data from reel and post URLs: caption, hashtags, owner username and name, publish time, like and comment counts and thumbnail. Export JSON, CSV or Excel. No login and no video download. $0.002 per reel and $0.002 per run.

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

## Pricing

from $2.00 / 1,000 video scrapeds

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

Scrape **Instagram Reel data** from reel URLs into clean JSON. For each public reel,
Instagram Reel Scraper returns the caption and its hashtags, the owner, the publish
time, the like and comment counts and the thumbnail. It reads only the reel's public
data: the video itself is never downloaded and no AI is run, so results are fast and
cost $0.002 per reel. Use the output for spreadsheets, dashboards, content research,
influencer reports or LLM prompts. No Instagram login, cookies or API key are needed.

### What Instagram Reel data you get

| Field | Content |
|---|---|
| `url`, `shortcode` | The URL you submitted and the reel's shortcode. |
| `caption`, `hashtags` | The text the owner wrote under the reel and the hashtags parsed from it. |
| `author_username`, `author_name`, `author_id`, `author_url` | The owner. |
| `published_at`, `upload_date` | Publish time (UTC, ISO 8601) and date. |
| `like_count`, `comment_count` | Engagement counts as Instagram shows them. |
| `thumbnail_url`, `width`, `height` | Cover image link, and the size in pixels of the best video stream. |
| `billing` | Whether this row was charged. |

**Not returned:** view or play counts and the reel's duration. Instagram's responses to
logged-out requests did not include them in our tests; the data has no duration field,
and its video formats carry none either. For the duration and the spoken
words, use
[Instagram Reel Transcript](https://apify.com/andronixmd/instagram-reel-transcript).

The Dataset has two views: **Videos** (caption, owner, date and counts) and
**Hashtags**.

### How to scrape Instagram Reels

1. **Paste your reel URLs.** `instagram.com/reel/…` links work, and so do the
   `/<user>/reel/…`, `/reels/…`, `/p/…` and `/tv/…` forms, up to 1,000 per run.
2. **Set a run budget** in the run options if you want a hard cap on the spend.
3. **Start the run and open the Dataset.** One row per URL. Export it as JSON, CSV or
   Excel, or read it through the API.

### Input

```json
{
  "urls": ["https://www.instagram.com/reel/DZpQwxqimz2/"]
}
```

| Field | What it does |
|---|---|
| `urls` | Up to 1,000 public Instagram Reel or post URLs. Required unless you set `datasetId`. |
| `datasetId` | Read URLs from another run's dataset. See [Chain from another Actor](#chain-from-another-actor). |
| `datasetUrlField`, `maxItems` | The dataset field that holds the URL (detected when empty), and how many rows to read (default 100, at most 1,000). |

### Scheduled runs: only new items

Turn on **Skip items processed by earlier runs** (`skipPreviouslyProcessed`) and run the
Actor on a [schedule](https://docs.apify.com/platform/schedules) to get only what is new
since the last run.

- The Actor keeps a key-value store named `polyglot-processed-instagram-scraper` in your Apify
  account, or `polyglot-processed-instagram-scraper--<memoryKey>` when you set **Memory name**
  (`memoryKey`), so separate schedules can keep separate memories. Other Actors keep
  their own stores, even with the same `memoryKey`. It records each item after the item
  is delivered and charged; failed items are tried again next time.
- It applies to every URL in the run: listed ones and dataset rows.
- When nothing is new, the run ends without any charge. Only error rows appear then, for
  sources or dataset rows that could not be used.
- If the store cannot be opened or read, the run stops before any charge, and the next
  scheduled run tries again. If an item's record cannot be written, the item is still
  delivered and the log says so; a later run may process and charge it again.
- Delete the store in Apify Console (Storage → Key-value stores) to start over. Do not run
  two runs with the same memory at the same time: both would process the same new items.

### Chain from another Actor

Run an Instagram scraper such as apify/instagram-reel-scraper first, then paste the dataset ID of that run into **Dataset ID**
(`datasetId`) to refresh the data of every one of its Reels:

```json
{ "datasetId": "<dataset ID from the other run>", "maxItems": 200 }
```

- The Actor reads up to `maxItems` rows (default 100) with your own run's Apify token and
  takes each row's URL from `webVideoUrl`, `url`, `postUrl`, `videoUrl`, `inputUrl`, `link` or `shortCode`, or from the field you name in `datasetUrlField`.
- Dataset URLs run after any `urls` you list, in dataset order; a dataset URL that is
  already in the run is skipped. A run takes at most 1,000 URLs in total.
- A row without a usable URL becomes an error item with its `dataset_row` index, and it is
  not charged. Items from the dataset also carry `dataset_row`, so you can join the results
  back to the source rows.
- The example link in the URL list is processed and charged too: remove it when you want only the dataset's items.

### Output example

A real result from an Apify run on 2026-10-30; only the thumbnail link is shortened.

```json
{
  "url": "https://www.instagram.com/reel/DZpQwxqimz2/",
  "shortcode": "DZpQwxqimz2",
  "caption": "There's more to the story of Pompeii than just destruction. Join Tom Hiddleston as he traces the stories of those who experienced the eruption and those who survived.\n\n#PompeiiOutOfTime with @twhiddleston premieres July 22 on @NatGeoTV. Streaming on @DisneyPlus and @hulu.",
  "hashtags": ["PompeiiOutOfTime"],
  "author_username": "natgeo",
  "author_name": "National Geographic",
  "author_id": "787132",
  "author_url": "https://www.instagram.com/natgeo/",
  "published_at": "2026-06-16T16:00:07Z",
  "upload_date": "2026-06-16",
  "like_count": 146711,
  "comment_count": 1362,
  "thumbnail_url": "https://scontent-iad6-1.cdninstagram.com/…",
  "billing": {
    "status": "paid",
    "events": [{ "event": "video-scraped", "requested_count": 1, "charged_count": 1, "state": "confirmed" }]
  }
}
```

- A field is left out when Instagram does not show it for that reel. Owners can hide
  like counts.
- `hashtags` is parsed from the caption; `@` mentions stay in the caption text.
- `thumbnail_url` is a signed link that expires, so download the image soon if you need
  it.
- A URL that fails returns a row with `url` and `error`.

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

Pay per event, with no subscription. The
[Pricing tab](https://apify.com/andronixmd/instagram-reel-scraper/pricing) shows the
current prices.

| Event | Price | When |
|---|---:|---|
| Run setup | $0.002 | Once per run. |
| Video scraped | $0.002 | Per reel whose data was returned. |

| Reels in one run | Cost |
|---|---:|
| 1 | $0.002 + $0.002 = **$0.004** |
| 100 | $0.002 + 100 × $0.002 = **$0.202** |
| 1,000 | $0.002 + 1,000 × $0.002 = **$2.002** |

Reel length does not change the price. URLs that fail or are rejected, including photo
posts, are not charged the per-reel fee. Apify's own small run-start event is separate
and is shown on the Pricing tab.

### Use it from the API

Start a run with the [Apify API client for JavaScript](https://docs.apify.com/api/client/js/)
and read the results:

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN })
const run = await client.actor('andronixmd/instagram-reel-scraper').call(
  { urls: ['https://www.instagram.com/reel/DZpQwxqimz2/'] },
  { maxTotalChargeUsd: 0.1 },
)
const { items } = await client.dataset(run.defaultDatasetId).listItems()
for (const item of items) console.log(item.url, item.error ?? item.like_count)
```

Or start one run over HTTP:

```sh
curl -X POST \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"urls":["https://www.instagram.com/reel/DZpQwxqimz2/"]}' \
  'https://api.apify.com/v2/actors/andronixmd~instagram-reel-scraper/runs?maxTotalChargeUsd=0.1'
```

The Actor also works from n8n and other automation tools through Apify's integrations. Schedule a run with the same URLs to track how the counts change over time.

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

Connect your agent to `https://mcp.apify.com`. It can find this Actor with `search-actors`, or
call it by name, `andronixmd/instagram-reel-scraper`, with `call-actor`. Use `fetch-actor-details` first for the
input schema and pricing. Every call starts a new paid run, so always set
`callOptions.maxTotalChargeUsd` and keep the `urls` list short:

```json
{ "actor": "andronixmd/instagram-reel-scraper", "input": { "urls": ["https://www.instagram.com/reel/DZpQwxqimz2/"] }, "callOptions": { "maxTotalChargeUsd": 0.1 } }
```

`call-actor` returns the run status and storage IDs, not the results. Read the rows with
`get-dataset-items` and the run's dataset ID. The fields to use are `caption`, `like_count`, `comment_count` and `error`.

With an Apify account, use your API token or MCP OAuth. Without one, an agent can buy a prepaid token from [Apify AGI](https://agi.apify.com) over
x402 or MPP and use it as the Bearer token. It starts at $1, the balance is a hard spending cap,
and the token expires after 14 days. This is experimental; see
[agentic payments](https://docs.apify.com/agents/payments).

### Limitations

- **Public reels only.** Reels from private accounts, stories, and anything that needs
  a login are not supported. The Actor uses no accounts or cookies and does not try to
  get around Instagram's access checks.
- **Reel and post URLs only.** Profile, story, hashtag, location and search URLs are
  not accepted, and the Actor does not discover reels by itself. One URL in a wrong
  format rejects the whole input before the run starts. `/p/…` post links are
  accepted; a photo post returns an error row and is not charged.
- **Not every public reel returns data.** Instagram changes how it serves pages to
  logged-out visitors and can refuse some requests, so some URLs return an error row.
  Check each row's `error` field and retry failed URLs later.
- **Reel data only.** No view counts, duration, comment text, follower counts or
  profile data, and no video or audio files. The caption is what the owner wrote, not a
  transcript of what is said.

### FAQ

**Can I get the transcript of the reel?**
Not here. The `caption` field is the text the owner wrote under the reel. For the
spoken words, use
[Instagram Reel Transcript](https://apify.com/andronixmd/instagram-reel-transcript),
which transcribes the audio with AI speech-to-text. Submit the same URLs to both and
join the results on `url`.

**Why are there no view counts?**
Instagram's responses to logged-out requests did not include play or view counts in
our tests, and this Actor does not log in.

**Does it return comments, followers or profile data?**
No. It takes individual reel URLs and returns the fields above. `comment_count` is the
number of comments, not their text.

**Are the numbers live?**
They are what Instagram shows at the moment of the run. Run it again later for new
numbers.

**Where is my data kept?**
In your Apify run storage, under your account's access and retention settings. Use the
data in line with Instagram's terms and the law that applies to you.

### Related Actors

- [Instagram Reel Transcript](https://apify.com/andronixmd/instagram-reel-transcript):
  the spoken words of the same reels as text, SRT and VTT, with the reel duration.
- [TikTok Video Scraper](https://apify.com/andronixmd/tiktok-scraper): the same kind of
  data for TikTok, including views, shares, saves and the music track.
- [YouTube Video Scraper](https://apify.com/andronixmd/youtube-scraper): YouTube video data
  and captions.
- [Audio & Video Transcriber](https://apify.com/andronixmd/speech-to-text-transcriber):
  transcripts of podcasts, audio and video files and other sites.

# Actor input Schema

## `urls` (type: `array`):

Public Instagram Reel links, one result per URL. Accepted forms: instagram.com/reel/<code>, /<user>/reel/<code>, /reels/<code>, /p/<code> and /tv/<code>. Profile, story, tag and location URLs are rejected. Submit up to 1,000 URLs, or leave this list empty and fill in Dataset ID below.

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

The example URL above is processed and charged too: remove it if you want only the dataset's items. Pick the dataset, or paste its ID, from another run that lists Instagram Reels (for example apify/instagram-reel-scraper) to get fresh data for every Reel in it. The Actor reads the rows with your run's own token and processes each row's URL like a URL above, after the listed URLs. Rows without a usable URL become uncharged error items. A named dataset works as username~dataset-name.

## `datasetUrlField` (type: `string`):

Optional. The row field that holds the URL, for example webVideoUrl, or a dotted path such as video.url. Leave it empty to use the first accepted URL from webVideoUrl, url, postUrl, videoUrl, inputUrl, link or shortCode.

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

Read at most this many dataset rows, in dataset order. A run processes at most 1,000 URLs in total, counting the list above.

## `skipPreviouslyProcessed` (type: `boolean`):

Remember every item that was delivered and charged, in a key-value store in your Apify account, and skip those items in later runs. Use it with a schedule to get only new videos or episodes. Items that failed are tried again next time. When every item was already processed, the run ends without any charge. If the store cannot be read, the run stops before any charge and the next run tries again.

## `memoryKey` (type: `string`):

Optional. Keeps a separate memory for this schedule, for example my-weekly-podcasts. The store is named polyglot-processed-instagram-scraper--<name>, and other Actors never share it; without a name every run of this Actor shares polyglot-processed-instagram-scraper. Delete the store in Apify Console (Storage, Key-value stores) to start over. Used only with the option above.

## Actor input object example

```json
{
  "urls": [
    "https://www.instagram.com/reel/DZpQwxqimz2/"
  ],
  "maxItems": 100,
  "skipPreviouslyProcessed": false
}
```

# Actor output Schema

## `videos` (type: `string`):

One Dataset item per submitted URL, with reel metadata, confirmed billing and errors. Results are in the default dataset; item-NNN key-value records are internal resume state.

# 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 = {
    "urls": [
        "https://www.instagram.com/reel/DZpQwxqimz2/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("andronixmd/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 = { "urls": ["https://www.instagram.com/reel/DZpQwxqimz2/"] }

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

```

## MCP server setup

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