# Instagram Profile Scraper: Followers, Bio, Posts (`automation_craft/instagram-profile-scraper`) Actor

Scrape Instagram profiles by username or user id, no login: exact followers, following and post count, bio and links, account type, category, HD picture and the newest posts with likes and engagement. Filters, related accounts, Page contact. JSON, CSV or API; pay per profile.

- **URL**: https://apify.com/automation_craft/instagram-profile-scraper.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** Social media, Lead generation, Marketing
- **Security:** Limited permissions
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.48 / 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?

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 Profile Scraper: Followers, Bio, Posts

**Scrape Instagram profiles by username** and get one row per public account with its exact followers, following and post count,
bio and every bio link, account type, category, HD profile picture and its newest posts with likes and comments, without an
Instagram account, cookies or login. Paste usernames, @handles, profile links or numeric user ids (up to 5,000 a run) and get one
row per account, plus a free row that says what became of every entry of your list.

- **Exact counts.** Followers and following as Instagram counts them, and the exact number of posts read from the profile's own
  embed page, not a rounded "14K".
- **The whole profile.** Bio and its hashtags, website and every bio link, account type (personal, business, creator), category,
  verified, private, memorialized, Threads profile, highlights, pronouns, the HD picture, Instagram's state media and news labels,
  and the 6 newest posts with engagement figures computed from them.
- **Options when you need them.** The 12 newest posts as the grid shows them, reel figures (plays of the 12 newest reels), the
  accounts Instagram suggests next to each profile (on the row, or delivered as profiles of their own up to 10 levels deep, with
  a cap in all and per profile), and the public contact of the Facebook Page the account links (a paid add-on).
- **Filters that cost nothing.** Followers, posts, verified, account type, private accounts only or left out, influencers only,
  words in the name, bio or posts, category, language, an e-mail or phone shown, a website, engagement rate, posting activity,
  reel plays. Accounts a filter leaves
  out are never charged.
- **Fair billing.** Each account is charged once per run. Accounts that do not exist or are not shown to a logged out reader,
  failed reads, repeats and refused entries are free, and the account list row names every one of them by its position.

### Quick start

1. Open the Actor's **Input** tab and paste your accounts in **Instagram accounts**, one per line: `nasa`, `@natgeo`,
   `https://www.instagram.com/nike/` or a numeric user id such as `528817151`.
2. Optional: turn on the options you need (latest 12 posts, reel figures, suggested accounts, the Facebook Page contact) and add
   filters.
3. Click **Start**. Each account arrives as a row of the dataset, followed by the free account list row and a run summary.
4. Download the dataset as JSON, CSV or Excel, or read it through the Apify API, a schedule, Make, n8n or Zapier.

### What you get

One `profile` row per account. The fill rates below were measured on the platform on 2026-11-04 on 1,244 distinct public and
private accounts of many kinds (brands, news, small businesses, creators, athletes, public figures; runs xmUs30bUQfhe9PJuS and
DBCNe7PYMszd9Vs92), read without a login. Options were measured on the 300 accounts of the second run (291 public).

