# Instagram Profile Scraper Pro — All-in-One Discovery & Leads (`thenetaji/instagram-profile-scraper-pro`) Actor

Five discovery modes in one Actor: expand a seed account's network up to 5 levels, enrich a specific list, export followers/following, search by keyword, or pull a post's likers and commenters. Every mode can enrich results with business contacts and a computed engagement quality score.

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

## Pricing

from $0.75 / 1,000 results

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 Pro

The Actor runs five separate Instagram discovery methods behind a single `scraperType` selector: expanding a seed account's network of related accounts, enriching a specific list of accounts, exporting an account's followers or following, searching for accounts by keyword, and pulling the likers and commenters of a post. Any mode that returns account records can additionally attach business contact fields and a computed engagement quality score, so a single run can produce a list of leads rather than a plain account list.

Each mode uses a different subset of the input fields; a field not relevant to the selected mode is simply ignored. The sections below document each mode's own inputs and outputs before covering the shared enrichment options.

### Discovery modes

| `scraperType` | What it does | Primary input |
|---|---|---|
| `similarUsers` | Expands one or more seed accounts into Instagram's own suggested-accounts set, optionally chained outward across up to 5 levels | `username` |
| `userInfo` | Resolves a specific list of usernames to profile records | `username` |
| `followersFollowing` | Exports an account's followers or following list | `username`, `type` |
| `searchUsers` | Searches Instagram for accounts matching a keyword | `keyword` |
| `mediaInfo` | Fetches a post's full media details, optionally with its comments and likers | `codes` |

#### Network expansion (`similarUsers`)

Follows the same suggested-accounts chaining as this project's dedicated related-accounts Actor: `chainDepth` (capped at 5) controls how many levels outward the traversal follows, `maxItemPerLevel` bounds branching per level, and `exportGraph` interleaves `_type: "graph_edge"` rows describing the discovery path alongside the account records.

```json
{
  "username": ["nasa"],
  "scraperType": "similarUsers",
  "chainDepth": 2,
  "maxItemPerLevel": 5
}
```

#### Specific accounts (`userInfo`)

Resolves each username in `username` to one profile record, without any discovery step. `fullProfileDetails` extends the record with post previews, media count, and business fields.

#### Followers/following (`followersFollowing`)

`type` selects `followers` or `followings`; `resumeCursor` continues a large export from a previously logged cursor rather than restarting it.

#### Keyword search (`searchUsers`)

`keyword` searches Instagram's own account search and returns ranked hits (`position` records the rank). `addonProfile` swaps each hit for its full public profile.

#### Post engagement (`mediaInfo`)

`codes` accepts post/reel shortcodes (not numeric media IDs). `addonComments` and `addonLikes` each attach their respective lists as nested `comments`/`likes` objects on the media record; `commentsSortType` orders the attached comments.

### Shared enrichment

#### Business contacts

`fullProfileDetails` (Network Expansion, Specific Accounts, Followers/Following) and `addonProfile` (Keyword Search) each extend a profile record with `is_business_account`, `business_category_name`, `business_email`, `business_phone_number`, `business_contact_method`, and `business_address_json` — public fields the account has chosen to publish. A field is `null` when the account has not published it; nothing is inferred or looked up elsewhere.

A minority of professional accounts currently fail on Instagram's own full-profile source and fall back to a reduced profile; those records carry `is_partial: true` and `partial_reason: "upstream_schema_error"`, and their business fields are absent rather than genuinely empty.

#### Engagement metrics

`computeEngagementMetrics` samples an account's most recent posts (up to 12) and attaches:

| Field | Meaning |
|---|---|
| `avg_likes`, `avg_comments` | Mean across the sampled posts |
| `posts_per_month` | Estimated from the spread between the newest and oldest sampled timestamps; `null` when fewer than two posts were sampled |
| `avg_views` | Mean play count across sampled video/reel posts only; `null` if none of the sampled posts were video |
| `views_follower_ratio`, `engagement_rate` | The above relative to follower count; `null` when follower count is 0 |
| `quality_score` | A single 0-100 figure combining the three signals above, for sorting accounts without comparing five separate columns |
| `metrics_sample_size` | How many posts the figures were computed from |

