# Instagram Posts Scraper — Profile Posts, Captions & Stats (`lergassy/instagram-posts-scraper`) Actor

Instagram posts scraper and API: every public post of a profile with caption, hashtags, mentions, likes, comments, plays, media links and location. No login, no cookies, no run fee.

- **URL**: https://apify.com/lergassy/instagram-posts-scraper.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** Social media, Marketing, AI
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.75 / 1,000 target checkeds

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** turns public Instagram profiles, post links or hashtags into a flat table. One row per post or per comment: caption, hashtags and mentions pulled out of it, likes, comments, plays, the media file link, location and the author. No login, no cookies, no Instagram account of yours at risk.

### Three modes, one Actor

| Mode | You give | One row is |
|---|---|---|
| 👤 **Posts of a profile** | handles or profile links | one post |
| 💬 **Comments under a post** | post or reel links | one comment |
| #️⃣ **Posts under a hashtag** | hashtags | one post |

### Why this needs us at all

Instagram shows none of this to a logged-out visitor: the profile page answers with a redirect to the login screen and its internal API answers `401 require_login`. Checked on 28 October 2026 from a plain server and again through a residential address — same answer both times. This Actor reads the data through a paid source that holds the sessions, so you never hand over your own cookies and never get an account flagged.

### What it costs

Two charges, both stated before you press Start:

| What is charged | When |
|---|---|
| **One target** | Once per profile, post link or hashtag in your list — even if it turns out to be private, empty or deleted |
| **One row** | For every post or comment actually delivered |

There is also a **run fee**, and it is the smallest one in this niche — 30% below the cheapest competitor charges to start a run.

#### On the Apify Free plan

A run collects the **first target in your list in full** — every row it has, not a sample — and **nothing is charged at all**. The remaining targets come back as a free note saying they were left alone. So you can see the real shape and the real volume of the data before you pay anything.

The reason the rest is held back is plain: every target costs us a request to a paid data source, and the free plan does not cover it.

Why a target is charged even when it is empty: looking it up costs us one request to the data source whether it returns sixty posts or none. A private profile and a post with comments turned off are normal answers, not failures.

### Output

```json
{
  "type": "post",
  "postUrl": "https://www.instagram.com/p/ABC123/",
  "ownerUsername": "natgeo",
  "takenAt": "2026-10-27T14:07:48.000Z",
  "caption": "…",
  "hashtags": ["wildlife", "photography"],
  "mentions": ["natgeotravel"],
  "likeCount": 27400,
  "commentCount": 312,
  "playCount": 905718,
  "imageUrl": "https://…",
  "videoUrl": null,
  "locationName": "Serengeti"
}
```

Comment rows carry the comment text, its author, when it was written, how many likes and replies it has, and whether the author of the post wrote it.

### What it does not do

- Private accounts. The target is charged like any other lookup, no rows come back.
- Likes of a private post, or who viewed a story. Instagram does not publish those.
- Posting, liking or replying. This Actor only reads.

### For AI agents

- **Minimal input:** `{"mode": "posts", "usernames": ["natgeo"]}` — or `{"mode": "comments", "postUrls": ["https://www.instagram.com/p/DemLxMGgoL_/"]}`, or `{"mode": "hashtags", "hashtags": ["wildlife"]}`.
- **Returns:** one row per post (`posts`, `hashtags`) or per comment (`comments`); `maxItemsPerTarget` caps each profile, post or hashtag. A target that gives nothing — private account, comments off, hidden hashtag — gets one free `type: "notice"` row with the reason; filter it out with `type != "notice"`.
- **Time:** about 10 seconds for 20 comments of one post, 30–50 seconds for 60 posts of one profile. A few targets — call synchronously (`run-sync-get-dataset-items`); long lists — start the run and poll it.

### Errors and empty runs

An empty run always says why in its own words — private account, comments turned off, hashtag hidden — in a free `notice` row. Filter it out with `type != "notice"`. If the data source stops answering, the run passes its answer through word for word instead of guessing.

### Your feedback

Found a bug or a missing field? Open an issue on the Actor page. Problems reported by buyers are fixed the same day.

# Changelog

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

# Actor input Schema

## `mode` (type: `string`):

Each mode uses its own field below.

## `usernames` (type: `array`):

Handles (nasa), @handles or profile links. <b>Each profile here is charged once as a target</b>, even if it turns out to be private or empty; delivered posts are charged on top.

## `postUrls` (type: `array`):

Links to posts or reels. <b>Each link here is charged once as a target</b>, even if comments are turned off; delivered comments are charged on top.

## `hashtags` (type: `array`):

With or without the # sign. <b>Each hashtag here is charged once as a target</b>; delivered posts are charged on top.

## `hashtagSort` (type: `string`):

Only used in the "hashtags" mode.

## `maxItemsPerTarget` (type: `integer`):

Per profile, per post or per hashtag. The Actor pages until it has this many or the source runs out. <b>On the Apify Free plan a run collects the first target in full and is not charged</b>; the rest of the list comes back as a note.

## Actor input object example

```json
{
  "mode": "posts",
  "usernames": [
    "natgeo"
  ],
  "postUrls": [],
  "hashtags": [],
  "hashtagSort": "top",
  "maxItemsPerTarget": 60
}
```

# Actor output Schema

## `results` (type: `string`):

One row per post or per comment.

## `summary` (type: `string`):

Rows delivered, targets charged and how many requests the data source has left.

# 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 = {
    "mode": "posts",
    "usernames": [
        "natgeo"
    ],
    "postUrls": [],
    "hashtags": [],
    "hashtagSort": "top"
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/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 = {
    "mode": "posts",
    "usernames": ["natgeo"],
    "postUrls": [],
    "hashtags": [],
    "hashtagSort": "top",
}

# Run the Actor and wait for it to finish
run = client.actor("lergassy/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 '{
  "mode": "posts",
  "usernames": [
    "natgeo"
  ],
  "postUrls": [],
  "hashtags": [],
  "hashtagSort": "top"
}' |
apify call lergassy/instagram-posts-scraper --silent --output-dataset

```

## MCP server setup

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