# Instagram Profile Scraper - Followers, Posts & Emails (`eiv/instagram-profile-scraper`) Actor

Scrape Instagram profiles by username, URL or ID: exact followers, following and post counts, bio, links, emails and phones from the bio, category, verified and business flags, engagement rate, 12 latest posts and related profiles. No login or cookies.

- **URL**: https://apify.com/eiv/instagram-profile-scraper.md
- **Developed by:** [Eimantas V](https://apify.com/eiv) (community)
- **Features:** Limited permissions
- **Stats:** 120 total users, 68 monthly users, 83.8% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 1,000 profile scrapeds

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** extracts public profile data from **Instagram**: exact follower, following and post counts, bio, website and bio links, emails and phone numbers found in the bio, verified, private and business flags, engagement rate, and the latest posts and Reels. Paste usernames, @handles, profile URLs or numeric user IDs and get one row per profile. No login, no cookies, no browser, from **$1.60 per 1,000 profiles**.

```json
{
  "username": "nasa",
  "fullName": "NASA",
  "followersCount": 104437877,
  "followsCount": 90,
  "postsCount": 4990,
  "isVerified": true,
  "accountType": "business",
  "externalUrl": "https://www.nasa.gov",
  "engagementRate": 0.215,
  "avgLikes": 223563,
  "postsPerWeek": 6.36,
  "latestPostAt": "2026-11-05T02:25:45.000Z"
}
```

**Measured on Apify (2026-11-05): 30 celebrity, creator and brand profiles in 19 seconds, every existing one returned in full.**

### What does Instagram Profile Scraper do?

It reads the same public profile data Instagram shows a visitor who is not logged in, for as many profiles as you list, and returns it as clean rows you can download as JSON, CSV or Excel. It adds what Instagram does not show directly: engagement rate, average likes, comments and Reel views, posting frequency, and the email addresses and phone numbers written in the bio.

- **Every input form.** Usernames (`natgeo`), @handles, profile URLs with any tracking parameters (`instagram.com/natgeo?igsh=...`), `/reels/` and story links, and numeric user IDs. Duplicates are scraped and charged once.
- **Exact counts.** Followers, following and posts as exact numbers, not "104M".
- **Leads and contacts.** Emails and international phone numbers from the bio and link titles, WhatsApp numbers from wa.me links, the website and all bio links (the real URLs, not Instagram's redirects).
- **Influencer metrics.** Engagement rate, average likes, comments and Reel views, posts per week and the date of the latest post, so inactive or inflated accounts stand out.
- **Latest posts and Reels.** The 6 latest posts on the grid and the 12 latest Reels, with caption, likes, comments, plays, date, hashtags, mentions, collaborators and media URLs.
- **Only pay for results.** Usernames that do not exist and profiles that cannot be read return an error row and are never charged.
- **Built for automation.** Run it on a schedule, call it from the API, or connect it to Make, Zapier, n8n, Google Sheets or an AI agent through Apify's MCP server.

### How it works

There is no browser and no login. For each profile the Actor reads Instagram's public profile page (bio, links, exact counts) through residential addresses, because Instagram shows that page only to home connections, and it reads the post count, the latest posts and the Reels from Instagram's own embed and app endpoints. Addresses are managed for you: there is no proxy to set up, and ten profiles are scraped at a time.

### What data can you extract from Instagram?

| Field | Example | What it is |
|---|---|---|
| `username`, `fullName`, `id` | `nasa`, `NASA`, `528817151` | Handle, display name and the permanent user ID |
| `followersCount`, `followsCount`, `postsCount` | `104437877`, `90`, `4990` | Exact counts |
| `biography` | `Making the seemingly impossible, possible.` | The bio text |
| `externalUrl`, `externalUrls` | `https://www.nasa.gov` | Main link and all bio links with their titles |
| `emails`, `phones` | `["hello@brand.com"]` | Found in the bio, link titles and WhatsApp links |
| `isVerified`, `isPrivate` | `true`, `false` | Blue badge, private account |
| `accountType` | `business` | Business, creator or personal |
| `engagementRate` | `0.215` | (Average likes + comments) / followers x 100 |
| `avgLikes`, `avgComments`, `avgVideoViews` | `223563`, `894`, `3856066` | Averages over the latest posts and Reels |
| `postsPerWeek`, `latestPostAt` | `6.36`, `2026-11-05T02:25:45Z` | Posting frequency and activity |
| `hasClips`, `hasThreadsProfile`, `fbid` | `true`, `true`, `17841401474538262` | Reels, Threads profile, Meta-wide account ID |
| `latestPosts` | up to 18 posts | Caption, likes, comments, plays, date, type, media URLs, hashtags, mentions, owner and collaborators |
| `profilePicUrl` | URL | Profile picture |
| `dataLevel` | `full` | `partial` for the rows described under Tips and limits |

The dataset has four views: **Overview**, **Contacts and leads**, **Engagement**, and **Latest posts** (one row per post).

### How to scrape Instagram profiles

1. Click **Try for free** and paste your usernames, @handles, profile URLs or user IDs into **Instagram profiles**, one per line.
2. Keep **Include the latest posts and Reels** on for the full picture, or turn it off for smaller rows.
3. Click **Start**.
4. Open the **Output** tab, or download the results as JSON, CSV, Excel or HTML.

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

You pay per profile returned, and the price drops on higher Apify plans:

| Apify plan | Per 1,000 profiles |
|---|---|
| Free | $2.50 |
| Starter | $2.00 |
| Scale | $1.80 |
| Business | $1.60 |

- 500 influencer profiles on the Starter plan cost **$1.00**.
- A run also costs **$0.00005** to start. Profiles that fail or do not exist cost nothing, and neither do partial rows.
- The Free plan's $5 monthly credit covers about **2,000 profiles**.

### Input

```json
{
    "targets": ["nasa", "@humansofny", "https://www.instagram.com/natgeo/", "787132"],
    "includeLatestPosts": true
}
```

| Field | Default | Notes |
|---|---|---|
| Instagram profiles | `nasa`, `humansofny` (example) | Usernames, @handles, profile URLs or numeric user IDs, one per line |
| Profile URLs (for chaining Actors) | empty | The same in the URL-list shape other Actors output |
| Max profiles | 10,000 | Total for the run: your cost cap |
| Include the latest posts and Reels | on | Free; off makes rows smaller |
| Concurrency, timeout, retries | 10, 30 s, 2 | Tuned already; IP addresses are managed for you |

### Output

Each profile is one row in the dataset (shortened here; the full row has every field in the table above):

```json
{
  "recordType": "profile",
  "input": "nasa",
  "id": "528817151",
  "username": "nasa",
  "url": "https://www.instagram.com/nasa/",
  "fullName": "NASA",
  "biography": "Making the seemingly impossible, possible. ✨",
  "followersCount": 104437877,
  "followsCount": 90,
  "postsCount": 4990,
  "isVerified": true,
  "isPrivate": false,
  "accountType": "business",
  "isBusinessAccount": true,
  "isProfessionalAccount": true,
  "emails": [],
  "phones": [],
  "externalUrl": "https://www.nasa.gov",
  "externalUrls": [
    { "title": "NASA.gov Homepage", "url": "https://www.nasa.gov", "linkType": "external" }
  ],
  "latestPostAt": "2026-11-05T02:25:45.000Z",
  "avgLikes": 223563,
  "avgComments": 894,
  "avgVideoViews": 3856066,
  "engagementRate": 0.215,
  "postsPerWeek": 6.36,
  "hasClips": true,
  "hasThreadsProfile": true,
  "fbid": "17841401474538262",
  "latestPosts": [
    {
      "shortCode": "DfF3eqGSKKc",
      "url": "https://www.instagram.com/p/DfF3eqGSKKc/",
      "type": "Video",
      "productType": "clips",
      "caption": "More power loading. 🔋 Today, NASA astronaut Anil Menon and…",
      "likesCount": 15099,
      "commentsCount": 161,
      "videoPlayCount": 2589611,
      "timestamp": "2026-10-29T20:35:35.000Z",
      "ownerUsername": "nasajohnson",
      "coauthors": ["iss", "nasa"]
    }
  ],
  "dataLevel": "full",
  "scrapedAt": "2026-11-05T06:39:31.834Z"
}
```

A profile that cannot be read becomes a row with `"recordType": "error"` and an `errorCode` instead of failing the whole run:

| `errorCode` | Meaning |
|---|---|
| `NOT_FOUND` | No such username or ID, or the account is deactivated, banned or restricted |
| `BLOCKED` / `RATE_LIMITED` | Instagram refused every address for this profile; run it again later |
| `PARSE_FAILED` | Instagram answered in an unexpected shape; please report it |

Error rows are never charged.

### Tips and limits

- **What Instagram no longer shows.** Since November 2026 Instagram no longer gives logged-out visitors a profile's category, story highlight count, long-video count or suggested accounts. No scraper without a login can get them now; those fields (`category`, `businessCategoryName`, `highlightReelCount`, `igtvVideoCount`, `relatedProfiles` and a few flags) stay in the rows, empty, so your integrations keep working.
- **Partial rows are free.** When Instagram refuses every address for a profile's public page, the row still comes with exact followers and posts, the account type, the latest posts and Reels and the engagement figures, but without bio, links, following count, emails and phones. It is marked `"dataLevel": "partial"` and is not charged. Run those profiles again later for the rest.
- **Latest posts are the grid's newest 6 plus the 12 newest Reels.** Collab posts owned by another account are included and name their owner. Posts per week is measured on the grid.
- **Contact buttons stay hidden.** Instagram does not show the address behind a business's Email, Call or Directions button to logged-out visitors, so `emails` and `phones` come from the bio, link titles and WhatsApp links only.
- **Private accounts** return their public header (name, bio, counts, links) but no posts, because Instagram hides them.
- **User IDs** are turned into usernames through the account's public Reels. An ID whose account has no public Reels returns `NOT_FOUND`: use the username instead.
- **"About this account"** (join date, country, former usernames) needs a logged-in session, so it is not included.
- **Media URLs expire** after a few days; download pictures and videos you want to keep.
- **For more posts per profile**, use a dedicated posts scraper.
- **Hit your spending limit?** The run stops cleanly at your maximum cost per run and keeps everything it collected. Raise the limit in the run options to get more.
- **Very long lists may stop early.** If Instagram refuses most requests, the run stops with everything it collected (saved and charged). Run the rest again later, or split the list across smaller runs.
- **Memory is fixed at 512 MB**, all the Actor needs. If you saved another memory setting for it, clear it, or the run will not start.

### FAQ

#### Is it legal to scrape Instagram?

This Actor collects only data that Instagram shows publicly, without logging in. Results can still contain personal data, which laws such as the GDPR protect. Scrape personal data only for a legitimate purpose, and ask a lawyer if you are unsure. Instagram is a trademark of its owner; this Actor is not affiliated with or endorsed by Instagram or Meta.

#### Can I use it through the API or with Make, Zapier and n8n?

Yes. Every run can be started through the [Apify API](https://docs.apify.com/api/v2) and returns the dataset as JSON, CSV or Excel. Schedules, webhooks and integrations for Make, Zapier, n8n and Google Sheets are on the **Integrations** tab.

#### Can AI agents use it?

Yes. Agents connected to [Apify's MCP server](https://mcp.apify.com) can find and run this Actor as a tool, with the same per-profile pricing. Give it a list of usernames and read back follower counts, bios and engagement.

#### How is the engagement rate calculated?

Average likes plus average comments over the latest posts and Reels, divided by followers, times 100. Pinned posts are left out when at least three others remain, because they are old favourites that stay on top. Accounts that hide their likes get no rate rather than a misleading one. Around 1-3 % is typical; well under 0.5 % on a large account often means inactive or bought followers.

#### Why did I get fewer results than I asked for?

Some usernames do not exist or are restricted (they return error rows), the run reached your maximum cost per run or its timeout, or Instagram refused so many requests that the run stopped early. The log says which, and nothing collected before that is lost.

### Related scrapers

- [TikTok Creator & Profile Scraper](https://apify.com/eiv/tiktok-creator-scraper): the same creator vetting for TikTok, with exact follower and like counts.
- [Threads Scraper - Posts, Likes & Replies by Profile](https://apify.com/eiv/threads-profile-scraper): the posts of the same accounts on Threads.
- [YouTube Channel & Video Scraper](https://apify.com/eiv/youtube-channel-scraper): subscriber counts and uploads for creators who are also on YouTube.
- [Website Tech Stack & Lead Enrichment Scraper](https://apify.com/eiv/website-intelligence-scraper): emails, phones and socials from the websites in the bios.

### Support

Missing a field, or found a profile that does not work? Open an issue on the **Issues** tab with the input you used, and it will be looked at quickly.

# Actor input Schema

## `targets` (type: `array`):

One profile per line, in any form: username (natgeo), @handle, profile URL (https://www.instagram.com/natgeo/) or numeric user ID (787132). Duplicates are scraped and charged once.

## `startUrls` (type: `array`):

The same profiles in the URL-list shape other Actors output (for example the authors found by a post or hashtag scraper), so their results can be fed straight in. Use this or the field above.

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

Stop after this many profiles in total. You pay per profile, so this is also your cost cap for the run.

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

Adds each profile's 6 latest grid posts and 12 latest Reels (caption, likes, comments, plays, date, media URLs, hashtags, mentions, collaborators). Free and costs no time; turn it off for smaller rows. Engagement rate and posts per week are computed either way.

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

How many profiles are scraped at the same time. The default is tuned for speed without tripping Instagram's rate limits.

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

How long to wait for one response from Instagram before giving up on it.

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

Retries for failed connections and server errors. Rate limits are handled separately, by switching IP address.

## Actor input object example

```json
{
  "targets": [
    "nasa",
    "humansofny"
  ],
  "maxItems": 10000,
  "includeLatestPosts": true,
  "maxConcurrency": 10,
  "requestTimeoutSecs": 30,
  "maxRetries": 2
}
```

# Actor output Schema

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

One row per profile (recordType "profile"), plus one uncharged row per target that could not be read (recordType "error").

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

The same profiles with account type, emails and phones found in the bio, website, bio links and bio text.

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

Followers, engagement rate, average likes, comments and video views, posts per week and latest post date per profile.

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

Every profile's latest posts and Reels, one row per post, with likes, comments, plays, date, owner and caption.

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

Totals for the run: profiles, failures, why it stopped, requests and which IP types answered them.

# 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 = {
    "targets": [
        "nasa",
        "humansofny"
    ]
};

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

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

```

## MCP server setup

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