# Instagram Profile Posts Scraper — Post History by Profile (`foxlabs/instagram-profile-posts-scraper`) Actor

The posts of public Instagram profiles — photos, carousels, reels — newest first, page by page: caption, hashtags, mentions, kind, image, approximate time. On request each post's likes, comments, exact time, tagged accounts, carousel items and topics. Only-new mode. No login, no cookies.

- **URL**: https://apify.com/foxlabs/instagram-profile-posts-scraper.md
- **Developed by:** [Berkan Kaplan](https://apify.com/foxlabs) (community)
- **Categories:** Social media
- **Stats:** 3 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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 Profile Posts Scraper — Post History by Profile 🚀

**foXLabs Instagram series:** [Bulk Profile](https://apify.com/foxlabs/instagram-profile-scraper) · [Post Details](https://apify.com/foxlabs/instagram-post-details-scraper) · [Comments](https://apify.com/foxlabs/instagram-comments-scraper) · [Reels](https://apify.com/foxlabs/instagram-reels-scraper)

🎉 Give this Actor Instagram profiles and get their posts — photos, carousels and reels — one row per post, from the top of each list down until the list ends or your limit is reached. A row carries the caption with hashtags and mentions, the kind, the image address, author and two approximate times. Turn on **Read each post's details** and one more request per post adds **like and comment counts, exact time, location, co-authors, tagged accounts, carousel items, topics**, and for a video its length, file address and sound.

**It reads only what a signed-out visitor sees.** No login, no cookies, nothing from your own Instagram account. Not affiliated with Instagram or Meta.

### 🔍 What is the Instagram Profile Posts Scraper — and when should you use it?

Give this Actor profiles and it returns their post history as clean rows — built for content/competitor analysis, brand-partnership tracking (who's tagged, who co-authored) and watching accounts for new posts.

**Use it when you need:** a profile's full post feed (photos/carousels/reels); engagement + exact times with details; or an only-new feed of new posts.

**Use something else when:** you want profile-level metrics → [Bulk Profile](https://apify.com/foxlabs/instagram-profile-scraper); one post by URL → [Post Details](https://apify.com/foxlabs/instagram-post-details-scraper); a post's comments → [Comments](https://apify.com/foxlabs/instagram-comments-scraper); only reels → [Reels](https://apify.com/foxlabs/instagram-reels-scraper).

### 🤖 Use with AI agents

**Already on the Apify MCP server?** Ask for this Actor by name: `foxlabs/instagram-profile-posts-scraper`. An agent can discover it, run it and read the dataset over MCP; the Actor is built to run in Standby for on-demand lookups.

Otherwise paste this into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```
I want an Instagram profile's posts using the Apify Actor
`foxlabs/instagram-profile-posts-scraper`.

Input: `profiles` is a list of usernames/URLs; `maxPostsPerProfile` caps rows; `postTypes`
filters photo/carousel/video; `includeDetails` adds like/comment counts, exact time and more.
Each row has type, caption, hashtags, url, takenAtApprox and (with details) likeCount, commentCount.

Start with:
{ "profiles": ["natgeo"], "maxPostsPerProfile": 24 }

Ask me which profiles to analyse, run the Actor, then summarise the posts.
```

The machine-readable API, MCP config and OpenAPI definition live at `apify.com/foxlabs/instagram-profile-posts-scraper.md`.

### 📋 Overview

Everything you need to turn a profile's post history into clean, structured data — captions, media and (with details) engagement — in one Actor, with no login, cookies or account.

**Why teams pick this Actor:**

- ✅ **Full post history** — photos, carousels and reels, page by page to the list's end or your cap.
- 📊 **Engagement on demand** — `includeDetails` adds like/comment counts, exact time, carousel items, topics.
- 🤝 **Partnership signals** — co-authors and tagged accounts (per carousel item too).
- 🎯 **Honest** — unknown is `null` never 0; approximate vs exact times clearly separated.
- 💰 **Pay only for results** — `post` / `post-detailed` events per row; status rows and skipped kinds free.
- 🤖 **Agent-ready** — MCP + Standby.

### ✨ Features

- 🔍 **Posts by profile** — username/@handle/URL, up to 10,000 profiles; duplicates read once.
- 🖼️ **From the list** — type, caption, hashtags, mentions, accessibility caption, image URL, carousel count, approximate times, position.
- 🔎 **With details** — exact time, like/comment counts (+ hidden/disabled flags), location, co-authors, tagged users, carousel media, topics, size, video URL + music, AI label.
- 🧹 **Filter** — `postTypes` (photo/carousel/video). 🔁 **Only-new lists** for watching accounts.

### 🎬 Quick Start

```bash
curl -X POST "https://api.apify.com/v2/acts/foxlabs~instagram-profile-posts-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"profiles": ["natgeo"], "maxPostsPerProfile": 24}'
```

### 🚀 Getting Started (3 steps)

1. **List your profiles** — one per line: `natgeo`, `@natgeo` or a URL.
2. **Set the cap & depth** — `maxPostsPerProfile`, optional `postTypes`, `includeDetails` for engagement.
3. **Run and export** — get a clean dataset as JSON, CSV or Excel.

### 📥 Input

| Field | Default | What it does |
|---|---|---|
| `profiles` | required | One profile per line (up to 10,000); a profile in two spellings read once. |
| `maxPostsPerProfile` | 100 | Posts per profile from the top of its list. |
| `maxPosts` | 100000 | Post rows in total. |
| `postTypes` | all | `photo`, `carousel`, `video` (covers reels); other kinds skipped, not charged. |
| `includeDetails` | false | Read each post's own record (one more request per post). |
| `onlyNewPosts`, `listName` | false, `default` | Deliver only posts not delivered before. |
| `proxyConfiguration` | auto | Nothing to change for normal use. |

```json
{ "profiles": ["nasa"], "maxPostsPerProfile": 12, "includeDetails": true }
```

### 📤 Output

One row per post (`postId` is the key; delivered once per run). A value Instagram didn't give is `null`, never 0.

**From the list:** `type` (photo/carousel/reel/video), `postId`, `shortCode`, `url`, `productType`, `profile`, `ownerUsername`, `ownerUserId`, `caption`, `hashtags`, `mentions`, `accessibilityCaption`, `displayUrl`, `carouselCount`, `takenAtApprox`, `publishedDayApprox`, `positionInProfile`, `input`, `scrapedAt`.

**With `includeDetails`:** `takenAt` (exact), `likeCount` (+ `likesHidden`), `commentCount` (+ `commentsDisabled`), `captionIsEdited`, `isAiLabeled`, `locationName`/`locationId`, `coauthors`, `taggedUsers`, `carouselMedia[]`, `topics`, `width`/`height`, `durationSeconds`/`videoUrl`, `musicArtist`/`musicTitle`, `detailsSource`.

```json
{
  "type": "photo",
  "postId": "4002789380695323831",
  "url": "https://www.instagram.com/p/DeMw7vrDPS3/",
  "profile": "nasa",
  "ownerUsername": "nasa",
  "caption": "Moon-like Madagascar … #NASA #Earth #Geology",
  "hashtags": ["NASA", "Earth", "Geology"],
  "takenAtApprox": "2026-10-07T16:15:00.015Z",
  "publishedDayApprox": "2026-10-07",
  "takenAt": "2026-10-07T16:15:06.000Z",
  "likeCount": 84901, "likesHidden": false,
  "commentCount": 249,
  "topics": ["satellite view", "geology", "earth from space"],
  "detailsSource": "post-query",
  "positionInProfile": 9
}
```

**Honest on time:** `takenAtApprox` is read from the post id (the moment it was *made*) — within a minute of the exact time for 64 of 120 posts, over an hour early for 16; use `takenAt` (details) for the exact order. `publishedDayApprox` is Instagram's image-description day; allow a day when filtering. No view/play counts (the public record has none); no comment texts, stories, follower lists or search; no private/signed-in-only profiles (free status row).

### 💼 Use cases

**1. Content & competitor analysis** — a profile's posts with formats, captions and (with details) engagement.
*Input:* the profiles, `includeDetails`. *Output:* posts + like/comment counts. *Use:* learn what performs.

**2. Partnership tracking** — who a brand co-authors and tags.
*Input:* the brand's profile, `includeDetails`. *Output:* `coauthors`, `taggedUsers`. *Use:* map collaborations.

**3. Account watching** — only-new posts as they appear.
*Input:* the profiles, `onlyNewPosts`, scheduled. *Output:* new posts each run. *Use:* a content feed.

### 🔗 Integration

**JavaScript / Node.js**

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('foxlabs/instagram-profile-posts-scraper').call({ profiles: ['natgeo'], maxPostsPerProfile: 24 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

**Python**

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('foxlabs/instagram-profile-posts-scraper').call(run_input={'profiles': ['natgeo'], 'maxPostsPerProfile': 24})
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)
```

Written for `apify-client` 3 for Python, where `call()` returns a run object; with version 1 or 2 it returns a dict — write `run['defaultDatasetId']` there.

**Automation (n8n / Zapier / Make):** schedule → HTTP request to the Actor API with your `profiles` → handle the JSON dataset → push to a sheet, CRM or dashboard.

### 📊 Pricing

Pay-per-event, one event per delivered row: **`post`** (from the list) or **`post-detailed`** (details read, `detailsSource: "post-query"`). A post asked with details that came without them carries `post`. Not charged: status rows, posts of a kind you didn't ask for, posts skipped as already delivered. [View current pricing.](https://apify.com/foxlabs/instagram-profile-posts-scraper)

### ❓ FAQ

**Do I need an Instagram login or cookies?** No — only what a signed-out visitor sees.

**Why no like/comment counts on some rows?** The list carries none; they come with `includeDetails`. A hidden like count stays `null`.

**Are the times exact?** `takenAtApprox`/`publishedDayApprox` are approximate (no details); `takenAt` (details) is exact — use it to sort.

**Does it get reels?** Yes (as `video`/`reel`). For reels-only with a performance score, use the [Reels Scraper](https://apify.com/foxlabs/instagram-reels-scraper).

**Can I export to CSV / Excel / JSON?** Yes — directly from the Apify dataset.

### 🐛 Troubleshooting / What it does NOT do

- **No view/play counts** — the public post record carries none; no comment texts, stories, highlights, follower lists or search; no file downloads.
- **Private / signed-in-only / age-restricted profiles** get a free status row (not read).
- **Approximate times aren't sort keys** — don't filter dates on `takenAtApprox`; allow a day on `publishedDayApprox`; use `takenAt` for order.
- **`likesHidden`/`commentsDisabled`** — a hidden like count is `null`; a disabled-comments post can state a higher count than the comments shown.
- **Media isn't downloaded** — `displayUrl`/`videoUrl`/`carouselMedia` are temporary addresses.
- **A changed Instagram page** ends the run with a message (start-up check), not empty rows.

### ⚠️ Trademark

Independent, third-party tool. Not affiliated with, endorsed by or connected to Instagram or Meta Platforms, Inc. "Instagram" and related marks belong to their owners and are used here for identification only.

### ⚖️ Is it legal to scrape this data?

Posts are published by the accounts themselves, but rows can hold personal data of others (co-authors, tagged accounts, mentions, locations); you decide why you use it and are responsible for a lawful reason (GDPR and similar). Media belongs to its owners; addresses are temporary. The Actor writes only to your own run's storage. See Apify's blog post on the legality of web scraping.

### 🤝 Support & contact

- 🌐 **Website:** [data.foxlabs.com.tr](https://data.foxlabs.com.tr)
- 📧 **Email:** info@foxlabs.com.tr
- 🐛 **Issues:** open a ticket in the Actor's **Issues** tab — the run's `SOURCE_REPORT` record says which road was used and why the run stopped.
- 🧰 **More clean data actors:** [Fox Labs on Apify](https://apify.com/foxlabs)

### Changelog

#### 0.1 — 2026-10-09

- First version: a profile's posts from its list, page by page; optional details per post; filter by kind; only-new lists; a free status row for every line that brings no posts; `publishedDayApprox` on every row; requests leave from the run's own address first; start-up check. Standby mode prepared.

# Changelog

This Actor's version history is a separate document: https://apify.com/foxlabs/instagram-profile-posts-scraper/changelog.md

# Actor input Schema

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

One profile per line: a user name (natgeo), an @name (@natgeo) or a profile address (https://www.instagram.com/natgeo/). The three forms can be mixed; a profile written twice is read once. Only public profiles can be read.

## `maxPostsPerProfile` (type: `integer`):

How many posts to deliver for each profile, from the top of its list: the posts its owner pinned come first, then the newest. The list is read 12 posts a request, as far as Instagram shows it: use a large number for a whole archive.

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

The run stops when this many rows have been delivered. You are charged only for delivered rows.

## `postTypes` (type: `array`):

Leave empty for every kind. Choose one or two to get only those: a post of another kind is skipped before anything more is read for it, and is not charged.

## `includeDetails` (type: `boolean`):

Off: rows come from the profile's list alone — caption, kind, image, author and two approximate times (the moment the post's ID was made, and the day Instagram's image description names). The list carries NO like count, NO comment count and no exact time. On: one more request per post adds like and comment counts, the exact time, location, co-authors, tagged accounts, the items of a carousel, topics, and for a video its length, file address and music. Slower, and charged as a different event.

## `onlyNewPosts` (type: `boolean`):

Remember delivered posts under the list name below and skip them in later runs. Schedule the same profiles daily and each run brings only the posts it has not delivered before. With this on, "Maximum posts per profile" is how far down each profile the Actor looks: of the first 100 (or whatever you set) it delivers the ones it has not delivered before, and it does not go further back.

## `listName` (type: `string`):

Name of the memory used by "Only posts not delivered before" (looked at only when that is on). Use a different name for each project. Letters, digits and hyphens (a hyphen not first or last), up to 40 characters; capitals are read as lower case.

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

Nothing to change for normal use: requests leave from the run's own address, and the Actor moves to Apify Proxy by itself if Instagram turns that address away. Turn a proxy on here to send every request through it: the run then stays on that proxy, and a setting the platform refuses ends the run with a message before anything is read.

## Actor input object example

```json
{
  "profiles": [
    "natgeo"
  ],
  "maxPostsPerProfile": 24,
  "maxPosts": 100000,
  "includeDetails": false,
  "onlyNewPosts": false,
  "listName": "default",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "profiles": [
        "natgeo"
    ],
    "maxPostsPerProfile": 24,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("foxlabs/instagram-profile-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 = {
    "profiles": ["natgeo"],
    "maxPostsPerProfile": 24,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("foxlabs/instagram-profile-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 '{
  "profiles": [
    "natgeo"
  ],
  "maxPostsPerProfile": 24,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call foxlabs/instagram-profile-posts-scraper --silent --output-dataset

```

## MCP server setup

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