`quality_score` weights engagement rate highest (60% of the score, or 50% when view data is available), posting consistency next, and reach from `views_follower_ratio` last when present. Always check `metrics_sample_size` before trusting a score built from one or two posts.

This applies only to account-returning modes (Network Expansion, Specific Accounts, Followers/Following, Keyword Search); it has no effect on Post Engagement, since that mode returns a media record rather than an account.

### Frequently asked questions

**Why does `codes` say shortcode and not media ID?**
Post Engagement's underlying lookup requires the shortcode form (the string in a post's URL, e.g. `DZpQwxqimz2`), not the numeric media ID. This project's other post-lookup Actor accepts both; this mode does not.

**Why are `avg_views` and `views_follower_ratio` `null` for an account with plenty of posts?**
Both are computed only from video/reel posts in the sample. An account whose recent posts are all photos has no view data to average, so the fields are `null` rather than zero.

**Why did `computeEngagementMetrics` charge for an account that returned no metrics?**
The sample fetch (up to 12 recent posts) is a request against the account regardless of what it finds; an account with zero public posts still costs that request even though no metrics can be computed from an empty sample.

**Does Keyword Search's `addonProfile` cost the same as `fullProfileDetails` on the other modes?**
Yes — both fetch the same full public profile per account and bill under the same event.

**Why did a Network Expansion run with `chainDepth` at 4 return far more accounts than expected?**
Expansion is multiplicative, not additive: each level multiplies by `maxItemPerLevel`, so depth 4 at the default of 5 reaches 625 accounts from a single seed before deduplication. Lowering `maxItemPerLevel` narrows each level while preserving reach; lowering `chainDepth` cuts levels outright.

### Related Actors

