# Instagram Post Scraper: Reels, Carousels & Photos by URL (`memo23/instagram-post-scraper`) Actor

Scrape any Instagram post, reel, IGTV or carousel by URL or shortcode. Returns caption, likes, comments, plays, author follower stats and public business email, hashtags, tagged users, co-authors, place tag, audio and every carousel slide. No login. JSON, CSV, Excel. Bulk-friendly.

- **URL**: https://apify.com/memo23/instagram-post-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Social media, AI, Agents
- **Stats:** 16 total users, 16 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.50 / 1,000 posts

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Instagram Post Scraper

<p align="center">
  <img src="https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/instagram-post-logo.png" alt="Instagram Post Scraper" width="240" />
</p>

Get the **complete data behind any public Instagram post** — reel, carousel, IGTV, or photo — from a URL or shortcode. Caption, likes, comments, plays, the author's profile and follower stats, hashtags, tagged users, co-authors, place tags, audio, and every carousel slide. No login, no cookies, no browser.

![How it works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-instagram-post.png)

### Why Use This Scraper?

- **One request, the whole post** — engagement, author identity, follower counts, audio, hashtags, tagged accounts, and media links all on a single row.
- **Every post type** — reels, multi-slide carousels, IGTV and plain photos. The `postType` field tells them apart, and carousels return one entry per slide.
- **Author stats without the extra bill** — each distinct account is looked up once per run, so 50 posts from one profile cost the same enrichment as one.
- **Public business contact** — business and creator accounts that publish an email or phone return them in `authorPublicEmail` / `authorPublicPhone`.
- **Tagged, mentioned and co-authored kept separate** — accounts tagged in the photo, @-mentions in the caption, joint co-authors and paid sponsors are four different fields, not one blurred list.
- **Honest about the gaps** — fields Instagram does not serve come back `null` rather than `0`, and known-unreliable data is flagged in this README instead of shipped silently.
- **Bulk-friendly** — mix URLs and shortcodes freely. Duplicates are dropped before billing. Private, deleted and invalid posts yield a clear error item instead of a failed run.

### Overview

This Actor takes a list of Instagram posts and returns one structured row per post. It works with public posts only and requires no Instagram account.

The output is **post-shaped**: one row per post you supply. A carousel is still one row — its slides arrive as a nested `slides` array, not as twenty separate rows.

### Supported Inputs

| Input form | Example |
|---|---|
| Post URL | `https://www.instagram.com/p/DcCUKZoAS8h/` |
| Reel URL | `https://www.instagram.com/reel/DcBx_I1iHZW/` |
| IGTV URL | `https://www.instagram.com/tv/DcBx_I1iHZW/` |
| Bare shortcode | `DcBx_I1iHZW` |

All forms can be mixed freely in the `posts` list.

**Not supported:** profile URLs (`instagram.com/nasa/`), hashtag pages, story links, and explore URLs. A profile URL returns an error item telling you to paste a post URL instead — see the sibling Actors below for those entry points.

### Use Cases

| Audience | What they use it for |
|---|---|
| Influencer marketing | Verify real engagement and follower counts before paying for a placement |
| Brand & competitor tracking | Snapshot the stats on any set of posts over time |
| Agencies | Pull tagged accounts, co-authors and paid-partnership flags to audit disclosed collabs |
| Content research | Analyze which hashtags, audio and formats drive plays in a niche |
| Lead generation | Collect published business emails from the creators behind posts |
| AI / data teams | Structured post records for analytics, training or RAG pipelines |

### How It Works

1. **Resolve** — every input is normalized to a shortcode, and duplicates collapse so the same post pasted three ways is billed once.
2. **Extract** — the post's full record is fetched in a single request: caption, engagement, media, audio, location, tagged accounts and co-authors.
3. **Enrich** — the author's follower, post and business-contact details are added, resolved once per account per run.
4. **Deliver** — one clean row per post written to the dataset, carousels carrying their slides inline.

### Input Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `posts` | array | — (required) | Instagram post, reel or IGTV URLs, or bare shortcodes. |
| `includeMediaUrls` | boolean | `true` | Include video, thumbnail, audio and per-slide carousel URLs. |
| `includeAuthorStats` | boolean | `true` | Include author follower / following / post counts, bio, category, external link and public business contact. |
| `includeHashtagsMentions` | boolean | `true` | Include hashtag and @-mention arrays parsed from the caption. |
| `includeTaggedUsers` | boolean | `true` | Include accounts tagged in the photo, co-authors and paid-partnership sponsors. |

