# 🌟Instagram Scraper Pro (`databuddy/instagram-scraper-pro`) Actor

- **URL**: https://apify.com/databuddy/instagram-scraper-pro.md
- **Developed by:** [Sarthak](https://apify.com/databuddy) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00005 / actor start

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 Scraper Pro — Posts, Reels, Comments, Profiles, Hashtags & Places

Scrape public Instagram data in one tool:

- posts and reels;
- comments and replies;
- mentions (posts where a profile is tagged);
- details of profiles, hashtags and places;
- discovery by search.

It also adds what plain scrapers leave out:

- **engagement rate** for every post and profile;
- **emails and phones from bios**, with evidence;
- **related hashtags measured from real posts**;
- **numeric post IDs** accepted anywhere;
- a **free status row for every input that fails**, saying how to fix it.

**Keywords:** instagram scraper · instagram api alternative · instagram post scraper · instagram reels scraper · instagram comments scraper · instagram profile scraper · instagram hashtag scraper · instagram location scraper · engagement rate · influencer research · brand monitoring · UGC

***

### ✨ What's different

| | This actor | Typical Instagram scrapers |
|---|---|---|
| Posts, reels, comments, replies, mentions, profile, hashtag and place details, search | ✅ | ✅ |
| **Numeric post IDs** (`/p/3923124318436838545/`) in every mode | ✅ | comments only |
| **Engagement rate %** on every post (from the owner's followers) and profile | ✅ | ❌ |
| **Business email, phone and address, plus emails and phones in bios** — with the exact source | ✅ | ❌ |
| **Related hashtags from the hashtag's own posts**, with counts; posts/day estimate with its basis | ✅ | third-party estimates |
| Hidden like counts returned as `null` with `likesHidden: true`, never a fake number | ✅ | `-1` |
| Filters: date, skip pinned, min likes, min comments | ✅ | date and pinned |
| **Skip items saved in previous runs**, so scheduled runs only pay for new items | ✅ | ❌ |
| Inputs that fail get a row with `status` and `fixHint`, never charged | ✅ | ❌ |
| `DIAGNOSTICS` record: which Instagram methods worked in your run | ✅ | ❌ |

### 🔒 What Instagram shows without a login (tested October 2026)

Instagram decides what logged-out visitors may see, and it changes this often. This actor tries several methods per data type and reports exactly what happened.

| Data | Logged-out status | What you get |
|---|---|---|
| Profile posts (by username or ID) | ✅ Works | Full post data, paginated |
| Profile reels tab | ✅ Works | Full reel data with play counts |
| Profile details | ⚠️ Often login-walled | When walled, a **partial profile** from the public feed: name, ID, verified, private, avg likes/comments, last post and latest 12 posts. `missingFields` lists what Instagram withheld (followers, bio, contacts). Nothing is guessed. |
| Comments, mentions, single-post details, hashtags, places, search | ⚠️ Usually login-walled | A free `login_required` row explaining it. The actor detects the wall after 2 tries and stops spending proxy traffic on it. |

**Proxy:** Instagram rate-limits some IP pools much more than others. In October 2026 tests, shared residential IPs were often blocked while datacenter and server IPs worked for posts and reels. The default is Apify datacenter proxy, with **automatic fallback**: if the chosen proxy keeps getting blocked, the actor moves to the next network route by itself. `RUN_SUMMARY.routes` shows which route was used.

The first input of every run goes alone, to learn which methods work before scaling to 25 parallel inputs. Every run writes `DIAGNOSTICS` with per-method results.

### 🔧 Input

**Mode 1: URLs.** Paste one or more URLs and pick **Content to scrape**:

| URL | Posts | Reels | Comments | Mentions | Details |
|---|---|---|---|---|---|
| Profile (`instagram.com/nike/`, `@nike`, profile ID) | ✅ | ✅ | — | ✅ | ✅ profile |
| Post or reel (`/p/…`, `/reel/…`, numeric ID, share link) | — | — | ✅ | — | ✅ post |
| Hashtag (`/explore/tags/travel/`, `#travel`) | ✅ | ✅ | — | — | ✅ hashtag |
| Place (`/explore/locations/7538318/`) | ✅ | ✅ | — | — | ✅ place |

`_u`, `profilecard`, story links and `/share/` links are handled automatically.

**Mode 2: search.** This is used only when no URLs are given. Enter comma-separated terms and choose hashtags, profiles or places. Each hit is then scraped with the content type you picked.

```json
{
  "directUrls": ["https://www.instagram.com/natgeo/", "#travel"],
  "resultsType": "posts",
  "resultsLimit": 50,
  "onlyPostsNewerThan": "30 days",
  "skipPinnedPosts": true,
  "proxyConfiguration": { "useApifyProxy": true },
  "proxyFallback": true
}
```

| Option | What it does |
|---|---|
| `resultsLimit` | Results per URL or search hit. |
| `maxItems` | Cap on results for the whole run (0 = none). |
| `onlyPostsNewerThan` | A relative period (`3 days`, `2 weeks`) or a date (`2024-09-05`, `2024-09-05T13:22:04Z`), in UTC. |
| `skipPinnedPosts`, `minLikes`, `minComments` | Post filters. Posts they remove are never charged. |
| `isNewestComments`, `includeNestedComments` | Comment order, and whether to include replies (each reply is its own row). |
| `addParentData` | Adds the profile, hashtag, place or post each row came from. |
| `skipPreviouslyScraped` | Skips IDs already saved by earlier runs. |
| `saveRawResponses` | Debug only: stores raw Instagram responses. |

### 📤 Output

Every row has a `status` and a `resultType` (`post`, `reel`, `mention`, `comment`, `reply`, `profile`, `hashtag`, `place`), plus `inputUrl`, `dataSource` and `scrapedAt`.

**Post or reel:**

- `id`, `shortCode`, `url`, `type`, `productType`;
- `caption`, `hashtags`, `mentions`;
- `likesCount`, `likesHidden`, `commentsCount`, `videoViewCount`, `videoPlayCount`, `videoDuration`;
- **`engagementRate`**, `ownerFollowersCount`, `timestamp`;
- `displayUrl`, `videoUrl`, `images`, `childPosts`;
- `ownerUsername`, `ownerFullName`, `ownerId`;
- `taggedUsers`, `coauthorProducers`, `locationName`, `musicInfo`;
- `isPinned`, `isSponsored`, `isCommentsDisabled`, `firstComment`, `latestComments`.

**Comment:**

- `postUrl`, `commentUrl`, `id`, `text`;
- `ownerUsername`, `ownerId`, `ownerProfilePicUrl`, `ownerIsVerified`;
- `timestamp`, `likesCount`, `repliesCount`, `parentCommentId`, `isReply`.

**Profile:**

- `username`, `fullName`, `biography`, `externalUrls`;
- `followersCount`, `followsCount`, `postsCount`;
- `verified`, `private`, `isBusinessAccount`, `businessCategoryName`, `category`;
- **`businessEmail`, `businessPhone`, `businessAddress`, `emailsFromBio`, `phonesFromBio`, `contactEvidence`**;
- **`avgLikes`, `avgComments`, `engagementRate`, `lastPostAt`**;
- `relatedProfiles`, `latestPosts`.

**Hashtag:**

- `name`, `postsCount`;
- **`relatedHashtags`** (with `postsInSample` and `sharePct`);
- **`postsPerDayEstimate`** with `postsPerDayBasis`;
- `topPosts`, `latestPosts`.

**Place:**

- `locationId`, `name`, `category`, `phone`, `website`;
- `lat`, `lng`, `address`, `city`, `zip`;
- `postsCount`, `igBusinessUsername`, `hoursStatus`;
- `topPosts`, `latestPosts`.

**Failed input:**

- `status`: `login_required`, `blocked`, `not_found`, `private`, `no_results`, `duplicate_input`, `invalid_input` or `unsupported_combination`;
- `error` and `fixHint`.

The dataset has five views: Overview, Posts & reels, Comments, Profiles and Failed inputs.

### 📊 Run records

Each run writes two records to Storage → Key-value store:

- **`RUN_SUMMARY`** lists, per input, what was saved, what was skipped and why, and which method fetched it. It also has charged events and request counts.
- **`DIAGNOSTICS`** gives, for each Instagram method, its attempts, successes, block statuses and last problem. If inputs come back `blocked`, this record shows the developer exactly what to fix.

### 💰 Pricing

| Event | When |
|---|---|
| `instagram-item` | Each post, reel, comment, reply or mention saved |
| `instagram-details` | Each profile, hashtag or place details row saved |

Failed inputs, duplicates, items from previous runs and filtered items are **never charged**. Set "Max cost per run" and the run stops cleanly at your budget.

### ❓ FAQ

**Do I need an Instagram account?** No. It reads what Instagram shows logged-out visitors.

**Why do counts differ from what I see in the app?** Logged-out visitors see slightly different numbers, and counts change by the minute. Open the post in a private window and compare it with the run's timestamp.

**Some inputs say `login_required`.** Instagram showed its login wall for that data type, and no method got past it. It isn't charged. Run again later; Instagram opens and closes these walls often.

**Some inputs say `blocked`.** Instagram rate-limited every network route the run tried. Wait 10–15 minutes and run again, with "Automatic proxy fallback" on. If it keeps happening, send the `DIAGNOSTICS` record to the developer.

**Can it scrape private accounts?** No. Profile details of a private account are returned, but its posts are not.

**Why is a reels run labelled "filtered from profile posts"?** When the reels tab can't be loaded, reels are taken from the main profile feed instead. The result is the same data, but older reels may be missed.

### ⚖️ Notes

This actor collects only publicly available Instagram data. Some public data may be personal data under GDPR and similar laws. Scrape only with a legitimate purpose, and respect Instagram's terms.

# Actor input Schema

## `directUrls` (type: `array`):

One per line: profile (instagram.com/nike/ or @nike), profile ID, post or reel URL (shortcode or numeric ID), hashtag (instagram.com/explore/tags/travel/ or #travel), place (instagram.com/explore/locations/7538318/), share links and story links. Each URL's type decides what it can return. URLs take priority over Search.

## `resultsType` (type: `string`):

One content type per run. Profiles → posts, reels, mentions or details. Posts/reels → details or comments. Hashtags and places → posts, reels or details. Note: Instagram currently shows profile posts and reels to logged-out visitors; comments, mentions, hashtags, places and full profile details are often behind its login wall (those inputs get a free login_required row).

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

How many results to save for each URL or search hit. Comment replies (when turned on) are extra.

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

Stop the whole run after this many saved (and charged) results. 0 = no limit.

## `search` (type: `string`):

Comma-separated, e.g. "travel, fitness" for hashtags, "nike, adidas" for profiles, or "vintage shop copenhagen" for places. Hashtags without the #.

## `searchType` (type: `string`):

What to search for. Found items are scraped with the "Content to scrape" setting.

## `searchLimit` (type: `integer`):

How many hashtags, profiles or places to take from each search term.

## `onlyPostsNewerThan` (type: `string`):

Relative ("3 days", "2 weeks", "6 months") or a date ("2024-09-05", "2024-09-05T13:22:04Z"). UTC. Leave empty for all posts. Profile scraping stops paging once it reaches older posts.

## `skipPinnedPosts` (type: `boolean`):

Leave out posts pinned to the top of a profile (often old).

## `minLikes` (type: `integer`):

Skip posts with fewer likes. Posts with hidden like counts are skipped when this is set. 0 = off.

## `minComments` (type: `integer`):

Skip posts with fewer comments. 0 = off.

## `isNewestComments` (type: `boolean`):

Fetch comments newest-first instead of Instagram's default "most relevant" order.

## `includeNestedComments` (type: `boolean`):

Also save replies to comments, each as its own row with parentCommentId. Replies don't count toward "Max results per URL".

## `addParentData` (type: `boolean`):

Adds a parentData object to every row (the profile, hashtag, place or post it came from).

## `includeFailedInputs` (type: `boolean`):

Adds one row per input that returned nothing (status = login_required / blocked / not_found / private / no_results / duplicate_input / invalid_input) with the reason and how to fix it. Never charged.

## `skipPreviouslyScraped` (type: `boolean`):

Remembers saved post, comment and profile IDs in a named key-value store, so scheduled runs only save (and charge) new items.

## `dedupeStoreName` (type: `string`):

Name of the key-value store that remembers saved IDs. Lowercase letters, numbers and hyphens.

## `saveRawResponses` (type: `boolean`):

Saves the first 2 raw Instagram responses per method to the key-value store (RAW\_\* records). Turn on only when the developer asks for it.

## `proxyFallback` (type: `boolean`):

If Instagram keeps blocking the chosen proxy, switch automatically to Apify datacenter proxy and then to the Apify server's own IP. The routes used are listed in RUN_SUMMARY.

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

Apify Proxy (datacenter, the default) works well for posts and reels. Instagram often rate-limits shared residential IPs, so RESIDENTIAL is not always better. With "Automatic proxy fallback" on, a blocked proxy is replaced automatically.

## Actor input object example

```json
{
  "directUrls": [
    "https://www.instagram.com/natgeo/"
  ],
  "resultsType": "posts",
  "resultsLimit": 50,
  "maxItems": 0,
  "search": "",
  "searchType": "hashtag",
  "searchLimit": 10,
  "onlyPostsNewerThan": "",
  "skipPinnedPosts": false,
  "minLikes": 0,
  "minComments": 0,
  "isNewestComments": false,
  "includeNestedComments": false,
  "addParentData": false,
  "includeFailedInputs": true,
  "skipPreviouslyScraped": false,
  "dedupeStoreName": "instagram-scraper-pro-seen",
  "saveRawResponses": false,
  "proxyFallback": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `comments` (type: `string`):

No description

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

No description

## `failed` (type: `string`):

No description

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

No description

## `diagnostics` (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 = {
    "directUrls": [
        "https://www.instagram.com/natgeo/"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("databuddy/instagram-scraper-pro").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 = {
    "directUrls": ["https://www.instagram.com/natgeo/"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("databuddy/instagram-scraper-pro").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 '{
  "directUrls": [
    "https://www.instagram.com/natgeo/"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call databuddy/instagram-scraper-pro --silent --output-dataset

```

## MCP server setup

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

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/NseBP6O1dChrBTPzd/builds/UCTVmowefl2c1kiuM/openapi.json