| Field | What it holds | Filled |
|---|---|---|
| `inputPosition` | the account's position in your list (empty for an account the expansion added) | 100% of list accounts |
| `username`, `id`, `fbid`, `url`, `fullName` | the username, Instagram's numeric id, its second id (the one Meta's Graph API uses), the profile link and the name | 100%, name 97.8% |
| `biography`, `bioHashtags` | the bio as Instagram serves it, and the hashtags Instagram marks in it | 92.8%, 8.8% |
| `followerCount`, `followingCount`, `followerToFollowingRatio` | exact followers and following, and their ratio | 100% |
| `postsCount` | the exact post count, from the profile's embed page (private accounts show none) | 97.2% of public accounts |
| `accountType`, `isProfessional`, `isBusinessAccount`, `category` | `personal`, `business` or `creator`, and the category the account shows | type 100%, category 43.7% |
| `isVerified`, `isPrivate`, `isMemorialized`, `isMetaVerified` | the badges and states Instagram serves | 100% |
| `externalUrl`, `bioLinks`, `externalUrlShimmed` | the website and every bio link with its title and type; Instagram's redirect link for the website with **Include personal data** (it is an instagram.com address) | 68.5%, 68.8% |
| `profilePicUrl`, `profilePicUrlHd` | the picture, small and full size | 100% |
| `threadsUsername`, `threadsUrl` | the account's Threads profile | 47.3% |
| `highlightTitles`, `latestStoryAt`, `hasPublicStory`, `hasReels`, `reelsCount`, `pronouns` | the first page of story highlights, the latest story, reels, pronouns | highlights 59.2%, reels count 92.1%, pronouns 6.9% |
| `transparencyLabel`, `transparencyProduct`, `newsRestrictedIn` | Instagram's own labels: state controlled media, and the countries where it limits the account's news (`CA`) | where Instagram shows them (news limits 1.0%) |
| `recentPosts`, `recentPostTimes` | the 6 newest posts (pinned posts left out): link, type, date, likes, comments, caption, paid partnership, place | 6 posts on 96.0% of public accounts |
| `avgLikes`, `avgComments`, `engagementRate`, `engagementGrade`, `postsPerWeek`, `lastPostAt` | engagement of the 6 newest posts (likes plus comments over followers, in percent; grade `high` from 3%, `average` from 1%, else `low`), the posting pace, the newest post | engagement 88.8%, last post 93.1% |
| `biographyLanguage` | the language of the bio and recent captions, our own estimate (README "Filters") | 84.6% |
| `hasEmail`, `hasPhone` | whether the bio, bio links or recent captions show an e-mail address or a phone number | 12.2%, 0.6% |
| `emails`, `phones`, `bioMentions` | those addresses and numbers with where each was found, and the accounts the bio mentions: empty unless you turn on **Include personal data** | when asked |
| `latestPosts` | option: the 12 newest posts as the grid shows them (pinned first): link, type, reel flag, date, caption, likes, comments, picture, place, paid partnership, carousel size; `latestPostsStatus` says when they could not be read | 12 posts on 286 of 291 public accounts (the rest have fewer) |
| `reelStats` | option: `reelsRead`, `medianPlays`, `averagePlays`, `maxPlays`, `newestReelCreatedAt`, `medianPlaysToFollowersPercent` | 273 of 291 public accounts (18 have no reels) |
| `relatedProfiles` | option: the accounts Instagram suggests next to this one; needs **Include personal data** | 115 of 300 accounts (38.3%) had any |
| `facebookPage`, `facebookPageContact` | add-on: the Facebook Page Instagram links to the account, else the one Page Meta's Ad Library search names with this account as its Instagram account (`id`, `name`, `alias`, `url`, `category`, `likes`, `country`), and the Page's public `emails`, `phones`, `whatsapp`, `websites`, `addresses`, `hours`, `priceRange`, `services`, `categories`, `ratings` | Page found for 133 of 300 (44.3%), contact read for 95 (31.7%) |
| `foundVia`, `relatedTo`, `expansionLevel` | `username` for an account of your list; `related_profile`, the profile it was suggested next to and its level for an account the expansion added | 100% |
| `detailsStatus` | `read`, or `partial` when a public account's embed showed no post count, or no posts while it counts some (that row is free) | partial 2.7% |

Likes an account hides are never written as 0: such a post has `likeCount` null and `likesHidden` true (831 of 6,927 recent posts,
12.0 percent, on 2026-11-04).

Example row (the prefill run r0VOClAvveYVswHdd of 2026-11-04, cut short):

```json
{
  "type": "profile",
  "inputPosition": 1,
  "username": "nasa",
  "id": "528817151",
  "url": "https://www.instagram.com/nasa/",
  "fullName": "NASA",
  "followerCount": 104428839,
  "followingCount": 90,
  "postsCount": 4988,
  "accountType": "business",
  "category": null,
  "isVerified": true,
  "isPrivate": false,
  "externalUrl": "https://www.nasa.gov",
  "avgLikes": 475466.5,
  "avgComments": 2058.2,
  "engagementRate": 0.457,
  "engagementGrade": "low",
  "lastPostAt": "2026-11-03T18:39:27.000Z",
  "postsPerWeek": 6.59,
  "recentPosts": [{ "url": "https://www.instagram.com/p/DfSi56IFwZK/", "postedAt": "2026-11-03T18:39:27.000Z", "likeCount": 184767, "commentCount": 502 }],
  "emails": null,
  "detailsStatus": "read"
}
```