Example input:

```json
{
    "posts": [
        "https://www.instagram.com/reel/DcBx_I1iHZW/",
        "https://www.instagram.com/p/DcCUKZoAS8h/",
        "DcGqb9vR8Ki"
    ],
    "includeMediaUrls": true,
    "includeAuthorStats": true,
    "includeHashtagsMentions": true,
    "includeTaggedUsers": true
}
```

Metadata only, no media links and no author lookup — the cheapest configuration:

```json
{
    "posts": ["https://www.instagram.com/p/DcCUKZoAS8h/"],
    "includeMediaUrls": false,
    "includeAuthorStats": false
}
```

### Output Overview

One row per post. Posts that cannot be delivered (private, deleted, age-restricted, or not a post URL) produce a single error item with a `message` explaining why — the run itself still succeeds.

### Output Samples

Reel row (real row, trimmed):

```json
{
    "postId": "3963668990156895830",
    "shortcode": "DcBx_I1iHZW",
    "postUrl": "https://www.instagram.com/reel/DcBx_I1iHZW/",
    "postType": "reel",
    "caption": "Check out the eclipse from 50,000 feet in the air! …",
    "createdAt": "2026-08-14T16:50:37.000Z",
    "likeCount": 334866,
    "commentCount": 1560,
    "playCount": 8397564,
    "viewCount": null,
    "durationSeconds": 92.94,
    "countsHidden": false,
    "commentsDisabled": false,
    "slideCount": 0,
    "isPaidPartnership": false,
    "authorId": "528817151",
    "authorUsername": "nasa",
    "authorFullName": "NASA",
    "authorVerified": true,
    "authorBio": "Making the seemingly impossible, possible. ✨",
    "authorFollowerCount": 104396814,
    "authorFollowingCount": 92,
    "authorPostCount": 4884,
    "authorIsBusiness": true,
    "authorExternalUrl": "https://www.nasa.gov",
    "authorPublicEmail": "public-inquiries@hq.nasa.gov",
    "hashtags": ["NASA", "Eclipse2026", "Aircraft"],
    "mentions": [],
    "taggedUsers": [],
    "coauthors": ["gopro"],
    "sponsors": [],
    "locationName": null,
    "musicTitle": "Original audio",
    "musicArtist": "nasa",
    "musicIsOriginalAudio": true,
    "thumbnailUrl": "https://scontent-lax3-1.cdninstagram.com/…",
    "videoUrl": "https://scontent-lax3-2.cdninstagram.com/…",
    "slides": [],
    "scrapedAt": "2026-08-19T12:10:05.663Z"
}
```

Carousel row — the `slides` array (trimmed to two of twenty):

```json
{
    "shortcode": "DcCUKZoAS8h",
    "postType": "carousel",
    "slideCount": 20,
    "playCount": null,
    "slides": [
        { "id": "3963804353273629911", "type": "image", "imageUrl": "https://scontent-iad3-1.cdninstagram.com/…", "videoUrl": null },
        { "id": "3963804353281968301", "type": "image", "imageUrl": "https://scontent-iad3-1.cdninstagram.com/…", "videoUrl": null }
    ]
}
```

Error item (deleted post):

```json
{
    "post": "https://www.instagram.com/p/ZZZZnotreal99/",
    "error": "post_unavailable",
    "message": "Post ZZZZnotreal99 is not available — it is private, deleted, or age-restricted."
}
```

### Key Output Fields

| Field | Meaning |
|---|---|
| `postType` | `reel`, `carousel`, `image`, `video` or `igtv`. |
| `likeCount` / `commentCount` | Engagement, on every post type. |
| `playCount` / `durationSeconds` | Video-only. `null` on photos and carousels rather than a misleading `0`. |
| `countsHidden` | `true` when the author has hidden like and view counts. |
| `slideCount` / `slides[]` | Carousel size, and one entry per slide with its own image / video URL. |
| `authorFollowerCount` … `authorPostCount` | The author's follower, following and post counts. |
| `authorPublicEmail` / `authorPublicPhone` | Contact details the account chose to publish. Null on personal accounts. |
| `hashtags` / `mentions` | Parsed from the caption text. |
| `taggedUsers` / `coauthors` / `sponsors` | Tagged in the photo / joint owners of the post / paid-partnership sponsors. Three different things. |
| `locationName` / `locationFacebookPlaceId` | The place tag. See the FAQ on coordinates before using `locationLat` / `locationLng`. |
| `musicTitle` / `musicArtist` / `musicIsOriginalAudio` | Licensed track, or the creator's own audio. |
| `thumbnailUrl` / `videoUrl` / `musicUrl` | Instagram CDN media links. These expire — see the FAQ. |

