# Instagram Post Scraper (`calm_builder/instagram-post-scraper`) Actor

Scrape public Instagram posts and reels from profiles or direct links. Get captions, photos, videos, likes, comments, reel play counts, hashtags, mentions, tagged users, co-authors and paid partnerships. Filter by date, skip pinned posts, and export to JSON, CSV or Excel.

- **URL**: https://apify.com/calm\_builder/instagram-post-scraper.md
- **Developed by:** [Coder](https://apify.com/calm_builder) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 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.
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?

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

Collect public Instagram posts and reels from profiles or direct links, with captions, media, engagement, reel play counts and comments, in a clean, structured format.

Add a username or paste a link, choose how many posts you need, and export the results as JSON, CSV or Excel, or pull them through the Apify API.

### What This Actor Does

- Collects the latest posts from public Instagram profiles, by username or profile link
- Collects single posts and reels from direct links
- Supports many profiles and links in one run
- Returns captions, hashtags, mentions, photos, videos, audio and carousel items
- Includes engagement: likes, comment counts and **reel play counts**
- Adds owner details, tagged users, co-authors, music info, pinned status and paid partnerships
- Optionally includes the latest comments on every post
- Filters by publish date and can skip pinned posts

### Best For

- Social listening and brand monitoring
- Competitor and influencer research
- Tracking content and reel performance over time
- Finding sponsored posts and brand partnerships
- Building datasets for dashboards, BI, NLP or AI workflows

### Input

Add one or more Instagram profiles or post links and set how many posts to collect.

#### Main input fields

- `startUrls`
  One entry per row. Accepts usernames (`natgeo`, `@natgeo`), profile links (`https://www.instagram.com/natgeo/`), post links (`https://www.instagram.com/p/SHORTCODE/`) and reel links (`https://www.instagram.com/reel/SHORTCODE/`).
- `maxPosts`
  How many of the most recent posts to collect from each profile. Direct post and reel links always return one post.
- `includeComments`
  Adds the latest comments to every post. Leave off if you only need post details.
- `skipPinnedPosts`
  Leaves out posts pinned to the top of a profile, so you get only the latest posts in order.
- `postsDateRange`
  Only collects posts newer than a date (`2026-01-31`) or a relative period (`7 days`, `2 weeks`, `3 months`, `1 year`).

#### Example input

```json
{
  "startUrls": ["natgeo", "https://www.instagram.com/reel/DdG4RIxIPyf/"],
  "maxPosts": 100,
  "includeComments": true,
  "skipPinnedPosts": false,
  "postsDateRange": "30 days"
}
```

### Output

Each dataset item is one Instagram post or reel. If the same post is reached through both a profile and a direct link in one run, it is returned only once.

#### Fields

| Field                                                  | Description                                                             |
| ------------------------------------------------------ | ----------------------------------------------------------------------- |
| `url`, `shortCode`, `id`                               | Post link and identifiers                                               |
| `type`, `productType`                                  | `Image`, `Video` or `Sidecar` (carousel); `clips` for reels             |
| `caption`, `hashtags`, `mentions`                      | Post text and the hashtags and accounts it mentions                     |
| `alt`                                                  | Accessibility text for the post                                         |
| `timestamp`                                            | Publish time (ISO 8601, UTC)                                            |
| `likesCount`, `commentsCount`                          | Engagement counts                                                       |
| `videoPlayCount`                                       | Play count for reels and videos                                         |
| `displayUrl`, `images`, `videoUrl`, `audioUrl`         | Media links                                                             |
| `videoDuration`, `dimensionsWidth`, `dimensionsHeight` | Media size and length                                                   |
| `childPosts`                                           | Every item of a carousel post                                           |
| `ownerUsername`, `ownerFullName`, `ownerId`            | Who published the post                                                  |
| `taggedUsers`, `coauthorProducers`                     | Tagged accounts and collaborators                                       |
| `musicInfo`                                            | Song or original audio used in a reel                                   |
| `isPinned`                                             | Whether the post is pinned on the profile                               |
| `paidPartnership`, `sponsors`                          | Paid partnership flag and the brands involved                           |
| `isCommentsDisabled`                                   | Whether comments are turned off                                         |
| `firstComment`, `latestComments`                       | Latest comments with author, time and likes (when comments are enabled) |
| `inputUrl`                                             | The link or username from your input that produced this post            |

#### Example output

```json
{
  "inputUrl": "https://www.instagram.com/natgeo/",
  "id": "3985535646503749253",
  "type": "Video",
  "productType": "clips",
  "shortCode": "DdPd43hg0aF",
  "url": "https://www.instagram.com/p/DdPd43hg0aF/",
  "caption": "Summer school looks a little different for loon chicks. During their first 12 weeks, they learn essential survival skills from their parents...",
  "hashtags": ["InsideTheEnchantedWaterways"],
  "mentions": ["DisneyPlus"],
  "alt": "Video by National Geographic on September 13, 2026.",
  "timestamp": "2026-09-13T20:55:32.000Z",
  "likesCount": 100362,
  "commentsCount": 258,
  "videoPlayCount": 1484927,
  "videoDuration": 30.04,
  "displayUrl": "https://instagram.fvii2-1.fna.fbcdn.net/v/t51.82787-15/...",
  "videoUrl": "https://instagram.fvii2-4.fna.fbcdn.net/o1/v/t2/f2/m86/...",
  "audioUrl": "https://instagram.fvii2-1.fna.fbcdn.net/o1/v/t2/f2/m78/...",
  "dimensionsWidth": 1080,
  "dimensionsHeight": 1920,
  "childPosts": [],
  "ownerUsername": "natgeo",
  "ownerFullName": "National Geographic",
  "ownerId": "787132",
  "taggedUsers": [],
  "coauthorProducers": [],
  "isPinned": null,
  "paidPartnership": false,
  "sponsors": null,
  "isCommentsDisabled": false,
  "firstComment": "Such a beautiful video!",
  "latestComments": [
    {
      "id": "17870010036639467",
      "text": "Such a beautiful video!",
      "ownerUsername": "example_user",
      "timestamp": "2026-09-14T15:22:34.000Z",
      "likesCount": 0
    }
  ]
}
```

Media links are provided by Instagram and expire after a while, so download any files you need soon after the run.

### How To Use

1. Add one or more Instagram usernames, profile links, or post and reel links to `startUrls`.
2. Set `maxPosts` to how many recent posts you need from each profile.
3. Turn on `includeComments` only if you need comments.
4. Optionally set `postsDateRange` or `skipPinnedPosts`.
5. Run the actor and open the dataset, or export it as JSON, CSV or Excel, or read it through the Apify API.

### Pricing

This actor uses pay-per-event pricing, so you only pay for results you receive:

- **Post** — charged once for each post saved to your dataset.
- **Post comments** — charged once for each post that comes back with comments, only when `includeComments` is on.
- **Actor start** — a small fixed fee of $0.001 per run.

Links that cannot be collected (private, deleted or unavailable) are not charged. Platform usage is included in these prices. Current prices for each Apify plan are shown on the actor's Pricing tab.

#### Free plan

On the Apify free plan, each run processes up to **2** links and up to **5** posts per profile. Upgrade to a paid Apify plan to remove these limits.

### Best Practices

- Start with a small `maxPosts` value to check the output quickly.
- Use `postsDateRange` for recurring monitoring, so each run only collects new posts.
- Turn on `skipPinnedPosts` when you need strictly the most recent posts.
- Enable comments only for runs that need them; runs without comments are faster and cheaper.
- Use JSON export when you need nested data such as comments, carousel items and music info.

### FAQ

#### Why is no data returned for some links?

The profile or post is probably private, age-restricted, deleted, or otherwise not publicly available. The run log names each link that could not be collected.

#### Why did a profile return fewer posts than I asked for?

The profile may simply have fewer posts, your date filter may exclude older ones, or Instagram did not return more at that moment. In that last case the log says so, and running again later usually collects the rest.

#### Do all posts have play counts?

Play counts are available for reels and videos. Photos and carousels don't have them.

#### How many comments are included per post?

The latest comments Instagram shows publicly for each post, usually around 10–15. The full comment count is always in `commentsCount`.

#### Can I collect stories, highlights or private accounts?

No. This actor collects public posts and reels only.

#### How long does a run take?

It depends on the number of profiles, `maxPosts`, and whether comments are enabled. Around 100 posts with comments from one profile typically finishes in well under a minute.

### Responsible Use

Use this actor only for publicly available content, and make sure your use complies with applicable laws (including data protection rules such as GDPR) and Instagram's terms. Avoid collecting personal data you don't need.

### Troubleshooting

- Open each link in a logged-out browser window to confirm it is public.
- Check the run log: it names any link that was skipped and why.
- If a profile returned fewer posts than expected, run it again a little later.
- Test with a small `maxPosts` value before large runs.

# Actor input Schema

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

Enter one Instagram link or username per row.

Supported formats:

- Profile — `natgeo`, `@natgeo`, or `https://www.instagram.com/natgeo/`
- Post — `https://www.instagram.com/p/SHORTCODE/`
- Reel — `https://www.instagram.com/reel/SHORTCODE/`

Only public content can be collected. If a post link is already covered by a profile in the same run, it is returned once.

## `maxPosts` (type: `integer`):

How many of the most recent posts to collect from **each profile**. If a profile has fewer posts, all of them are returned.

Direct post and reel links always return one post each, regardless of this value.

## `includeComments` (type: `boolean`):

Add the latest comments to every post, in the `firstComment` and `latestComments` fields.

Comments are an optional add-on with their own price and make runs a little longer. Leave this off if you only need post details.

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

Leave out posts the owner has pinned to the top of their profile.

Pinned posts can be much older than the rest, so turn this on when you only want the latest posts in order.

## `postsDateRange` (type: `string`):

Optional. Collect only posts published after this point. Use a date (`YYYY-MM-DD`) or a relative period such as `7 days`, `2 weeks`, `3 months` or `1 year`.

Leave empty to collect posts of any age.

## Actor input object example

```json
{
  "startUrls": [
    "natgeo",
    "https://www.instagram.com/reel/DdG4RIxIPyf/"
  ],
  "maxPosts": 24,
  "includeComments": false,
  "skipPinnedPosts": false,
  "postsDateRange": ""
}
```

# Actor output Schema

## `results` (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": [
        "natgeo",
        "https://www.instagram.com/reel/DdG4RIxIPyf/"
    ]
};

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

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

```

## MCP server setup

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