| Actor | Purpose |
|---|---|
| [Instagram Related Users Scraper](https://apify.com/thenetaji/instagram-related-user-scraper) | Network expansion alone, with the discovery graph as its primary output |
| [Instagram User Info Scraper](https://apify.com/thenetaji/instagram-user-info-scraper) | Specific-account profile lookups alone |
| [Instagram Followers & Followings Scraper](https://apify.com/thenetaji/instagram-followers-followings-scraper) | Followers/following export alone |
| [Instagram Post Scraper](https://apify.com/thenetaji/instagram-post-scraper) | Post details, comments, and oEmbed metadata by shortcode or URL |

# Actor input Schema

## `scraperType` (type: `string`):

Which discovery mode to run — pick this first. Every field below is labeled with which mode(s) it applies to; fields for other modes are simply ignored.

## `username` (type: `array`):

Instagram usernames to scrape. Used by Network Expansion, Specific Accounts, and Followers/Following — ignored by Keyword Search and Post Engagement.

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

Followers or followings. Only used when Discovery Mode is Followers/Following.

## `keyword` (type: `string`):

Search keyword. Only used when Discovery Mode is Keyword Search.

## `codes` (type: `array`):

Instagram post/reel shortcodes. Only used when Discovery Mode is Post Engagement.

## `maxItem` (type: `integer`):

Maximum number of results (0 = unlimited). Not used by Specific Accounts or Post Engagement, which always process every username/code given.

## `resumeCursor` (type: `string`):

Optional. If an earlier run of this Actor stopped partway through, open its log, copy the code next to '📍 RESUME CURSOR', and paste it here to carry on from where it left off instead of starting over.

## `enrichProfile` (type: `boolean`):

Fetch full profile details for each account. Only used by Network Expansion and Followers/Following.

## `fullProfileDetails` (type: `boolean`):

Extend enrichment to the full profile payload (business fields included). Used together with Enrich Profiles (Network Expansion, Followers/Following) or on its own (Specific Accounts, which always fetches a profile).

## `addonProfile` (type: `boolean`):

Fetch each hit's full public profile. Only used when Discovery Mode is Keyword Search.

## `computeEngagementMetrics` (type: `boolean`):

Fetch each account's recent posts and attach average likes/comments, posting frequency, view/follower ratio, and a composite quality score. Costs an extra event per account.

## `addonComments` (type: `boolean`):

Attach a page of comments to each result. Only used when Discovery Mode is Post Engagement.

## `addonLikes` (type: `boolean`):

Attach the liker list to each result. Only used when Discovery Mode is Post Engagement.

## `commentsSortType` (type: `string`):

Sort order for attached comments. Only used when Include Comments is on.

## `chainDepth` (type: `integer`):

Discover accounts connected to your results, not just directly similar ones. Set to 1 to also find users similar to your results. Set to 2 to go one level further. Leave at 0 to skip this.

## `maxItemPerLevel` (type: `integer`):

How many similar accounts to follow at each step of the chain. Lower = faster and more focused. Higher = broader discovery.

## `exportGraph` (type: `boolean`):

In chain mode, also push a graph edge record for every discovered connection: { from, to, depth }. Useful for network visualization.

## `verifiedOnly` (type: `boolean`):

Only include verified accounts. Only used when Discovery Mode is Network Expansion.

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

Exclude private accounts. Only used when Discovery Mode is Network Expansion.

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

Only include accounts with at least this many followers. Only used when Discovery Mode is Network Expansion; requires Enrich Profiles.

## `maxFollowers` (type: `integer`):

Only include accounts with at most this many followers. Only used when Discovery Mode is Network Expansion; requires Enrich Profiles.

## `excludePosts` (type: `boolean`):

Strip post and video timeline data from enriched profiles. Removes the largest fields — highly recommended.

## `excludeSavedMedia` (type: `boolean`):

Strip saved media and collections data from enriched profiles.

## `excludeInternalFlags` (type: `boolean`):

Strip internal viewer-relationship and supervision flags rarely useful for scraping (e.g. blocked\_by\_viewer, is\_supervised\_user, ai\_agent\_type).

## `excludeBioLinkDetails` (type: `boolean`):

Remove tracking URLs from bio links and strip the duplicate biography\_with\_entities field.

## Actor input object example

```json
{
  "scraperType": "similarUsers",
  "username": [
    "natgeo"
  ],
  "type": "followers",
  "keyword": "tokyo",
  "codes": [
    "DZpQwxqimz2"
  ],
  "maxItem": 100,
  "enrichProfile": false,
  "fullProfileDetails": false,
  "addonProfile": false,
  "computeEngagementMetrics": false,
  "addonComments": false,
  "addonLikes": false,
  "commentsSortType": "popular",
  "chainDepth": 0,
  "maxItemPerLevel": 5,
  "exportGraph": false,
  "verifiedOnly": false,
  "skipPrivate": false,
  "minFollowers": 0,
  "maxFollowers": 0,
  "excludePosts": false,
  "excludeSavedMedia": false,
  "excludeInternalFlags": true,
  "excludeBioLinkDetails": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

All records scraped by this run

# 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 = {
    "username": [
        "natgeo"
    ],
    "keyword": "tokyo",
    "codes": [
        "DZpQwxqimz2"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("thenetaji/instagram-profile-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 = {
    "username": ["natgeo"],
    "keyword": "tokyo",
    "codes": ["DZpQwxqimz2"],
}

# Run the Actor and wait for it to finish
run = client.actor("thenetaji/instagram-profile-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 '{
  "username": [
    "natgeo"
  ],
  "keyword": "tokyo",
  "codes": [
    "DZpQwxqimz2"
  ]
}' |
apify call thenetaji/instagram-profile-scraper-pro --silent --output-dataset

```

## MCP server setup

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