### FAQ

**Do I need to log in or provide cookies?**
No. The Actor never touches your Instagram account and only reads public posts.

**Does it handle carousels?**
Yes. A carousel is one row with a `slides` array — one entry per slide, each with its own image or video URL. `slideCount` tells you how many.

**Why is a media URL not loading later?**
Instagram's CDN links are signed and expire roughly 24-36 hours after the run, then return 403. Fetch them promptly, or use the [Instagram Video Downloader](https://apify.com/memo23/instagram-video-downloader) to get permanent re-hosted copies instead.

**Why is `viewCount` always null?**
Instagram does not populate it on this endpoint — it came back `0` on every video tested, across multiple accounts. Reporting `0` would read as "no views", so the field is nulled and `playCount` is the metric to use.

**Are the location coordinates reliable?**
The place **name** and Facebook place id are. The lat/lng frequently is not — Instagram returned London's coordinates for "Kefalonia, Greece" and California's for "Okinawa, Japan". They are passed through unaltered because they are what Instagram serves, but geocode from `locationName` or `locationFacebookPlaceId` rather than trusting `locationLat` / `locationLng`.

**I pasted a profile URL and got an error.**
That is intended — this Actor takes individual posts. For a whole account's posts see the profile and hashtag Actors below.

**What happens with a private or deleted post?**
It returns an error item explaining why, and the run continues with your other posts.

**Do I pay twice if the same post appears twice in my input?**
No. Inputs are de-duplicated by shortcode before anything is looked up, so `/p/CODE/`, `/reel/CODE/` and a bare `CODE` all collapse to one billed row.

**What does it cost?**
Pay per result: one charge per post delivered, plus a small per-run start fee. No subscription.

### Support

Found a bug or need a field added? Open an issue on the Actor's **Issues** tab in Apify Console, or email <muhamed.didovic@gmail.com>.

### Additional Services

Need a custom Instagram or social-media scraper, enrichment pipeline, or a private version of this Actor? Custom builds available — reach out at <muhamed.didovic@gmail.com>.

### Explore More Scrapers

