# Instagram Profile Posts · Capped (`steadyfetch/instagram-profile-posts`) Actor

Every post and reel from any public Instagram profile — captions, hashtags, engagement, media links, tagged accounts. A post we cannot deliver is never charged. Your result limit is exact: set 30 and you get 30, not 240 because a page size said so. No login, no cookies.

- **URL**: https://apify.com/steadyfetch/instagram-profile-posts.md
- **Developed by:** [Steadyfetch Team](https://apify.com/steadyfetch) (community)
- **Categories:** Social media, Automation, MCP servers
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 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 Profile Posts · Capped

**Your result limit is the law.** Set it to 30 and you get 30 — not 31, not 240 because the
page size said so. Every post and reel from any public Instagram profile, no login and no
cookies, and a post we could not deliver is never charged.

Paste a handle. Get the posts.

*Unofficial. Not affiliated with, endorsed by, or sponsored by Instagram or Meta Platforms, Inc.
This actor reads publicly available profile pages; Instagram is a trademark of Meta Platforms, Inc.*

***

### Output

One row per post, one row per profile, and every row carries `charged` and `status` — so your
invoice reconciles from the dataset itself. Real rows below, taken from a verified run against
`nasa` (captions trimmed with … for the page):

| shortCode | type | takenAt | caption | likeCount | commentCount | playCount | videoDuration |
|---|---|---|---|---|---|---|---|
| `DcOX3hWFiey` | `image` | 2026-08-19T14:11:47Z | With your powers combined… This colorful picture of the cosmos is the product of teamwork between our @NASAHubble, @NASAWebb… | 432,624 | 2,998 | — | — |
| `DcMXl1IPNtB` | `video` | 2026-08-18T19:37:40Z | Soothing spacewalk scenes. Today, August 18, NASA's @astro\_anil and… | 86,418 | 719 | 3,142,693 | 50.2 |
| `Db9IVmrDvQ4` | `image` | 2026-08-12T21:28:58Z | When the Moon and Sun align. This rare sight — a total solar eclipse —… | 2,405,782 | 4,587 | — | — |

The first row above in full, exactly as it lands in the dataset (caption and signed URL trimmed
with … for the page):

```json
{
  "postId": "3967213292204992434",
  "shortCode": "DcOX3hWFiey",
  "url": "https://www.instagram.com/p/DcOX3hWFiey/",
  "type": "image",
  "productType": "feed",
  "caption": "With your powers combined…\n\nThis colorful picture of the cosmos is the product of teamwork between our @NASAHubble, @NASAWebb, and @NASAChandraXray telescopes…",
  "hashtags": ["nasa", "universe", "nebula"],
  "mentions": ["nasahubble", "nasawebb", "nasachandraxray"],
  "takenAt": "2026-08-19T14:11:47.000Z",
  "takenAtTimestamp": 1787148707,
  "likeCount": 432624,
  "commentCount": 2998,
  "playCount": null,
  "videoDuration": null,
  "displayUrl": "https://instagram.fruh4-3.fna.fbcdn.net/v/t51.82787-15/780550892_…",
  "videoUrl": null,
  "videoUrlExpiresAt": null,
  "carouselCount": null,
  "dimensionsWidth": 1280,
  "dimensionsHeight": 1129,
  "ownerUsername": "nasa",
  "ownerFullName": "NASA",
  "ownerIsVerified": true,
  "taggedUsers": [],
  "coauthors": [],
  "isPinned": true,
  "isSponsored": false,
  "postSource": "feed",
  "profileHandle": "nasa",
  "charged": true,
  "status": "delivered",
  "statusReason": null
}
```

And one **profile row** per handle you asked about — uncharged, always:

```json
{
  "profileHandle": "nasa",
  "profileUrl": "https://www.instagram.com/nasa/",
  "fullName": "NASA",
  "biography": "Making the seemingly impossible, possible. ✨",
  "externalUrl": "https://www.nasa.gov/",
  "followers": 104427542,
  "following": 92,
  "postCount": 4893,
  "isVerified": true,
  "isPrivate": false,
  "isBusiness": true,
  "categoryName": "Government Agencies",
  "postsReturned": 30,
  "postsFiltered": 0,
  "charged": false,
  "status": "profile",
  "statusReason": "Profile row for \"nasa\" — 30 posts returned. This row itself carries no result fee."
}
```

Every field is always present (explicit `null` over silent omission), so a row from the profile
route and a row from the depth route are the same shape.

### Agent / API paste-block

```
Actor:   steadyfetch/instagram-profile-posts  (Apify Store)
Does:    Instagram handle -> every post and reel that public profile has published.
         One JSON row per post + one uncharged profile row per handle.
         No Instagram login, no cookies.
Run:     POST https://api.apify.com/v2/acts/steadyfetch~instagram-profile-posts/run-sync-get-dataset-items?token=APIFY_TOKEN
Input:
  {
    "profiles": ["nasa", "https://www.instagram.com/bbcnews/"],
    "resultsLimit": 30,        // HARD cap per profile, newest first (1-5000)
    "maxItems": 1000,          // HARD cap for the whole run (1-100000)
    "maxRunSeconds": 900,      // clean stop before the platform timeout
    "mediaType": "any",        // any | image | video | carousel
    "postedAfter": "2026-01-01",
    "postedBefore": "2026-08-01",
    "datasetId": "<dataset id of a run that emits handles>",
    "datasetItems": [ { "username": "nasa" } ]
  }
Output   post rows: postId, shortCode, url, type, productType, caption, hashtags[],
         mentions[], takenAt, takenAtTimestamp, likeCount, commentCount, playCount,
         videoDuration, displayUrl, videoUrl, videoUrlExpiresAt, carouselCount,
         dimensionsWidth, dimensionsHeight, ownerUsername, ownerFullName,
         ownerIsVerified, taggedUsers[], coauthors[], isPinned, isSponsored,
         postSource, profileHandle, charged, status, statusReason
         profile rows (uncharged): profileHandle, profileUrl, fullName, biography,
         externalUrl, followers, following, postCount, isVerified, isPrivate,
         isBusiness, categoryName, postsReturned, postsFiltered
         one final summary row: delivered, profilesRequested, stoppedBy, resumeCursor
Pricing  pay per event, platform usage INCLUDED, no start fee:
  post   $0.0024 -> $0.0006 per delivered post (falls with your Apify plan tier)
  Charged only on delivery — private accounts, wrong handles, empty profiles,
  filtered-out posts and Instagram's own walls cost $0.
  Cap any run with maxTotalChargeUsd (minimum $0.05).
MCP:     reachable through Apify's MCP server; ask for "instagram profile posts".
```

### Input

Handles (`nasa`), or profile URLs (`https://www.instagram.com/nasa/`). Capital letters, a
leading `@` and a trailing slash are all fine. You can also chain a **Dataset ID** from a
previous run and this actor will find the profiles in it.

Optional: max posts per profile, max posts for the whole run, post type, posted-after and
posted-before dates, max run seconds.

Leave the input empty and you get uncharged sample rows showing the exact schema, without
touching Instagram.

### The limits are hard, and they name themselves

Three things can stop a run: your result limit, your maximum cost per run, or your time
limit. Whichever binds, the run still finishes **successfully**, the last row tells you
which one it was and what is still pending, and only delivered posts were charged. You will
never have to guess which knob to raise.

The result limit is exact under concurrency too: two profiles are read in parallel, and a
whole-run cap of 1 still delivers exactly one row and exactly one charge.

### What it costs

**One result = one delivered post or reel**, with everything Instagram publishes about it in
the same row. There is no second charge for "details" — no per-field, per-comment or
per-image top-up. No start fee, no subscription, no third-party API key to buy.

**from $0.60/1,000 posts** — $0.0024 each on the free plan, falling to $0.0006 on the top
Apify plan tier. Platform usage (compute + transfer) is **included in the event price**, so
the per-post price you see is the whole price.

**What can fail, and it is free when it does.** These rows ship with `charged: false`, always:

| status | when |
|---|---|
| `not_found` | no public profile at that handle — wrong, renamed or deleted |
| `private_account` | the account is private, so its posts are not publicly readable |
| `no_posts` | a real public profile with nothing on it |
| `rate_wall` / `rate_limited` | Instagram asked us to wait, and was still asking after retries |
| `unavailable_schema` | Instagram's own profile service is erroring for that handle |
| `empty_response` / `source_unavailable` | Instagram answered, but with nothing readable |
| `input_error` | that input is not an Instagram profile — the row names the fix |

Posts your filters excluded are also never delivered and never charged; the profile row counts
them. Cap any run with **Maximum cost per run** (any amount from $0.05 up) and it stops
cleanly before your ceiling.

### Honesty contract

A profile that returns nothing still gets a row, and the row says why — uncharged, every
time:

| status | what it means | can a re-run help? |
|---|---|---|
| `not_found` | no public profile at that handle — wrong, renamed or deleted | no |
| `private_account` | the account is private, so its posts are not publicly readable | no |
| `no_posts` | a real public profile with nothing on it — a definitive answer | no |
| `unavailable_schema` | Instagram's own profile service is erroring for that handle | no, it is on their side |
| `rate_wall` / `rate_limited` | Instagram asked us to wait, and was still asking after retries | **yes** |
| `empty_response` | Instagram answered but sent an empty body | **yes** |
| `source_unavailable` | Instagram did not return readable data on this run | **yes** |
| `input_error` | that input is not an Instagram profile — the row names the fix | fix and re-run |

A post that appears on two profiles you asked for (a co-authored post) is **one row and one
charge**, not two. If Instagram stops serving a profile part-way through, the profile row says
so and is marked worth re-running — a partial answer never reads like a complete one.

This actor may fail when the platform changes things — failed items are never charged.

### Freshness

Post data is read live on every run, so it is as current as Instagram's own public profile
page. The `videoUrl` and image links are signed by Instagram and expire in roughly **1–3
days** — the `videoUrlExpiresAt` column tells you exactly when, so download or transcribe
soon after the run rather than months later. The permalink in `url` never expires.

### Works with

Chain this actor's output straight into the transcript actors, or feed it from any actor
that emits Instagram handles.

| Chain | How |
|---|---|
| **Profiles → reel transcripts** | run this actor, then pass its **Dataset ID** to [Instagram Reels to Text · @handle](https://apify.com/steadyfetch/instagram-reel-transcript-scraper) — it reads the `videoUrl` column |
| **Any list of handles → posts** | pass a **Dataset ID** here; rows need a `username` / `ownerUsername` field or an instagram.com profile URL |
| **Paste rows directly** | use **Dataset items** instead of a dataset ID |

### Steadyfetch Instagram suite

Handle in, structured rows out. All-inclusive pay per event, no start fee, charged only on delivery.

| What you want | Actor |
|---|---|
| Reels turned into text, with the 3-second hook | [Instagram Reels to Text · @handle](https://apify.com/steadyfetch/instagram-reel-transcript-scraper) |
| A profile's recent posts, capped where you say | **this actor** |

**The rest of the steadyfetch shelf** — same contract everywhere: all-inclusive pay per event,
no start fee, charged only on delivery.

| Family | Actors |
|---|---|
| Ad creative intelligence | [Facebook](https://apify.com/steadyfetch/facebook-ads-transcript-scraper) · [Google Ads video](https://apify.com/steadyfetch/google-ads-video-transcript-scraper) · [TikTok](https://apify.com/steadyfetch/tiktok-ads-transcript-scraper) · [LinkedIn](https://apify.com/steadyfetch/linkedin-ads-transcript-scraper) · [Google Ads text & OCR](https://apify.com/steadyfetch/google-ads-creative-text-scraper) |
| Trends & keywords | [Google Trends](https://apify.com/steadyfetch/google-trends-scraper) · [Trends Now](https://apify.com/steadyfetch/google-trends-now-scraper) · [Breakout keywords](https://apify.com/steadyfetch/breakout-keywords-scraper) · [Autocomplete keywords](https://apify.com/steadyfetch/google-keyword-suggest-scraper) · [Keyword volume & CPC](https://apify.com/steadyfetch/keyword-search-volume-scraper) · [Social trends](https://apify.com/steadyfetch/social-trends-scraper) |
| YouTube transcripts | [YouTube videos](https://apify.com/steadyfetch/youtube-transcript-scraper) · [YouTube channels](https://apify.com/steadyfetch/youtube-channel-transcripts) |
| **Instagram** | [Reel transcripts](https://apify.com/steadyfetch/instagram-reel-transcript-scraper) · [Profile posts](https://apify.com/steadyfetch/instagram-profile-posts) |
| Jobs | [Indeed](https://apify.com/steadyfetch/indeed-jobs-scraper) · [Career sites by domain](https://apify.com/steadyfetch/company-jobs-by-domain) · [Glassdoor](https://apify.com/steadyfetch/glassdoor-jobs-scraper) · [Multi-board](https://apify.com/steadyfetch/multi-job-board-scraper) |
| Amazon | [Products](https://apify.com/steadyfetch/amazon-product-scraper) · [Search](https://apify.com/steadyfetch/amazon-search-scraper) · Bestsellers · Sellers |
| Any media file | [Speech to Text](https://apify.com/steadyfetch/media-transcriber) · any link or file |

Unlinked names are publishing shortly on the same account — search **steadyfetch** on Apify Store.

### Feedback & support

Open an issue on the actor's **Issues tab** with the input you used — we respond within one
business day. Bugs on our side are fixed; misses on Instagram's side are documented in the row
you already have.

# Actor input Schema

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

Instagram handles (nasa), or profile URLs (https://www.instagram.com/nasa/). Capital letters and a leading @ are fine. Leave the default in place to see uncharged sample rows first. Omit the field entirely rather than sending null.

## `resultsLimit` (type: `integer`):

Hard cap on delivered posts from any single profile. Newest first.

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

Hard cap on delivered posts across every profile in this run.

## `maxRunSeconds` (type: `integer`):

The run stops cleanly before this many seconds and reports what is left, instead of being killed by a timeout.

## `mediaType` (type: `string`):

Return only one kind of post. Leave as Any for everything.

## `postedAfter` (type: `string`):

Only posts published on or after this date. Use YYYY-MM-DD.

## `postedBefore` (type: `string`):

Only posts published before this date. Use YYYY-MM-DD.

## `datasetId` (type: `string`):

Dataset from a previous run to read profiles from. Selecting it here is what grants this run permission to read it.

## `datasetItems` (type: `array`):

Rows pasted directly, instead of a dataset ID.

## Actor input object example

```json
{
  "profiles": [
    "nasa",
    "bbcnews"
  ],
  "resultsLimit": 30,
  "maxItems": 1000,
  "maxRunSeconds": 900,
  "mediaType": "any"
}
```

# Actor output Schema

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

One row per post or reel: caption, hashtags, mentions, engagement, media links, tagged accounts, co-authors and the permalink. Every row carries `charged` and `status`, so the invoice reconciles from the dataset itself. Only rows with charged = true were billed.

## `profiles` (type: `string`):

One row per profile you asked about: followers, bio, category, how many posts were returned and how many your filters excluded. Profiles that returned nothing are never charged and say why.

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

Delivered count, profiles returned, uncharged misses, duplicate sightings skipped (first sighting kept), what stopped the run, and the charged-event totals.

## `errors` (type: `string`):

Present only when Instagram rate-limited, walled or dropped a request after retries: the handle and the reason. These are re-runnable, not permanent.

# 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": [
        "nasa",
        "bbcnews"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyfetch/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 = { "profiles": [
        "nasa",
        "bbcnews",
    ] }

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

```

## MCP server setup

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