# Instagram Posts Scraper (`coregent/instagram-posts-scraper`) Actor

Scrape public Instagram posts, carousels and Reels from profiles or direct URLs. Extract captions, hashtags, mentions, likes, comment counts, Reel views, timestamps, media URLs, tagged users, collaborators, locations and owner details. Export clean JSON, CSV or Excel.

- **URL**: https://apify.com/coregent/instagram-posts-scraper.md
- **Developed by:** [Delowar Munna](https://apify.com/coregent) (community)
- **Stats:** 7 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 post results

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 Posts Scraper

![Instagram Posts Scraper](https://raw.githubusercontent.com/coregentdevspace/instagram-posts-scraper-assets/main/thumbnail-instagram-posts-scraper.png)

Scrape public Instagram posts, carousels and Reels from profiles or direct URLs. Extract captions, hashtags, mentions, likes, comment counts, Reel views, timestamps, media URLs, tagged users, collaborators, locations and owner details. Export clean JSON, CSV or Excel.

### What this actor does

**Instagram Posts Scraper** takes Instagram usernames, profile URLs, post URLs, Reel URLs or shortcodes and returns **one clean row per post**:

- 🖼️ **Every format**: image posts, video posts, carousels (multi-slide) and Reels, all in one stable schema
- 📝 **Text**: caption, hashtags and mentions (parsed, without `#` / `@`)
- 📊 **Engagement**: likes, the exact total comment count, Reel/video plays and views, shares where public
- 🙈 **Hidden likes done right**: `likesCount: null` with `likesHidden: true`. Never a fake zero
- 🎠 **Complete carousels**: every slide as a nested `childPosts` entry, with no extra charge
- 👥 **People**: owner (name, verified, followers), collaborators/co-authors and tagged users
- 📍 **Location**, 📌 **pinned** and ✏️ **edited** flags
- 🤝 **Sponsorship**: paid-partnership flag and sponsor name, taken from Instagram's own label (never guessed from `#ad`)
- 🎞️ **Media**: image, thumbnail and video URLs, video duration, dimensions and alt text

It is a **posts and Reels scraper**. For profile metadata (bio, follower counts, business contact) use [Instagram Profile Scraper](https://apify.com/coregent/instagram-profile-scraper).

### How it works

1. **Detect inputs.** Each entry is classified on its own: profile (`natgeo`, `@natgeo`, `instagram.com/natgeo`), post (`/p/…`), Reel (`/reel/…`), TV (`/tv/…`) or bare shortcode. Tracking parameters are stripped and duplicates are removed. You never pick a mode.
2. **Profiles.** The profile is resolved first, so private and nonexistent accounts are reported straight away. The feed is then paged newest-first until your limit, your date cutoff or the end of the feed.
3. **Direct URLs.** Each post or Reel URL is looked up directly and returns at most one row.
4. **Retry safely.** Rate limits, login walls and temporary errors are retried on a fresh session/IP with backoff, and a profile resumes from where it stopped. If Instagram keeps refusing, the content comes from an alternative source instead of waiting out the throttle.
5. **Export.** One row per post. Inputs that can't be served get a free **status row**, so every input can be matched to an output.

### FAQ

**What input formats are supported?** Usernames, @handles, profile URLs, `/p/` post URLs, `/reel/` and `/reels/` URLs, legacy `/tv/` URLs, the newer `/{username}/p/{shortcode}/` form, and bare shortcodes in the URL field. Mix them freely in one run.

**Do I need an Instagram login or cookies?** No. You don't provide any login, password, cookies, session IDs or Meta token. The actor only reads public content.

**Can I scrape an entire profile?** Yes. Set `resultsLimit` at or above the profile's post count. Very large exports take longer because Instagram serves a profile 12 posts per page.

**Can I scrape direct post or Reel URLs?** Yes. Put them in **Instagram URLs**. Each one returns at most one row.

**Are Reels included?** Yes. Reels in a profile feed come back as `mediaType: "REEL"`, and Reel URLs work directly. Use `mediaTypes` to keep only Reels or exclude them.

**Are carousel slides included?** Yes. A carousel is one row (one result) with every slide nested in `childPosts`. Slides are never charged separately.

**What happens when likes are hidden?** `likesCount` is `null` and `likesHidden` is `true`. The actor never substitutes zero for a count Instagram hides.

**Are comment counts exact?** `commentsCount` is the total Instagram reports for the post, not the number of comments loaded on the page. If a source reports 0 for a post that has comments turned on and the count can't be verified (this happens on some direct post URLs), `commentsCount` is `null` rather than a fake zero.

**Are video and Reel views included?** Yes, where Instagram exposes them: `videoPlayCount` (plays) and `videoViewCount` (views). Missing values stay `null` and are never estimated.

**Can I filter by date?** Yes. `postsNewerThan` accepts `2026-09-01` or a period like `7 days` or `24 hours`. Paging stops as soon as older posts are reached, and old **pinned** posts at the top of a profile don't stop it early. `postsOlderThan` returns only posts before a date.

**Can I filter by media type?** Yes. `mediaTypes` takes any of `IMAGE`, `VIDEO`, `CAROUSEL`, `REEL`. Filtered-out posts are not returned and not charged.

**How does `resultsLimit` work?** It's the maximum number of posts **per profile input**. Two profiles with `resultsLimit: 100` return up to 200 posts. Direct URLs always return at most one post each, and carousel slides don't count toward the limit.

**What happens with private profiles?** You get a free `PRIVATE_PROFILE` status row and no posts. The actor never tries to access private content. For the public metadata of a private account, use [Instagram Profile Scraper](https://apify.com/coregent/instagram-profile-scraper).

**Are media URLs permanent?** No. Instagram CDN links are signed and expire after a while. Download the media soon after the run if you need it. Set `includeMediaUrls: false` if you don't need them.

**How is pricing calculated?** Per returned post. See [Pricing](#pricing).

**Can I schedule recurring collection?** Yes. Schedule the actor in Apify with `postsNewerThan: "24 hours"` (or `"7 days"`) to collect only new public content on each run.

**Can I call it through the API or MCP?** Yes. Use the Apify API, any Apify client library, or Apify's MCP server so AI agents can call it as a tool. See the **API** tab for ready-made snippets.

**How do I get full comments?** This actor returns the comment **count**, not the comment threads. Feed the post URLs into a comments scraper such as [Instagram Comment Leads Extractor](https://apify.com/coregent/instagram-comment-leads-commenter-extractor).

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `startUrls` | URL list | — | Profile, post, Reel or TV URLs, or bare shortcodes |
| `profiles` | `string[]` | — | Usernames or @handles. Merged with `startUrls`, up to 1,000 inputs per run |
| `resultsLimit` | int | `100` | Max posts **per profile** (direct URLs return at most one) |
| `postsNewerThan` | string | — | Only posts after this date or period, with early stop |
| `postsOlderThan` | string | — | Only posts before this date or period |
| `mediaTypes` | `string[]` | all | Any of `IMAGE`, `VIDEO`, `CAROUSEL`, `REEL` |
| `includeCarouselChildren` | bool | `true` | Nested `childPosts` for carousels |
| `includeOwnerDetails` | bool | `true` | Owner full name, verified flag and follower count (the follower count comes from the profile, so it's set for posts from a profile input and `null` for direct URLs and collaborators' posts) |
| `includeMediaUrls` | bool | `true` | Image, thumbnail and video URLs (CDN URLs expire) |
| `proxyConfiguration` | object | Apify Proxy on | Proxy settings, see [Proxy policy](#-proxy-policy) |
| `maxConcurrency` | int | `5` | Inputs processed in parallel (pages of one profile are always sequential) |
| `maxRetries` | int | `4` | Retries per input on rate limits, login walls or temporary errors |
| `debugMode` | bool | `false` | Verbose logging |

Provide at least one entry in `startUrls` or `profiles`. A completely empty input runs the example profile `natgeo`.

#### Example 1: The latest posts of a profile

```json
{
  "profiles": ["natgeo"],
  "resultsLimit": 100
}
```

#### Example 2: Direct post and Reel URLs

```json
{
  "startUrls": [
    { "url": "https://www.instagram.com/p/DPwhVB-jo9k/" },
    { "url": "https://www.instagram.com/reel/DeIXf9SNQVO/" }
  ]
}
```

#### Example 3: Last 30 days from several profiles

```json
{
  "profiles": ["natgeo", "nasa"],
  "resultsLimit": 1000,
  "postsNewerThan": "30 days"
}
```

#### Example 4: Images and carousels only

```json
{
  "profiles": ["natgeo"],
  "resultsLimit": 500,
  "mediaTypes": ["IMAGE", "CAROUSEL"]
}
```

#### Example 5: Daily monitoring of competitors (schedule it)

```json
{
  "startUrls": [
    { "url": "https://www.instagram.com/redbull/" },
    { "url": "https://www.instagram.com/gopro/" }
  ],
  "resultsLimit": 50,
  "postsNewerThan": "24 hours",
  "includeMediaUrls": false
}
```

### Output

One row per post or Reel, deduplicated by post ID: content reached through both a profile and a direct URL is returned and charged once. Unavailable values are `null`, never guessed. Every row has the same columns, so CSV/Excel exports stay stable.

The dataset has five tabs: **Posts**, **Engagement**, **Media & carousels**, **People, location & partnerships** and **Status & errors**.

![Instagram Posts Scraper: Posts table view](https://raw.githubusercontent.com/coregentdevspace/instagram-posts-scraper-assets/main/instagram-posts-scraper-output-posts-table-view.png)

The records below come from a real run with this input (21 posts: 20 from `nasa`, 1 direct URL). Long Instagram CDN URLs are shortened with `…`.

```json
{
  "startUrls": [{ "url": "https://www.instagram.com/p/DPwhVB-jo9k/" }],
  "profiles": ["nasa"],
  "resultsLimit": 20
}
```

#### Full record: a pinned carousel from a profile

```json
{
  "type": "post",
  "status": "SUCCESS",
  "errorMessage": null,
  "mediaType": "CAROUSEL",
  "id": "3999305299946081000",
  "shortCode": "DeAYvsnn4la",
  "url": "https://www.instagram.com/p/DeAYvsnn4la/",
  "caption": "Swipe for countless stars\n\nSagittarius B2 is the most massive and most active star-forming region in the Milky Way. It produces half of the stars in our home galaxy’s core.\n\nThis image of Sagittarius B2 was taken by our @NASAWebb telescope.\n\n#NASA #Space #Stars",
  "hashtags": ["NASA", "Space", "Stars"],
  "mentions": ["nasawebb"],
  "timestamp": "2026-10-02T20:52:45.000Z",
  "likesCount": 951004,
  "likesHidden": false,
  "commentsCount": 3582,
  "videoPlayCount": null,
  "videoViewCount": null,
  "sharesCount": null,
  "isPinned": true,
  "isEdited": false,
  "isSponsored": false,
  "isPaidPartnership": false,
  "sponsorName": null,
  "partnershipLabel": null,
  "owner": {
    "id": "528817151",
    "username": "nasa",
    "fullName": "NASA",
    "profileUrl": "https://www.instagram.com/nasa/",
    "isVerified": true,
    "followersCount": 104261898
  },
  "coauthors": [],
  "taggedUsers": [],
  "location": { "id": null, "name": null, "slug": null },
  "media": {
    "displayUrl": "https://instagram.flim34-1.fna.fbcdn.net/v/t51.82787-15/831222439_…_n.jpg?stp=dst-jpg_e35_p720x720…",
    "thumbnailUrl": "https://instagram.flim34-1.fna.fbcdn.net/v/t51.82787-15/831222439_…_n.jpg?stp=dst-jpg_e35_p720x720…",
    "videoUrl": null,
    "videoDurationSeconds": null,
    "width": 1080,
    "height": 1350,
    "altText": null
  },
  "childPosts": [
    { "id": "3999304758001953300", "type": "IMAGE", "displayUrl": "https://instagram.flim34-1.fna.fbcdn.net/v/t51.82787-15/831222439_…_n.jpg?…", "videoUrl": null, "width": 1080, "height": 1350, "altText": null },
    { "id": "3999304758346117000", "type": "IMAGE", "displayUrl": "https://instagram.flim34-1.fna.fbcdn.net/v/t51.82787-15/830418338_…_n.jpg?…", "videoUrl": null, "width": 1080, "height": 1350, "altText": null },
    { "id": "3999304760703117300", "type": "IMAGE", "displayUrl": "https://instagram.flim34-1.fna.fbcdn.net/v/t51.82787-15/831354642_…_n.jpg?…", "videoUrl": null, "width": 1080, "height": 1350, "altText": null }
  ],
  "input": "nasa",
  "inputType": "PROFILE",
  "scrapedAt": "2026-10-08T18:55:34.534Z"
}
```

#### Posts tab: a Reel

```json
{
  "media": { "thumbnailUrl": "https://instagram.flim34-1.fna.fbcdn.net/v/t51.82787-15/836198157_…_n.jpg?stp=dst-jpg_e15_p240x240…" },
  "mediaType": "REEL",
  "url": "https://www.instagram.com/reel/DeIXf9SNQVO/",
  "owner": { "username": "nasa" },
  "timestamp": "2026-10-05T23:17:58.000Z",
  "caption": "From the Moon to the 50-yard line.\n \nSix months ago, @Astro_Christina flew @Eagles Super Bowl confetti around the Moon on the Artemis II mission. Yesterday, in a full circle moment, she served as honorary captain at an Eagles game, bringing a little Moon Joy to the field.\n \n#ArtemisII #FlyEaglesFly #MoonJoy",
  "likesCount": 17862,
  "commentsCount": 299,
  "videoPlayCount": 2087552,
  "isPinned": false,
  "isPaidPartnership": false,
  "shortCode": "DeIXf9SNQVO",
  "status": "SUCCESS"
}
```

#### Engagement tab: the same Reel

```json
{
  "url": "https://www.instagram.com/reel/DeIXf9SNQVO/",
  "mediaType": "REEL",
  "owner": { "username": "nasa", "followersCount": 104261898 },
  "timestamp": "2026-10-05T23:17:58.000Z",
  "likesCount": 17862,
  "likesHidden": false,
  "commentsCount": 299,
  "videoPlayCount": 2087552,
  "videoViewCount": null,
  "sharesCount": null,
  "hashtags": ["ArtemisII", "FlyEaglesFly", "MoonJoy"],
  "mentions": ["astro_christina", "eagles"]
}
```

`videoViewCount` and `sharesCount` are `null` here because Instagram didn't expose them for this Reel. When a post's likes are hidden, `likesCount` is `null` and `likesHidden` is `true`.

#### Media & carousels tab: the Reel's video

```json
{
  "media": {
    "displayUrl": "https://instagram.flim34-1.fna.fbcdn.net/v/t51.82787-15/836198157_…_n.jpg?stp=dst-jpg_e15_p240x240…",
    "videoUrl": "https://instagram.flim34-1.fna.fbcdn.net/o1/v/t2/f2/m86/AQM8J9Nwcb…_spSjX84MdmRsT8z18F6uHtpI.mp4?…",
    "videoDurationSeconds": 38.766,
    "width": 1080,
    "height": 1920,
    "altText": null
  },
  "url": "https://www.instagram.com/reel/DeIXf9SNQVO/",
  "mediaType": "REEL",
  "childPosts": []
}
```

For a carousel, `childPosts` holds every slide (see the full record above).

#### People, location & partnerships tab: a collaboration post with a location

```json
{
  "url": "https://www.instagram.com/p/DePI-TbRKO3/",
  "owner": { "username": "astro_watkins", "fullName": "Jessica Watkins", "isVerified": true },
  "coauthors": [
    { "userId": "528817151", "username": "nasa", "fullName": "NASA", "profileUrl": "https://www.instagram.com/nasa/", "isVerified": true },
    { "userId": "953293389", "username": "iss", "fullName": "International Space Station", "profileUrl": "https://www.instagram.com/iss/", "isVerified": true }
  ],
  "taggedUsers": [
    { "username": "nasa", "userId": "528817151", "fullName": "NASA", "profileUrl": "https://www.instagram.com/nasa/" },
    { "username": "iss", "userId": "953293389", "fullName": "International Space Station", "profileUrl": "https://www.instagram.com/iss/" }
  ],
  "location": { "id": "1783641135097024", "name": "International Space Station" },
  "isSponsored": false,
  "isPaidPartnership": false,
  "sponsorName": null,
  "partnershipLabel": null
}
```

This post appeared in `nasa`'s feed as a collaboration, but its author is `astro_watkins`. The row names the real author as `owner`, and `nasa` appears among the `coauthors`.

#### Status & errors tab: a direct post URL

```json
{
  "input": "https://www.instagram.com/p/DPwhVB-jo9k/",
  "inputType": "POST",
  "type": "post",
  "status": "SUCCESS",
  "errorMessage": null,
  "shortCode": "DPwhVB-jo9k",
  "url": "https://www.instagram.com/p/DPwhVB-jo9k/",
  "scrapedAt": "2026-10-08T18:55:32.333Z"
}
```

Inputs that can't be served get an error row instead, with the same columns (`type: "error"`, the status code in `status`, a human-readable `errorMessage`). Error rows are free. For example (illustrative):

```json
{
  "input": "@someprivateaccount",
  "inputType": "PROFILE",
  "type": "error",
  "status": "PRIVATE_PROFILE",
  "errorMessage": "This Instagram profile is private. Public posts are not available. Use coregent/instagram-profile-scraper for its public profile metadata.",
  "shortCode": null,
  "url": null,
  "scrapedAt": "2026-10-08T18:55:32.000Z"
}
```

#### Status values

| Status | Meaning | Charged |
|---|---|---|
| `SUCCESS` | Post returned | ✅ |
| `PARTIAL_RESULT` | A post missing core fields, or a profile whose feed stopped early (the posts already returned are kept) | — |
| `INVALID_INPUT` | Not a recognizable Instagram username, URL or shortcode | — |
| `PROFILE_NOT_FOUND` | The profile doesn't exist | — |
| `POST_NOT_FOUND` | The post doesn't exist or was removed | — |
| `PRIVATE_PROFILE` | The profile is private | — |
| `CONTENT_UNAVAILABLE` | Instagram refused this content | — |
| `AGE_RESTRICTED` | The content needs a logged-in, age-verified viewer | — |
| `LOGIN_WALL` / `RATE_LIMITED` / `BLOCKED` | Instagram kept refusing after all retries and the fallback | — |
| `TEMPORARY_INSTAGRAM_ERROR` / `PROVIDER_ERROR` | Upstream failure after all retries | — |

#### Run summary and retry input

Each run writes `RUN_SUMMARY` to the key-value store: input counts, posts saved by type (posts, Reels, carousels), duplicates skipped, posts filtered by date and by media type, and availability rates (hidden likes, Reel views, locations, collaborators). If any input failed for a temporary reason, `RETRY_INPUT` holds a ready-to-run input containing just those inputs.

### Pricing

Pay per event, **per returned post or Reel**. One carousel is one result, whatever its slide count. You are not charged for carousel slides, profile lookups, pagination, retries, invalid inputs, duplicates, filtered-out posts, partial results or error rows. There is no start fee. The per-post rate can differ by Apify plan, so see the **Pricing** tab for the current rate on yours. This README deliberately doesn't quote figures.

The actor respects the spending limit you set for a run: when it's reached, the run stops cleanly and no further posts are fetched.

#### 🚦 Proxy policy

Use **Apify Datacenter** proxy (the default) or **no proxy** for normal runs. Both work for Instagram profile feeds and post lookups at this actor's conservative concurrency.

**Apify Residential proxy is not supported.** The actor fails at startup if `apifyProxyGroups` includes `RESIDENTIAL`. In pay-per-event actors, residential bandwidth is billed per GB to the developer, not the run user, so a single bandwidth-heavy run could cost more than the per-result revenue.

If you need residential routing, supply your own residential provider in the proxy editor's **Custom proxy URLs** field. That traffic goes through your provider, not Apify, and is unaffected:

```
http://user:pass@proxy.iproyal.com:12321
http://user:pass@proxy.brightdata.com:22225
http://user:pass@proxy.oxylabs.io:7777
```

### Limitations

- **Public content only.** Private accounts, Stories, Highlights and close-friends content are out of scope.
- **Instagram decides what's public.** Some counts (likes on hidden-like posts, views on some videos, shares) are simply not exposed and come back as `null`.
- **Media URLs expire.** Instagram's CDN links are temporary.
- **Large exports take time.** Instagram serves a feed 12 posts at a time, and the actor pages one profile sequentially to stay under rate limits.
- **Filters have a scan limit.** With date or media-type filters, a profile is scanned for up to 10× `resultsLimit` posts (at least 240), then stops with what it found. A run also stops fallback work that keeps returning nothing billable, such as filters that match nothing or long lists of private or missing accounts. Affected profiles get a free `PARTIAL_RESULT` row that says so. Narrow the filters or split the run if you hit this.
- **Not included:** comment threads, likers, follower lists, hashtag or keyword search, media downloads into storage, and AI analysis. These belong to separate actors.
- Public data availability on Instagram can change at any time.

### Related actors

- [Instagram Profile Scraper](https://apify.com/coregent/instagram-profile-scraper): profile metadata, follower counts, bio links and public business contact
- [Instagram Reel Hooks & Competitor Analyzer](https://apify.com/coregent/instagram-reel-hooks-competitor-analyzer): what makes competitors' Reels work
- [Instagram Comment Leads Extractor](https://apify.com/coregent/instagram-comment-leads-commenter-extractor): commenters on posts as leads
- [Instagram Creator Leads Scraper](https://apify.com/coregent/instagram-creator-leads-scraper): find creators by niche

### Legal and privacy

This is an unofficial tool. It is not affiliated with, endorsed by or sponsored by Instagram or Meta. It processes only publicly accessible content and never accesses private accounts. Public posts can contain personal data (names, faces, tagged people, locations). You are responsible for having a lawful basis for collecting and processing it (for example under GDPR or CCPA) and for complying with Instagram's terms in your use of the data.

### Local development

```bash
cd actor
npm install
npm test     # unit tests
npm start    # runs with INPUT.json
```

# Actor input Schema

## `startUrls` (type: `array`):

Profile URLs (https://www.instagram.com/natgeo/), post URLs (/p/{shortcode}/), Reel URLs (/reel/{shortcode}/), legacy TV URLs (/tv/{shortcode}/) or bare shortcodes. The input type is detected automatically; tracking parameters are ignored. Each post/Reel URL returns at most one result.

## `profiles` (type: `array`):

Instagram usernames or @handles (natgeo, @nasa). Merged with the URLs above; duplicates are removed. Up to 1,000 inputs per run in total.

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

Maximum number of posts returned for each profile input (newest first). Carousel slides don't count — one carousel is one result. Direct post/Reel URLs always return at most one result. Common values: 20, 100, 500, 1,000, 5,000.

## `postsNewerThan` (type: `string`):

Return only posts published after this point. An ISO date (2026-09-01, 2026-09-01T00:00:00Z) or a relative period (24 hours, 7 days, 2 weeks, 3 months). Pagination stops as soon as older posts are reached; old pinned posts at the top of a profile don't stop it early. Leave empty for no limit.

## `postsOlderThan` (type: `string`):

Return only posts published before this point (same formats as above). Newer posts are paged through and skipped without charge, so a far-back date makes a run slower. Leave empty for no limit.

## `mediaTypes` (type: `array`):

Return only these types. Leave empty for all types. Filtered-out posts are not charged.

## `includeCarouselChildren` (type: `boolean`):

Return every slide of a carousel post as nested childPosts (type, image/video URL, size, alt text). Slides are never charged separately.

## `includeOwnerDetails` (type: `boolean`):

Add the owner's full name, verified flag and follower count to each post. When off, owner keeps only ID, username and profile URL.

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

Return image, thumbnail and video URLs. Instagram CDN URLs are signed and expire after a while — download media soon after the run if you need it.

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

Apify Proxy configuration. Defaults to Apify Proxy (datacenter) enabled, which rotates IPs between sessions to avoid Instagram's per-IP limits. Apify Residential is not supported — use Custom proxy URLs for your own residential provider.

## `maxConcurrency` (type: `integer`):

Maximum number of inputs processed in parallel. Pages of one profile are always fetched one after another.

## `maxRetries` (type: `integer`):

How many times an input is retried on a fresh session/IP after rate limits, login walls or temporary Instagram errors. A profile resumes where it stopped. Content Instagram still throttles after the first retry is fetched from an alternative source instead. Not-found and private inputs are never retried.

## `debugMode` (type: `boolean`):

Enable verbose logging.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.instagram.com/natgeo/"
    },
    {
      "url": "https://www.instagram.com/p/DPwhVB-jo9k/"
    }
  ],
  "profiles": [
    "nasa"
  ],
  "resultsLimit": 20,
  "postsNewerThan": "",
  "postsOlderThan": "",
  "mediaTypes": [],
  "includeCarouselChildren": true,
  "includeOwnerDetails": true,
  "includeMediaUrls": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 5,
  "maxRetries": 4,
  "debugMode": false
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `engagement` (type: `string`):

No description

## `media` (type: `string`):

No description

## `people` (type: `string`):

No description

## `errors` (type: `string`):

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://www.instagram.com/natgeo/"
        },
        {
            "url": "https://www.instagram.com/p/DPwhVB-jo9k/"
        }
    ],
    "profiles": [
        "nasa"
    ],
    "resultsLimit": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("coregent/instagram-posts-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 = {
    "startUrls": [
        { "url": "https://www.instagram.com/natgeo/" },
        { "url": "https://www.instagram.com/p/DPwhVB-jo9k/" },
    ],
    "profiles": ["nasa"],
    "resultsLimit": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("coregent/instagram-posts-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 '{
  "startUrls": [
    {
      "url": "https://www.instagram.com/natgeo/"
    },
    {
      "url": "https://www.instagram.com/p/DPwhVB-jo9k/"
    }
  ],
  "profiles": [
    "nasa"
  ],
  "resultsLimit": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call coregent/instagram-posts-scraper --silent --output-dataset

```

## MCP server setup

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