# Instagram Profile Posts Scraper – Feed Export (`scrapingmonkey/instagram-profile-posts`) Actor

Scrape public Instagram profile posts by username with page-based pagination. Export photos, videos, Reels, carousels, captions, engagement, media, and authors.

- **URL**: https://apify.com/scrapingmonkey/instagram-profile-posts.md
- **Developed by:** [ScrapingMonkey](https://apify.com/scrapingmonkey) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 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?

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

Collect public Instagram profile posts with pagination and save every post as a separate dataset row. **Instagram Profile Posts Scraper** accepts plain usernames and returns images, Reels, carousels, captions, engagement, media URLs, author data, tags, collaborations, audio, and location metadata.

Choose pages rather than an arbitrary post limit: each requested profile page asks Instagram for up to 12 posts. Results are saved page by page, require no Instagram login, and remain convenient for CSV, JSON, Excel, APIs, and automation.

| At a glance | Details |
|---|---|
| 📥 Input | Plain Instagram usernames and pages per profile |
| 📤 Output | One row per image, Reel, video, or carousel post |
| 📄 Pagination | Up to 12 posts per requested page when available |
| 🔐 Login required | No |
| ⚡ Processing | Up to 5 profile-page requests concurrently with automatic retries |
| 💾 Delivery | Apify dataset with flattened Store columns and complete nested JSON |

### What the Instagram profile posts scraper collects 📸

The Actor reads the public profile feed and normalizes different media types into one consistent schema. You can filter rows by `type` while retaining type-specific fields such as video variants, audio, or carousel children.

Data can include:

- Post ID, PK, shortcode, canonical URL, post type, product type, and media type
- Caption text, caption ID, publication time, translation state, and edit state
- Like, comment, view, play, Instagram play, Facebook, and repost counts
- Image, thumbnail, video, duration, dimensions, and accessibility text
- All image and video variants supplied by Instagram
- Full ordered carousel children with their own media and tagged users
- Author, location, tagged users, coauthors, sponsors, and audio
- Comment, hidden-count, partnership, resharing, pinned, and Facebook-sharing flags

### How to scrape posts from Instagram profiles 🚀

1. Enter one or more usernames without `@`.
2. Set `pagesPerProfile` to the number of feed pages to attempt.
3. Start the Actor.
4. Review each post as a separate success row.
5. Export the dataset or connect it to your application.

```json
{
  "inputList": [
    "nike",
    "nasa"
  ],
  "pagesPerProfile": 2
}
```

Two full pages can yield up to roughly 24 unique posts per username. The real total can be lower because feeds end, items overlap, posts disappear, or duplicates are removed.

### Profile post data and complete output 📦

| Field group | Included data |
|---|---|
| Identity | IDs, shortcode, canonical URL, normalized type, product and media type |
| Caption | Text, ID, timestamps, translation and edit flags |
| Engagement | Likes, comments, views, plays, Facebook counts, reposts |
| Media | Image, thumbnail, video, duration, dimensions, image and video variants |
| Carousel | Child count and ordered child objects with media variants |
| Relationships | Author, location, tagged users, coauthors, sponsors |
| Audio and state | Audio metadata, comment state, hidden counts, partnership, pinned, resharing |

Complete representative Reel result. Image and carousel rows use the same top-level schema; irrelevant fields remain null or empty.

```json
{
  "input": "nike",
  "status": "success",
  "image_url": "https://instagram.example/reel-cover.jpg",
  "url": "https://www.instagram.com/reel/DctPchKOVcw/",
  "id": "1234567890123456789_13460080",
  "pk": "1234567890123456789",
  "code": "DctPchKOVcw",
  "type": "reel",
  "product_type": "clips",
  "media_type": 2,
  "caption": "An example profile post",
  "caption_id": "987654321",
  "caption_timestamp": 1754006400,
  "caption_published_at": "2025-08-01T00:00:00Z",
  "caption_has_translation": false,
  "caption_is_edited": false,
  "published_at": "2025-08-01T00:00:00Z",
  "timestamp": 1754006400,
  "like_count": 24500,
  "comment_count": 410,
  "view_count": 340000,
  "play_count": 352000,
  "instagram_play_count": 350000,
  "facebook_play_count": 0,
  "facebook_like_count": 0,
  "facebook_comment_count": 0,
  "repost_count": 97,
  "thumbnail_url": "https://instagram.example/reel-thumbnail.jpg",
  "video_url": "https://instagram.example/reel-video.mp4",
  "video_duration": 12.8,
  "width": 1080,
  "height": 1920,
  "accessibility_caption": null,
  "has_audio": true,
  "comments_disabled": false,
  "commenting_disabled_for_viewer": false,
  "counts_hidden": false,
  "is_paid_partnership": false,
  "can_reshare": true,
  "is_pinned": false,
  "is_shared_to_facebook": false,
  "author": {
    "profile_picture_url": "https://instagram.example/nike.jpg",
    "profile_picture_url_hd": "https://instagram.example/nike-hd.jpg",
    "username": "nike",
    "name": "Nike",
    "id": "13460080",
    "pk": "13460080",
    "profile_url": "https://www.instagram.com/nike/",
    "is_verified": true,
    "is_private": false
  },
  "location": {
    "id": "1001",
    "pk": "1001",
    "name": "New York",
    "short_name": "New York",
    "address": "New York, NY",
    "city": "New York",
    "latitude": 40.7128,
    "longitude": -74.006
  },
  "image_versions": [
    {
      "url": "https://instagram.example/reel-cover-1080.jpg",
      "width": 1080,
      "height": 1920
    }
  ],
  "video_versions": [
    {
      "url": "https://instagram.example/reel-video-1080.mp4",
      "width": 1080,
      "height": 1920,
      "type": 101
    }
  ],
  "carousel_media_count": 0,
  "carousel_media": [],
  "tagged_users": [
    {
      "id": "2002",
      "pk": "2002",
      "username": "examplecreator",
      "name": "Example Creator",
      "profile_url": "https://www.instagram.com/examplecreator/",
      "profile_picture_url": "https://instagram.example/tagged.jpg",
      "is_verified": false,
      "position": [0.5, 0.5]
    }
  ],
  "coauthors": [
    {
      "id": "3003",
      "pk": "3003",
      "username": "partnerbrand",
      "name": "Partner Brand",
      "profile_url": "https://www.instagram.com/partnerbrand/",
      "profile_picture_url": "https://instagram.example/coauthor.jpg",
      "is_verified": true
    }
  ],
  "audio": {
    "id": "5005",
    "type": "music",
    "title": "Example Track",
    "artist": "Example Artist",
    "url": "https://instagram.example/audio.m4a",
    "duration_ms": 12800,
    "is_original_audio": false
  },
  "sponsors": [
    {
      "id": "4004",
      "pk": "4004",
      "username": "sponsorbrand",
      "name": "Sponsor Brand",
      "profile_url": "https://www.instagram.com/sponsorbrand/",
      "is_verified": true
    }
  ]
}
```

For carousel rows, each `carousel_media` item includes `position`, `id`, `pk`, `code`, `type`, `media_type`, `image_url`, `video_url`, `video_duration`, `width`, `height`, `accessibility_caption`, `image_versions`, `video_versions`, `product_type`, `timestamp`, `published_at`, `like_count`, and `tagged_users`.

A failed row uses the identical top-level schema: it preserves `input`, sets `status` to `failed`, and sets every post-data field to `null`. This prevents dead usernames or failed pages from disappearing silently.

### Input and pagination settings ⚙️

| Parameter | Type | Required | Default | Rules |
|---|---|---|---|---|
| `inputList` | array of strings | Yes | None | At least one plain Instagram username |
| `pagesPerProfile` | integer | No | `1` | Minimum `1` |

Use `nike`, not `@nike` and not a profile URL. Invalid username strings fail immediately. Duplicate usernames and duplicate post IDs are deduplicated.

The initial feed request counts as page 1. Each page asks for 12 posts. Earlier pages are saved before the next pagination request, so useful output remains available when a later page repeatedly fails.

### Instagram profile feed use cases 🎯

#### Brand and competitor monitoring

Create repeatable public-feed datasets and compare captions, formats, visible engagement, partnerships, and collaborators.

#### Creator content analysis

Study posting mix across images, Reels, and carousels while keeping author and media details attached to every row.

#### Media discovery

Collect canonical post links, thumbnails, direct media variants, audio references, and carousel child data for authorized workflows.

#### Content databases and search

Index public captions, timestamps, identifiers, tags, locations, and media types in your own database.

#### Reporting and AI pipelines

Send structured post rows to dashboards, categorization, moderation, sentiment, vision, or language-processing systems.

### Pricing and saved-result behavior 💰

See the Actor's **Pricing** tab for the active pricing model and current rate. Store settings may change, so this README does not claim a fixed cost.

Under dataset-item pricing:

- Each unique post saved as `success` is one billable result.
- An invalid or unavailable profile, or a page that cannot be retrieved after retries, can save a `failed` result.
- A carousel post is one row even if `carousel_media` contains many children.
- Automatic retry attempts do not create extra rows by themselves.
- More requested pages can produce more saved post rows.

### Instagram profile posts API 🔌

Replace `$ACTOR_ID` with the ID shown in the Actor API tab and `$APIFY_TOKEN` with your token.

```bash
curl -X POST "https://api.apify.com/v2/acts/$ACTOR_ID/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"inputList":["nike","nasa"],"pagesPerProfile":2}'
```

Use schedules for regular collection, webhooks for completion notifications, and Apify integrations for Google Sheets, Make, Zapier, cloud storage, data warehouses, or custom APIs.

### Reliability, retries, and public-feed limits ⚠️

The Actor processes up to five requests concurrently. Temporary network errors, timeouts, throttling, selected HTTP errors, and blocked redirects are retried automatically. Invalid syntax and confirmed permanent input failures are not retried unnecessarily.

One bad profile or later page should not erase successful output from other inputs or earlier pages. The whole Actor run can still fail because of infrastructure-level problems such as startup failure, unavailable Apify dataset storage, or an unrecoverable result-save error.

Instagram controls public availability and pagination. Private, deleted, renamed, suspended, login-gated, age-restricted, or region-restricted profiles may not return posts. Counts and optional metadata can be null, zero, or empty even on a successful post row.

### Frequently asked questions ❓

#### Does it return one row per profile or one row per post?

One row per unique post. The source username and full author fields are included in every result.

#### Can I choose an exact number of posts?

You choose pages. Each page requests up to 12 posts; the final unique result count may be lower.

#### Does it include videos and every carousel image?

Yes, when Instagram exposes them in the public feed response. Reels include video variants and carousels include ordered child media.

#### Can I submit profile links?

No. Enter plain usernames without `@`.

#### Does it require Instagram cookies?

No Instagram login, password, cookie, or session input is required.

#### Why are some media or count fields null?

The field may not apply to that post type, the account may hide the count, or Instagram may omit it from the public response.

### Support, responsible use, and related actors 🛟

For a reproducible problem, share the run ID, approximate time, page count, and a safe public username through the support channel. Never disclose access tokens or proxy credentials.

Related actors:

- [Instagram Profile Reels Scraper](../instagram-profile-reels-scraper) for Reel-only profile pagination
- [Instagram Profile Details Scraper](../instagram-profile-details-scraper) for bio, audience, business, and contact fields
- [Instagram Post Details Scraper](../instagram-post-details-scraper) for deeper extraction from selected post URLs

Use public content lawfully and responsibly. Follow privacy, copyright, data-protection, contractual, and platform requirements before storing, analyzing, downloading, or redistributing data.

# Actor input Schema

## `inputList` (type: `array`):

Add one Instagram username such as nike per item. Enter only the username without @ or a profile link. Private, unavailable and invalid profiles are saved with failed status.

## `pagesPerProfile` (type: `integer`):

Every page asks Instagram for up to 12 posts. Choose 1 for up to 12 posts, 5 for up to 60, or 10 for up to 120. Collection stops automatically when no more posts are available.

## Actor input object example

```json
{
  "inputList": [
    "nike"
  ],
  "pagesPerProfile": 1
}
```

# Actor output Schema

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

One Dataset row for every unique post returned directly by the Instagram profile feed. Failed input or page rows keep the original input and use failed status.

# 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 = {
    "inputList": [
        "nike"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapingmonkey/instagram-profile-posts").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 = { "inputList": ["nike"] }

# Run the Actor and wait for it to finish
run = client.actor("scrapingmonkey/instagram-profile-posts").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 '{
  "inputList": [
    "nike"
  ]
}' |
apify call scrapingmonkey/instagram-profile-posts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapingmonkey/instagram-profile-posts"
        }
    }
}

```

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/5wRafWBfbEbv3RSKc/builds/px419FA5UcBNRtYGD/openapi.json