**The account list row (free).** One `subject` row for your list: its `status`, `finished`, `stopReason`, how many accounts were
read and delivered, and `accountOutcomes`: how many were delivered, and by position which were not found (or not shown to a logged
out reader), left out by a filter, already delivered, or not reached because the run stopped. Every entry of your list ends in
exactly one of those places, or in a free refused entries row when it is not an account at all. (A run the platform stops during
its start up, before it read its own dataset back, names every entry under `notReadThisAttempt` instead, with no delivered count:
rows an earlier attempt of the same run delivered stay delivered.) The last row of every run is a free
`summary` row with the run's counts.

### How much does it cost to scrape Instagram profiles?

You pay per result (pay per event). Prices per 1,000 events:

| Event | Free | Bronze | Silver | Gold |
|---|---|---|---|---|
| Profile (one account delivered as a row with its details) | $0.67 | $0.61 | $0.55 | $0.475 |
| Facebook Page contact (add-on, a linked Page that shows contact details) | $2.10 | $1.92 | $1.74 | $1.50 |
| Re-filtered profile (a profile of an earlier run that passes this run's filters) | $0.10 | $0.09 | $0.08 | $0.07 |

Platinum and Diamond plans pay the Gold price. Each run also pays the Actor start event of $0.0075 (256 MB), which has no plan
discount. The Store pricing card shows these same prices per 1,000 events: "$0.475 / 1,000" on the Profile row means one profile
costs less than a twentieth of a cent.

Examples at the Gold price: 10 profiles cost $0.0075 + 10 x $0.000475 = $0.0123; 1,000 profiles cost $0.0075 + 1,000 x
$0.000475 = $0.4825; the same 1,000 with the Facebook Page contact read for the 300 whose Page shows one add 300 x $0.0015 = $0.45.
The latest 12 posts, reel figures and suggested accounts on the row add no charge.

Free: the account list row, status rows, left out rows, the summary, accounts that do not exist or are not shown to a logged out
reader (age restricted accounts included), accounts a filter leaves out, repeats, accounts whose posts could not be read (a
public account whose embed shows no post count, or no posts while it counts some: delivered free with `detailsStatus` `partial`), Facebook Pages without contact details
or without an exact match, failed calls, refused entries and invalid input. An invalid input charges only the run's start fee.

### Input

| Setting | What it does | Default |
|---|---|---|
| `usernames` | the accounts: usernames, @handles, profile links or numeric user ids, up to 5,000 | |
| `maxProfiles` | stop after this many profiles | every account |
| `includeRecentPosts` | the 6 newest posts on the row | on |
| `includeLatestPosts` | the 12 newest posts as the grid shows them | off |
| `latestPostsSince` | keep only latest posts on or after a day (`2026-10-01`) or within "N days" | all 12 |
| `includeReelStats` | reel figures of the 12 newest reels | off |
| `includeRelatedProfiles` | the suggested accounts on the row (needs `includePersonalData`) | off |
| `includeFacebookPageContact` | the linked Facebook Page and its public contact (paid add-on) | off |
| `expandWithRelatedProfiles` | deliver the suggested accounts as profiles of their own (each a Profile) | off |
| `expansionDepth` | how many levels of suggested accounts, 1 to 10 | 1 |
| `maxRelatedProfiles` | the most accounts the expansion adds | 50 |
| `maxRelatedPerAccount` | the most suggestions the expansion takes from each profile, 1 to 50 | 50 |
| `minFollowers`, `maxFollowers`, `minPosts`, `maxPosts` | follower and post ranges | none |
| `verified` | `any`, `only` or `exclude` | `any` |
| `accountTypes` | `personal`, `business`, `creator`, `professional` (business or creator) | every type |
| `influencersOnly` | creators and accounts whose category is a person who publishes (README "Filters") | off |
| `includePrivate` | keep private accounts (their header and counts) | on |
| `onlyPrivate` | keep only private accounts | off |
| `mustContain`, `mustContainIn` | words or phrases that must be in the username, name, bio or recent captions | none |
| `excludeWords` | leave out accounts whose username, name or bio holds any of these | none |
| `categories`, `combineCategoryAndWords` | words of the Instagram category; with `mustContain`, both or either | none, both |
| `languages` | two letter codes of the bio and captions language | any |
| `contactFilter` | an e-mail, a phone, either or both shown | any |
| `requireWebsite` | keep accounts with a website or bio link | off |
| `minEngagementRate` | minimum engagement rate in percent | none |
| `activeWithinDays` | newest post at most this many days old | none |
| `minRecentPosts`, `recentPostsDays` | at least N of the 6 newest posts within the period | none, 30 days |
| `minMedianReelPlays`, `reelPostedWithinDays`, `minPlaysToFollowersPercent`, `maxPlaysToFollowersPercent` | reel filters (need `includeReelStats`) | none |
| `excludeUsernames` | accounts never to deliver, up to 10,000 | none |
| `includeLeftOutAccounts` | a free row for every account read and left out, with the reason | off |
| `minMatchRatePercent` | stop when, after 100 accounts judged, fewer than this percent passed the filters | never |
| `refilterDatasetId` | filter an earlier run's profile rows again without reading Instagram | none |
| `includePersonalData` | fill the fields that name or reach a person (see "Personal data") | off |
| `maxConcurrency` | accounts read at the same time, 1 to 4 | 4 |
| `maxRunSeconds`, `requestTimeoutSecs`, `maxRetries` | time limits and retries | platform timeout, 30, 2 |
| `proxyConfiguration` | Apify Proxy (default: the run's own address first, Apify's datacenter proxy when a request type is refused there) | Apify Proxy |

#### Filters

Every filter is judged once, on the row as it will be delivered; an account a filter leaves out is free, and a value the account
does not show fails the filter that asks for it (a missing count is never read as 0). A filter whose data a failed read left out
is never a filter miss: such an account is a failed read, free and named on the account list row. **Influencers only** keeps
creator accounts and accounts whose category is one of: Digital creator, Video creator, Gaming video creator, Blogger, Personal
blog, Public figure, Artist, Musician, Musician/band, Athlete, Fitness model, Fashion model, Model, Actor, Comedian, Writer, Author,
Photographer, Gamer, Dancer, Chef, Entrepreneur, Coach, Personal coach, Fitness trainer, Makeup artist, Podcast, Journalist, News
personality, Motivational speaker, DJ, Producer, Designer, Fashion designer. Instagram serves no language for an account: the
language is our own estimate from the bio and each recent caption (the franc library, a text of 40 letters or more with a clear
result), the language most of them agree on; a tie or nothing clear gives no language, and **Languages** leaves such accounts out.

#### Work that earns nothing

Reads that deliver no profile (names that do not exist or are not shown logged out, accounts a filter leaves out, failed reads)
are free, so the run bounds them: a run starts with a small allowance of such work and every profile it delivers adds to it.
When the allowance is spent the run stops with `work_allowance`, and the account list row names the accounts not reached so you
can run them again. Measured on 2026-11-04: 700 made up names stopped after 301 reads; 300 made up names were all read in one run
and stopped after 255 in another; a filter nobody passes (300 real accounts, a minimum of a billion followers) stopped after 40
reads, since each of those reads is a full profile read. A list whose first few hundred entries all miss, or a strict filter on
a large list, can therefore stop before the accounts behind them: put the accounts you trust first, or split the list. A list
that delivers profiles runs to its end.

#### Personal data

With **Include personal data** off (the default), the fields that name or reach a person are empty: `emails`, `phones`,
`relatedProfiles`, `bioMentions`, the collaborators of the latest posts, the usernames of suggested accounts a filter left out
(left out rows), Instagram's redirect link `externalUrlShimmed`, and links to Instagram, Facebook, Messenger, Threads or WhatsApp
and contact links (any app link such as mailto, tel, sms, callto, tg or sgnl, and links to messaging services such as Telegram,
Signal, Viber, Skype or LINE) in `externalUrl` and `bioLinks`. Turn it on to fill them. Bios and captions are always delivered exactly as Instagram serves them. You are responsible
for a lawful use of personal data, GDPR included.

### API examples

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~instagram-profile-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"usernames": ["nasa", "natgeo", "nike"], "includeLatestPosts": true}'
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('automation_craft/instagram-profile-scraper').call({ usernames: ['nasa', '528817151'], minFollowers: 1000 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((row) => row.type === 'profile').map((row) => [row.username, row.followerCount, row.postsCount]));
```

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("automation_craft/instagram-profile-scraper").call(run_input={"usernames": ["mrbeast", "cristiano"], "includeReelStats": True})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["type"] == "profile":
        print(row["username"], row["followerCount"], row["engagementRate"])
```

### What this Actor does NOT do

- **No follower or following lists, no likers and no mutual followers.** Instagram shows them only to logged in viewers; this Actor
  reads logged out only.
- **No "About this account" facts** (the date an account joined, its country, former usernames, the date it was verified), and no
  business e-mail, phone or address of Instagram's contact button: a logged out reader does not get them. The bio, bio links,
  recent captions and the linked Facebook Page's public contact are read instead.
- **No highlight count, IGTV count, IGTV videos, "joined recently" or broadcast channel flag.** The only page that served them to a
  logged out reader stopped answering on 2026-11-04; the first page of highlight titles is on every row.
- **No age restricted accounts.** Accounts Instagram restricts by age (alcohol brands, for example) are not shown to a logged out
  reader: they get the free "not found or not shown" outcome.
- **No keyword, hashtag, place or commenter search for accounts.** This Actor reads the accounts you name (and, if you ask, the
  accounts Instagram suggests next to them); finding accounts by keyword is the Instagram User Search Scraper's job.
- **No posts, reels or comments as rows of their own**, beyond the 6 or 12 newest posts and the reel figures on each row.
- **No monitoring across runs.** There is no memory of earlier runs, no change since the last run, no "new only" mode and no
  follower tracking; schedule runs and compare them in your own sheet, or filter an earlier run again with `refilterDatasetId`.
- **No e-mail verification and no pages outside Meta.** The website a bio links to is not opened, and no e-mail address is checked
  against its mail server.
- **No logins, cookies or accounts of yours.**

### FAQ

#### Can I get an Instagram follower count without logging in?

Yes. The Actor reads each account's public profile without an account, cookies or login and gives the exact follower and following
counts Instagram serves, as numbers you can sort and filter.

#### How do I get the number of posts of an Instagram account?

Every row carries `postsCount`, the exact post count from the profile's own embed page. A private account shows no post count to a
logged out reader, so its `postsCount` is empty.

#### Can I look up an Instagram profile by its user id?

Yes. Put the numeric user id in the list like a username (for example `528817151`); the Actor reads the account by its id and
delivers it under its current username. An id and a username of the same account are delivered once.

#### Does it work for private accounts?

A private account's row carries what Instagram shows to anyone: its name, bio, exact followers and following, verified and account
type, but no posts. It is charged as a Profile; turn **Include private accounts** off to leave private accounts out for free.

#### How do I track follower growth over time?

Schedule the same list (daily or weekly) and compare `followerCount` between runs in your sheet or database; each run is a fresh,
complete read. The Actor keeps no memory between runs.

#### Why does this Actor run with limited permissions?

It needs no more: it reads Instagram's and Meta's public pages and writes only to its own run's dataset and key-value store, so it
cannot touch anything else in your Apify account. Filtering an earlier run again reads that run's dataset, in your own account, by
its id.

### More data tools by Automation Craft

- [Instagram User Search Scraper: Profiles by Keyword](https://apify.com/automation_craft/instagram-user-search-scraper)
- [Instagram Posts Scraper: Profiles, Reels, No Login](https://apify.com/automation_craft/instagram-posts-scraper)
- [Instagram Search Scraper: Reels, Users, Hashtags](https://apify.com/automation_craft/instagram-search-scraper)
- [Instagram Reels Search Scraper: Reels by Keyword](https://apify.com/automation_craft/instagram-reels-search-scraper)
- [Threads Profile Scraper: Followers, Bio, Posts](https://apify.com/automation_craft/threads-profile-scraper)
- [Facebook Page ID Finder: Names to Page IDs](https://apify.com/automation_craft/facebook-page-id-finder)
- [Meta Branded Content Scraper: Paid Partnerships](https://apify.com/automation_craft/meta-branded-content-scraper)

### Changelog

See the Changelog tab: 0.1 (2026-11-04) is the first release.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation_craft/instagram-profile-scraper/changelog.md

# Actor input Schema

## `usernames` (type: `array`):

Instagram accounts to read (up to 5,000): usernames, @handles, profile links (instagram.com/<username>/) or numeric user ids. Each account gives one profile row. An account Instagram does not show to a logged out reader (not found, renamed, deleted) is free, and its position in this list is named on the account list row.

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

Stops the run once this many profiles were delivered (accounts are read in the order given). Empty means every account in the list.

## `includeRecentPosts` (type: `boolean`):

Adds the account's 6 newest posts (link, date, likes, comments, caption, pinned, paid partnership, place) to its row. Engagement figures are computed from them either way.

## `includeLatestPosts` (type: `boolean`):

Adds the account's 12 newest posts as its grid shows them, pinned posts first (latestPosts): link, type, reel flag, date, caption, likes, comments, picture, place, paid partnership and carousel size. Up to 13 more reads per account (the grid, and one read per post the 6 newest do not cover), no extra charge.

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

With includeLatestPosts: keeps only the latest posts posted on or after this day, as a date (2026-10-01, read as 00:00 UTC) or a number of days back from the run's start ("30 days"). Empty keeps all 12.

## `includeReelStats` (type: `boolean`):

Reads the account's 12 newest reels: median, average and highest play count and the newest reel's date (reelStats). One more read per account, no extra charge.

## `includeRelatedProfiles` (type: `boolean`):

Adds the accounts Instagram suggests next to each profile (relatedProfiles; often none logged out). These name other accounts, so they need includePersonalData. One more read per account, no extra charge.

## `includeFacebookPageContact` (type: `boolean`):

Reads the public contact of the Facebook Page the account links: the Page Instagram links to it, else the one Page Meta's Ad Library search (by the username, then the name) names with this account as its Instagram account. E-mail, phone, WhatsApp, website, address, hours. Charged as one Facebook Page contact only when the Page shows an e-mail, a phone or WhatsApp number, a website, an address or its hours; no Page, no exact match or none of those is free.

## `expandWithRelatedProfiles` (type: `boolean`):

Also delivers the accounts Instagram suggests next to the profiles of your list, each as a profile row of its own (charged as a Profile), marked with the profile it was suggested next to (relatedTo). Logged out, Instagram suggests accounts for about a third of the profiles. One more read per profile.

## `expansionDepth` (type: `integer`):

With expandWithRelatedProfiles: 1 adds the accounts suggested next to your list, 2 also those suggested next to them, and so on up to 10. maxRelatedProfiles caps the accounts added in all.

## `maxRelatedProfiles` (type: `integer`):

With expandWithRelatedProfiles: stops the expansion once this many suggested accounts were delivered (default 50).

## `maxRelatedPerAccount` (type: `integer`):

With expandWithRelatedProfiles: takes at most this many of the accounts Instagram suggests next to each profile, in Instagram's order, at every level (default 50, all of them; Instagram suggests at most 50).

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

Leave out accounts with fewer followers.

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

Leave out accounts with more followers.

## `minPosts` (type: `integer`):

Leave out accounts with fewer posts (private accounts show no post count and are left out by this filter).

## `maxPosts` (type: `integer`):

Leave out accounts with more posts.

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

Any account (default), verified accounts only, or unverified accounts only.

## `accountTypes` (type: `array`):

Keep only these account types (empty keeps every type). Professional means business or creator.

## `influencersOnly` (type: `boolean`):

Keep only creator accounts and accounts whose category is one of a list of people who publish for an audience (Digital creator, Video creator, Blogger, Public figure, Artist, Musician, Athlete, model, Writer, Photographer, Gamer, Chef, Coach and more; README "Filters").

## `includePrivate` (type: `boolean`):

Private accounts show their name, bio and counts but no posts. Off leaves them out (free).

## `onlyPrivate` (type: `boolean`):

Keep only private accounts (their header and counts); public accounts are left out free.

## `mustContain` (type: `array`):

Keep only accounts that hold at least one of these words or phrases (whole words, any case; a word of four letters or more also counts inside the username) in the part mustContainIn names.

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

Where mustContain looks: the username, name and bio (default), the bio only, the username and name only, the captions of the 6 recent posts, or anywhere.

## `excludeWords` (type: `array`):

Leave out accounts whose username, name or bio holds any of these words or phrases.

## `categories` (type: `array`):

Keep only accounts whose Instagram category holds one of these words ("photographer", "coffee shop"). Accounts without a category are left out.

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

When both categories and mustContain are set: an account must pass both (default), or either one.

## `languages` (type: `array`):

Keep only accounts whose bio and recent captions read as one of these languages (two letter codes such as en, es, de; our own estimate, accounts we cannot tell are left out).

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

Keep only accounts that show this contact in their bio, bio links or recent captions: any account (default), an e-mail or a phone, an e-mail, a phone, or both. The addresses and numbers themselves are delivered with includePersonalData.

## `requireWebsite` (type: `boolean`):

Keep only accounts with a website or another link in their bio.

## `minEngagementRate` (type: `number`):

Keep only accounts whose engagement rate (average likes and comments of their 6 newest posts over followers, in percent) is at least this. Accounts without visible likes are left out.

## `activeWithinDays` (type: `integer`):

Keep only accounts whose newest post (pinned posts aside) is at most this many days old.

## `minRecentPosts` (type: `integer`):

Keep only accounts with at least this many of their 6 newest posts inside the last recentPostsDays days (1 to 6).

## `recentPostsDays` (type: `integer`):

The period minRecentPosts counts in, in days back from the run's start (default 30).

## `minMedianReelPlays` (type: `integer`):

Keep only accounts whose 12 newest reels have at least this median play count. Needs includeReelStats.

## `reelPostedWithinDays` (type: `integer`):

Keep only accounts whose newest reel is at most this many days old. Needs includeReelStats.

## `minPlaysToFollowersPercent` (type: `number`):

Keep only accounts whose median reel play count is at least this percent of their followers. Needs includeReelStats.

## `maxPlaysToFollowersPercent` (type: `number`):

Leave out accounts whose median reel play count is above this percent of their followers (one viral reel). Needs includeReelStats.

## `excludeUsernames` (type: `array`):

Accounts never to deliver (usernames, @handles, profile links or ids), for example accounts an earlier run already gave you (up to 10,000). They are left out free.

## `includeLeftOutAccounts` (type: `boolean`):

Adds a free row for every account read and left out (its username and the reason: a filter, not shown logged out, already delivered), so you see why an account is missing.

## `minMatchRatePercent` (type: `integer`):

Stops the run when, after 100 accounts were judged, fewer than this percent of them passed your filters (a list that does not fit the filters). Empty never stops.

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

The dataset id of an earlier run of this Actor: its profile rows are judged again by this run's filters and the ones that pass are delivered without reading Instagram (charged as a Re-filtered profile). Can run alone or beside usernames.

## `includePersonalData` (type: `boolean`):

Off (default): fields that name or reach a person are empty: emails and phones (from the bio, bio links, captions), relatedProfiles, bioMentions, collaborators of the latest posts, Instagram's redirect link, and Meta profile links and contact links (any app link such as mailto, tel, sms, callto, tg; messaging services such as Telegram, Signal, Viber, Skype) in the website and bio links. On: filled. Bios and captions are delivered as served. You answer for a lawful use, GDPR included.

## `maxConcurrency` (type: `integer`):

How many accounts are read in parallel (1 to 4, default 4). Fewer is slower and gentler.

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

Stops the run after this many seconds; the account list row names the accounts not reached. Empty means the platform timeout.

## `requestTimeoutSecs` (type: `integer`):

How long one request may take before it is retried.

## `maxRetries` (type: `integer`):

How often a failed request is retried on a fresh connection.

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

Default: Apify Proxy without a group or country, which reads from the run's own address first and moves a request type to Apify's datacenter proxy when it is refused there. Choose a group or a country to read only through Apify Proxy, or give your own proxy links. A residential group is read through the datacenter pool instead (no extra cost).

## Actor input object example

```json
{
  "usernames": [
    "nasa",
    "natgeo",
    "nike"
  ],
  "includeRecentPosts": true,
  "includeLatestPosts": false,
  "includeReelStats": false,
  "includeRelatedProfiles": false,
  "includeFacebookPageContact": false,
  "expandWithRelatedProfiles": false,
  "verified": "any",
  "influencersOnly": false,
  "includePrivate": true,
  "onlyPrivate": false,
  "mustContainIn": "bio_or_name",
  "combineCategoryAndWords": "and",
  "contactFilter": "any",
  "requireWebsite": false,
  "recentPostsDays": 30,
  "includeLeftOutAccounts": false,
  "includePersonalData": false,
  "maxConcurrency": 4,
  "requestTimeoutSecs": 30,
  "maxRetries": 2,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `items` (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 = {
    "usernames": [
        "nasa",
        "natgeo",
        "nike"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/instagram-profile-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 = {
    "usernames": [
        "nasa",
        "natgeo",
        "nike",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/instagram-profile-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 '{
  "usernames": [
    "nasa",
    "natgeo",
    "nike"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call automation_craft/instagram-profile-scraper --silent --output-dataset

```

## MCP server setup

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