- **[Instagram Video Downloader](https://apify.com/memo23/instagram-video-downloader)** — permanent re-hosted MP4, cover and carousel slides that never expire
- **[Instagram Transcript Scraper](https://apify.com/memo23/instagram-transcript-scraper)** — reels, posts and IGTV turned into text
- **[Instagram Comments Scraper](https://apify.com/memo23/apify-instagram-comments-scraper)** — every comment and reply on any post or reel
- **[Instagram Post Likers Scraper](https://apify.com/memo23/instagram-likers-scraper)** — who liked a post
- **[Instagram Hashtag Scraper](https://apify.com/memo23/instagram-hashtag-scraper)** — top posts and reels under any hashtag
- **[Instagram Followers & Following Scraper](https://apify.com/memo23/instagram-following-scraper)** — full follower and following lists
- **[Instagram Tagged Posts Scraper](https://apify.com/memo23/instagram-tagged-mentioned-posts-scraper)** — every post an account is tagged in

Browse the full portfolio: [muhamed-didovic.github.io](https://muhamed-didovic.github.io/)

### 🤖 For AI Agents & LLM Apps

**Purpose:** Return the full structured record of public Instagram posts, reels, carousels and IGTV — caption, engagement, author + follower stats, business contact, hashtags, tagged accounts, location, audio and media URLs.

**Minimal tested input:**

```json
{ "posts": ["https://www.instagram.com/reel/DcBx_I1iHZW/"] }
```

**Output:** array of flat objects, one per post. Core fields: `postId`, `shortcode`, `postUrl`, `postType`, `caption`, `title`, `createdAt`, `likeCount`, `commentCount`, `playCount`, `viewCount`, `durationSeconds`, `countsHidden`, `commentsDisabled`, `slideCount`, `isPaidPartnership`, `authorId`, `authorUsername`, `authorFullName`, `authorVerified`, `authorPrivate`, `authorProfilePicUrl`, `inputPost`, `scrapedAt`. With the default toggles on: `authorBio`, `authorFollowerCount`, `authorFollowingCount`, `authorPostCount`, `authorIsBusiness`, `authorCategory`, `authorExternalUrl`, `authorPublicEmail`, `authorPublicPhone`, `hashtags[]`, `mentions[]`, `taggedUsers[]`, `coauthors[]`, `sponsors[]`, `locationName`, `locationId`, `locationFacebookPlaceId`, `locationAddress`, `locationCity`, `locationLat`, `locationLng`, `musicId`, `musicTitle`, `musicArtist`, `musicIsOriginalAudio`, `thumbnailUrl`, `videoUrl`, `musicUrl`, `slides[]`.

**Behavior & billing:** Pay-per-event — one charge per post delivered. Duplicate inputs are dropped before billing. Media URLs expire ~24-36h; `viewCount` is always null (use `playCount`); `locationLat`/`locationLng` are unreliable (use `locationName`). Private, deleted and non-post URLs yield one error item each (`error`, `message`) instead of failing the run. No login or cookies required.

### ⚠️ Disclaimer

This Actor accesses publicly available data on Instagram for legitimate research, market-intelligence, and business-analysis purposes. It does not log in, bypass authentication, or access private content. Use of this Actor must comply with Instagram's Terms of Service and all applicable laws, including data-protection regulations (GDPR, CCPA, etc.). The authors are not responsible for any misuse. Users must:

- Respect rate limits and avoid overloading Instagram's infrastructure
- Not use scraped data to violate user privacy or platform terms
- Process any personal data only with a lawful basis and in compliance with their jurisdiction
- Not republish scraped content in violation of copyright

We do not store scraped data; the Actor returns it directly to your Apify dataset for your authorized use. Instagram is a trademark of Meta Platforms, Inc.; this Actor is not affiliated with or endorsed by Instagram or Meta.

### SEO Keywords

instagram post scraper, instagram reel scraper, scrape instagram post, instagram post data, instagram carousel scraper, instagram post api, instagram engagement scraper, instagram stats scraper, instagram metadata extractor, instagram likes scraper, instagram caption scraper, instagram hashtag extractor, instagram tagged users scraper, instagram influencer data, instagram post metrics, instagram post export, instagram post json, instagram post to csv, instagram content analysis, instagram business email scraper, instagram reels data, instagram igtv scraper, apify instagram scraper

# Actor input Schema

## `posts` (type: `array`):

Posts to scrape. Accepts post URLs (`https://www.instagram.com/p/CODE/`), reel URLs (`/reel/CODE/`), IGTV URLs (`/tv/CODE/`) or bare shortcodes — mix them freely. Carousels return every slide.

## `includeMediaUrls` (type: `boolean`):

Include the video, thumbnail, audio and per-slide carousel URLs on each row. These are signed Instagram CDN links that expire about 24-36 hours after the run — download them promptly, or use the Instagram Video Downloader actor to get permanent copies.

## `includeAuthorStats` (type: `boolean`):

Include the author's follower / following / post counts, bio, category and external link. Each distinct author is looked up once per run, so scraping many posts from one account costs no more than scraping one.

## `includeHashtagsMentions` (type: `boolean`):

Include arrays of the hashtags and @-mentions parsed from the caption.

## `includeTaggedUsers` (type: `boolean`):

Include the accounts tagged in the photo itself, any co-authors who jointly own the post, and paid-partnership sponsors. These are all distinct from caption @-mentions.

## Actor input object example

```json
{
  "posts": [
    "https://www.instagram.com/p/DcGqb9vR8Ki/"
  ],
  "includeMediaUrls": true,
  "includeAuthorStats": true,
  "includeHashtagsMentions": true,
  "includeTaggedUsers": true
}
```

# Actor output Schema

## `posts` (type: `string`):

All post rows (one per post, reel or carousel) in the default dataset.

# 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 = {
    "posts": [
        "https://www.instagram.com/p/DcGqb9vR8Ki/"
    ]
};

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

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

```

## MCP server setup

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