# Instagram Public Posts Scraper (`zinin/instagram-public-posts-scraper`) Actor

Scrape current public Instagram posts and reels, captions, media links, and source URLs from logged-out profile pages without login.

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

## Pricing

from $2.10 / 1,000 public instagram post delivereds

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 Public Posts & Reels Scraper

![Instagram public posts and reels](https://api.apify.com/v2/key-value-stores/IwI7VoxszQjT6v69X/records/instagram-public-posts-scraper-b9bbaead98c1cf3e-readme-hero.webp?signature=1cpVuzEfOLnDMskrYNRT7)

Turn a public Instagram profile into structured post and reel rows for monitoring, research, or an internal content dashboard. Submit an exact profile root such as `https://www.instagram.com/instagram/`; the Actor returns source-visible post IDs, post or reel URLs when exposed, captions, display-media URLs, media types, product types, and observation timestamps. It reads logged-out public profile HTML through Apify Residential Proxy. No Instagram login, cookies, browser session, or customer credential is required.

Each run observes one currently returned HTML document per requested profile and delivers at most 12 rows in total. This is a bounded current-feed observation, not a full profile archive. If the first profile fills the shared cap, later profiles are not requested. The retained real source fixture produced 12 rows from `instagram`, with validated post or reel URLs. `likeCount` and `publishedAt` remain `null` because that source did not expose verified values. A URL remains null when the source node provides neither a valid canonical URL nor a shortcode.

```json
{"profileUrls":["https://www.instagram.com/instagram/"],"maxItems":12}
```

The price is **$0.003 per delivered post or reel** through `result-found`. There is no start fee or default Dataset-item fee, and source failures or diagnostics are free. Bronze pays $0.0027, Silver $0.0024, and Gold, Platinum, and Diamond $0.0021 per delivered row. Repeating a successful observation is billable again because it delivers a fresh timestamped Dataset row.

Selected fields from the retained public fixture:

```json
{"postId":"3983211470613048091","postURL":"https://www.instagram.com/reel/DdHNbqDJusb/","username":"instagram","caption":"Every room is its own world 🖊️⁣\n⁣\n@draw_vengers drew this building cutaway with fineliner pens. Inside each space? Imaginary elements like a nuclear-powered rocket, an indoor shipwreck and more.⁣\n⁣\n“I really made the drawing up as I went along! The fun was in thinking up all sorts of ideas for what rooms I could draw in.”⁣\n⁣\nVideo by @draw_vengers⁣\n⁣\nMusic by @harrystyles","mediaType":2,"productType":"clips","likeCount":null,"publishedAt":null,"sourceURL":"https://www.instagram.com/instagram/","observedAt":"2026-09-12T11:49:47+00:00"}
```

### What you receive

The default Dataset contains one row per delivered source node. Every row includes `schemaVersion`, `recordType`, `postId`, `postURL`, `username`, `caption`, `displayUrl`, `mediaType`, `productType`, `likeCount`, `publishedAt`, `sourceURL`, `observedAt`, a SHA-256 source reference, and billing metadata. Nullable fields remain `null`; the Actor does not manufacture missing engagement or dates.

`OUTPUT` records the outcome, delivery status, per-profile evidence, errors, and a compact snapshot of delivered rows. `outcome: "completed"` means the available rows were delivered without a source error. `deliveryComplete` and `coverage.complete` remain `false` at the one-page boundary because the result is not a full archive. `source_failed`, `partial`, `empty`, and `budget_stopped` stay distinct.

### How the source is handled

![Observed public-profile workflow](https://api.apify.com/v2/key-value-stores/IwI7VoxszQjT6v69X/records/instagram-public-posts-scraper-a04f16cb5a634e1e-readme-workflow.webp?signature=1iKF8KVbeJM90v9o1aBnd)

The parser reads only `application/json` `data-sjs` Relay data found in the received logged-out page. It accepts nodes whose embedded username matches the requested profile, or whose timeline profile ID joins to that verified username. Public URLs come only from a validated Instagram canonical URL or shortcode. It leaves `publishedAt` null unless the received source contains a verified timestamp; it does not infer a publication date from a media ID. It does not create private GraphQL calls or follow pagination.

Requests use HTTPS with certificate validation, reject redirects, allow one attempt per profile, cap both compressed and decoded content at 5 MiB, and share a bounded run deadline. A login redirect, HTTP error, unexpected content type, malformed Relay data, oversized response, or timeout produces no paid row.

### Ready-to-use Task recipes

**Current profile snapshot — up to 12 source-visible nodes**

```json
{"profileUrls":["https://www.instagram.com/instagram/"],"maxItems":12}
```

**Three-row sample from the same verified source**

```json
{"profileUrls":["https://www.instagram.com/instagram/"],"maxItems":3}
```

**Repeat snapshot — schedule the same bounded input**

```json
{"profileUrls":["https://www.instagram.com/instagram/"],"maxItems":12}
```

Replace `instagram` with the exact root of the public profile you are authorized to observe. Inputs can contain up to 10 unique profiles, but the 12-row cap is shared and input order matters.

### Costs and run budgets

| Tier | Price per delivered row | 12 delivered rows |
|---|---:|---:|
| Base | $0.0030 | $0.0360 |
| Bronze | $0.0027 | $0.0324 |
| Silver | $0.0024 | $0.0288 |
| Gold / Platinum / Diamond | $0.0021 | $0.0252 |

The runtime checks the run's effective charge limit before requesting the source and again before each paid write. When starting runs through the Apify API, use a **positive** `maxTotalChargeUsd`. A value of `0` can be treated by the platform as unset and replaced by its default. To verify the no-affordable-row path, use a small positive value below one result price, such as `0.0001`.

### Repeat observations safely

Keep the exact input, run ID, Dataset, and `OUTPUT` together. Compare `postId` values only across the same ordered profile list and `maxItems`. A missing ID means only that the item was not observed within that run's one-page, 12-row boundary; it does not prove deletion. Media CDN URLs can expire, so retain the post URL and source evidence rather than treating a display URL as permanent storage.

Use the data only for lawful purposes and according to Instagram's terms and applicable rights. The Actor reads public pages and does not access private profiles, messages, or account data.

# Actor input Schema

## `profileUrls` (type: `array`):

Exact public profile roots, for example https://www.instagram.com/instagram/. Up to 10 profiles per run.

## `maxItems` (type: `integer`):

Total delivered current timeline nodes. This Actor reads one observed public profile page and cannot promise archive or pagination coverage.

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.instagram.com/instagram/"
  ],
  "maxItems": 12
}
```

# Actor output Schema

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

One billable instagram\_public\_post row for each delivered public timeline node.

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

Observed profile-page coverage, delivery state and delivered-row snapshot.

# 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 = {
    "profileUrls": [
        "https://www.instagram.com/instagram/"
    ],
    "maxItems": 12
};

// Run the Actor and wait for it to finish
const run = await client.actor("zinin/instagram-public-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 = {
    "profileUrls": ["https://www.instagram.com/instagram/"],
    "maxItems": 12,
}

# Run the Actor and wait for it to finish
run = client.actor("zinin/instagram-public-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 '{
  "profileUrls": [
    "https://www.instagram.com/instagram/"
  ],
  "maxItems": 12
}' |
apify call zinin/instagram-public-posts-scraper --silent --output-dataset

```

## MCP server setup

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