# Instagram Profile Scraper - Engagement Rates (`datalayer/instagram-profile-stats`) Actor

Followers, engagement rate and recent post performance for any public Instagram profile. Paste 300 handles and get 300 rows. The spend cap is checked before every request and stops the run - it does not trim results after your money is gone. Filtered and private profiles are never charged for.

- **URL**: https://apify.com/datalayer/instagram-profile-stats.md
- **Developed by:** [Datalayer](https://apify.com/datalayer) (community)
- **Categories:** Social media, Lead generation
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 profiles

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 Scraper — engagement rates, with a spend cap that holds

Follower counts, engagement rate and recent post performance for any public Instagram profile. Paste 300 handles, get 300 rows, and **never spend more than you said you would.**

### The limit you set is the limit you get

The most-used Instagram scrapers on this store carry thousands of monthly users and ratings in the 3s. Their reviews explain why, in their own words:

> *"I set the limit but this actor fetched a lot of records and I spent hundreds of USD in vain. I want my credit back"*

> *"Even though I set a limit on the request, it fetched thousands of records and simply used up hundreds of dollars"*

Two different people, same actor, same complaint. So this one is built the other way round:

- **`maxProfiles` and `maxCostUsd` are checked before each request**, not applied to the results afterwards. When the ceiling is reached the run *stops fetching*. Trimming the output after the money is gone is not a limit.
- **Filtered-out profiles are never charged for.** Private accounts and profiles under your follower minimum cost nothing.
- **A date range that cannot be read stops the run** instead of being silently dropped, which is the other complaint on the competing Twitter and Facebook scrapers.
- Every run writes a summary telling you exactly what you spent against your cap.

### What you get

**One row per profile:**

| Field | Notes |
|---|---|
| `followers`, `following`, `postsTotal` | Live counts |
| `engagementRatePercent` | Average interactions per post ÷ followers |
| `avgLikes`, `avgComments`, `avgEngagement` | Across the recent posts sampled |
| `isVerified`, `isPrivate`, `isBusinessAccount`, `category` | Account type |
| `fullName`, `biography`, `externalUrl` | Bio block, including the link |
| `profilePicUrl`, `profileUrl` | Full-resolution avatar |

**One row per recent post**, when `includePosts` is on: `likes`, `comments`, `engagement`, `caption`, `hashtags`, `isVideo`, `videoViews`, `postedAt`, `postUrl`.

#### Two honest limits, stated up front

**Instagram returns the 12 most recent posts per profile.** That is what the endpoint gives, and this Actor does not pretend to page deeper. Sampling 12 recent posts is exactly how engagement rate is normally calculated, but if you need a profile's entire history, this is the wrong tool and you should know that before you pay rather than after.

**Hidden like counts return `null`, not `0`.** Instagram lets accounts hide likes. A zero there would quietly destroy any average you calculate, so the gap is left visible and posts with hidden counts are excluded from the averages.

### What it is for

- **Influencer vetting** — engagement rate across a shortlist, in one run. A 500k-follower account with 0.2% engagement is a different proposition to a 40k account at 6%.
- **Competitor monitoring** — follower and posting trends across a category, on a schedule.
- **Agency reporting** — client and competitor numbers pulled the same way every week.
- **Lead qualification** — business accounts, categories and the link in bio.

### Input

```json
{
  "profiles": ["nasa", "@bbcnews", "https://www.instagram.com/natgeo/"],
  "maxProfiles": 100,
  "maxCostUsd": 5,
  "includePosts": true,
  "minFollowers": 10000,
  "skipPrivate": true
}
```

Usernames, `@handles` and full URLs all work, so a column pasted straight from a spreadsheet is fine.

### Reliability

**One bad handle never fails the run.** A profile that does not exist, or is challenged by Instagram, is recorded in the run summary with the reason while everything else continues.

Instagram intermittently answers a valid handle with an error on one address and succeeds on the next. Rather than reporting that as "profile not found" — which would silently drop real profiles from a large list — the request is retried on a fresh address before it is ever reported as missing.

Requests go through Apify Proxy residential, which is the only route Instagram answers with data. Changing it will usually break the run.

### FAQ

**Do I need an Instagram account or login?** No. The Actor reads the public
profile endpoint Instagram serves to logged-out visitors. There is no account
to get flagged or banned.

**How is engagement rate calculated?** Average interactions (likes + comments)
across the recent posts sampled, divided by followers. Hidden like counts come
back as `null`, never as a fake zero, so they cannot drag the average down.

**How many posts do I get per profile?** Up to 12 — the most recent posts the
public endpoint carries. That is Instagram's ceiling, not ours, and we say so
rather than promising 100 and delivering 12.

**Can I export to CSV or Excel?** Yes — every run's dataset downloads as CSV,
Excel, JSON or JSONL straight from the platform, or via the API for pipelines.

**Can I run it on a schedule?** Yes. Create a Task with your handle list and
schedule it hourly, daily or weekly. Each run writes a fresh dataset.

**What happens when a profile fails?** It is retried on a fresh IP before it is
ever reported missing, and failures are listed per handle in the run summary —
never silently dropped from your results.

### Notes

Reads only public profile data, logged out — the same information any visitor sees without an account. No login, no cookies, no account of yours involved. Private accounts return no posts or counts by design. This Actor is unofficial and not affiliated with Instagram or Meta. Content belongs to the people who posted it; use it in line with applicable laws and terms.

# Actor input Schema

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

Usernames, @handles or full profile URLs. All three forms work, so you can paste straight from a spreadsheet.

## `maxProfiles` (type: `integer`):

Hard stop. The run stops fetching once this many profiles have been delivered - it does not keep spending and trim afterwards.

## `maxCostUsd` (type: `integer`):

Hard ceiling on what this run may cost. Reached it, the run stops and tells you. Leave empty for no cost ceiling.

## `includePosts` (type: `boolean`):

Adds a row per recent post with likes, comments, caption and hashtags. Instagram returns the 12 most recent per profile.

## `postsFrom` (type: `string`):

Only keep posts on or after this date, e.g. 2026-01-01. Posts outside the range are never charged for. An unreadable date stops the run rather than being ignored.

## `postsTo` (type: `string`):

Only keep posts on or before this date.

## `minFollowers` (type: `integer`):

Skip profiles under this follower count. Skipped profiles are not charged for.

## `skipPrivate` (type: `boolean`):

Private accounts publish no posts or counts. Skipping them costs you nothing.

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

Instagram only answers residential addresses, so this defaults to Apify Proxy residential. Changing it will usually break the run.

## Actor input object example

```json
{
  "profiles": [
    "nasa",
    "@bbcnews",
    "https://www.instagram.com/natgeo/"
  ],
  "maxProfiles": 100,
  "maxCostUsd": 5,
  "includePosts": true,
  "postsFrom": "",
  "postsTo": "",
  "minFollowers": 0,
  "skipPrivate": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Every profile and post returned by this run as clean JSON.

## `profilesCsv` (type: `string`):

The same rows as a CSV download, ready for a spreadsheet.

## `runSummary` (type: `string`):

What was delivered, what was skipped by your filters, what failed, and what it cost against your cap.

# 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",
        "https://www.instagram.com/natgeo/"
    ],
    "maxProfiles": 100,
    "maxCostUsd": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("datalayer/instagram-profile-stats").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",
        "https://www.instagram.com/natgeo/",
    ],
    "maxProfiles": 100,
    "maxCostUsd": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("datalayer/instagram-profile-stats").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",
    "https://www.instagram.com/natgeo/"
  ],
  "maxProfiles": 100,
  "maxCostUsd": 5
}' |
apify call datalayer/instagram-profile-stats --silent --output-dataset

```

## MCP server setup

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

```

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/rtNHMtuqfzQ4I2fbx/builds/hu0WVMsNjbwb87IRN/openapi.json
