# Instagram Profile Email & Phone Scraper (`khadinakbar/instagram-profile-scraper`) Actor

Extract public emails and phone numbers from Instagram profiles by username or URL. Each row adds bio, followers, following, business category, website, bio links, verification and recent posts. Optional email domain check and account age estimate. Unknown usernames are not charged. No login needed.

- **URL**: https://apify.com/khadinakbar/instagram-profile-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Social media, Lead generation, MCP servers
- **Features:** Limited permissions
- **Stats:** 185 total users, 42 monthly users, 98.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 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.

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

### What is Instagram Profile Email & Phone Scraper?

Instagram Profile Email & Phone Scraper turns Instagram usernames or profile URLs into one clean row per profile, with the public email and phone the account publishes on its contact button or in its bio. Each row also has the display name, bio, follower and following counts, verification, business flag and category, external link, bio links and profile picture, plus `hasEmail`, `hasPhone` and `contactSource` so you can filter outreach-ready accounts at a glance. It also includes up to 12 recent posts with caption, comment count, media type and date. Brand teams, influencer marketers, researchers and AI agents use it to size up and enrich Instagram accounts in bulk, with no Instagram login.

| You give | You get | Price |
|---|---|---|
| Usernames, @handles or profile URLs | One row per profile: public email and phone with their source, bio, followers, category, links, up to 12 recent posts | $4 per 1,000 profiles (`profile-scraped`), Apify platform usage included; unknown usernames are free |

### Why marketers use it for profile research

- **The numbers that matter first.** `followersCount`, `followingCount` and `isVerified` sit at the top of every row for quick ranking.
- **Contacts when they are public.** `email` and `phone` come from the contact button or the bio when the account publishes them; `contactSource` says which. Turn on `onlyWithContact` to save (and pay for) only profiles that list one.
- **Recent activity at a glance.** `recentPosts` shows up to 12 latest posts with caption, comments, date and media type.
- **Handles or URLs, deduplicated.** Paste `natgeo`, `@nasa` or a full profile URL; repeats are skipped.
- **Pay only for real profiles.** Unknown usernames are listed in the run summary and are free.

### How to use it

**Look up a list of creators with their recent posts:**

```json
{
  "usernames": ["natgeo", "@nasa", "https://www.instagram.com/humansofny/"],
  "scrapeRecentPosts": true,
  "maxRecentPosts": 12
}
```

**Profile details only, smallest rows:**

```json
{
  "usernames": ["nike", "adidas", "puma"],
  "scrapeRecentPosts": false
}
```

| Input | What it controls |
|---|---|
| `usernames` | Instagram usernames, @handles or profile URLs. Required. |
| `onlyWithContact` | Save only profiles with a public email or phone; others are skipped free (default off) |
| `includeAccountAge` | Add the estimated month and year the account was created, its age in years and a confidence level (default off, no extra charge) |
| `verifyEmails` | Add `emailCheck` to each profile with a public email: `mx_ok` (the domain accepts mail), `no_mail_server`, `invalid_format` or `unknown`. It shows the domain can receive email, not that the mailbox exists (default off, no extra charge) |
| `scrapeRecentPosts` | Add the profile's latest posts (default on) |
| `maxRecentPosts` | Posts per profile, up to 12 (default 12) |
| `proxyConfiguration` | Apify Proxy settings; Residential by default |

Need more than 12 posts per account? Continue with **Instagram Posts Scraper** linked below.

### Output: Instagram profile data you receive

A real row for a public creator account (email partly redacted, `recentPosts` shortened to one post, image URLs left out):

```json
{
  "username": "humansofny",
  "fullName": "Humans of New York",
  "userId": "242598499",
  "biography": "New York City, one story at a time.\nCreated by Brandon Stanton\nInquiries/Collabs: h***@gmail.com",
  "followersCount": 12654423,
  "followingCount": 755,
  "isVerified": true,
  "isPrivate": false,
  "isBusinessAccount": false,
  "email": "h***@gmail.com",
  "hasEmail": true,
  "hasPhone": false,
  "contactSource": "bio",
  "externalUrl": "https://bit.ly/dearnewyorkbook",
  "bioLinks": ["https://bit.ly/dearnewyorkbook"],
  "igtvVideoCount": 1,
  "recentPosts": [
    {
      "postId": "3741054891297971261",
      "shortCode": "DPq5ZpJDZw9",
      "postUrl": "https://www.instagram.com/p/DPq5ZpJDZw9/",
      "caption": "Dear New York closes on October 19th. ...",
      "commentCount": 974,
      "isVideo": true,
      "postedAt": "2025-10-11T13:27:07.000Z"
    }
  ],
  "profileUrl": "https://www.instagram.com/humansofny/"
}
```

| Field | What it contains |
|---|---|
| `username`, `fullName`, `userId`, `biography`, `profileUrl` | Who the account is |
| `followersCount`, `followingCount` | Audience size |
| `isVerified`, `isPrivate`, `isBusinessAccount` | Account status flags |
| `email`, `phone` | Public contact details, included when the account publishes them |
| `hasEmail`, `hasPhone`, `contactSource` | Quick contact flags and where the contact came from (`contact_button` or `bio`) |
| `businessCategory` | The account's public category, when shown |
| `externalUrl`, `bioLinks` | The website and links in the bio |
| `recentPosts` | Up to 12 latest posts with URL, caption, comment count, media type and date |
| `postsCount` | Total posts when Instagram's public data reports it, mostly for smaller accounts |
| `profilePicUrl`, `profilePicUrlHd` | Profile picture links |

Fields without a value are left out of the row. `OUTPUT` in the default key-value store reports the run `outcome` and lists any usernames that were not found.

### Example workflow: shortlisting creators for a campaign

An outdoor brand has 50 creator handles from a hashtag search. They run them with `maxRecentPosts` set to 6, sort by `followersCount`, and read `recentPosts` to confirm each creator posted in the last month. They keep creators whose `email` is filled for direct outreach. Then they pass the rest to [Instagram Contact Scraper](https://apify.com/khadinakbar/instagram-contact-scraper) to look for a contact in the bio and contact button.

### Pricing

This Actor uses **Pay per event**. Apify platform usage is included in the event price, so you pay one `profile-scraped` event per profile saved ($4 per 1,000 profiles) plus one start event per run. Unknown usernames and profiles skipped by `onlyWithContact` are free. See the Pricing tab for current rates.

- 50 profiles = 50 profile events (about $0.20) + 1 start event.
- Recent posts come at no extra charge.
- The size of your `usernames` list sets the ceiling for each run.

#### Free Apify plan

Runs started from a free Apify plan return up to 25 results per run, with every input mode and output field available. Paid Apify plans have no per-run limit, so your usual result settings apply.

### Profile research with AI agents (MCP)

Connect this Actor to an AI agent through [Apify MCP](https://mcp.apify.com) and ask in plain language:

> Look up these 10 Instagram accounts and keep only those with a public email or phone. Rank them by followers and give me each one's email, phone, category, website and the date of its latest post.

Agent checklist:

1. Pass handles or URLs in `usernames`.
2. Set `scrapeRecentPosts: false` when only profile numbers matter, to keep rows short.
3. Read rows with `get-dataset-items`; read `OUTPUT` for usernames that were not found.
4. Use `profileUrl` as the stable ID when joining with other data.

### API example

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~instagram-profile-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"usernames": ["natgeo", "nasa"], "scrapeRecentPosts": false}'
```

### Related Instagram tools from the same developer

| Your next step | Use | Why |
|---|---|---|
| When you still need to find accounts by keyword | [Instagram User Search Scraper](https://apify.com/khadinakbar/instagram-user-search-scraper) | Profiles for any niche or keyword |
| When you want more than 12 posts per account | [Instagram Posts Scraper](https://apify.com/khadinakbar/instagram-posts-scraper) | Full post lists by profile, hashtag or URL |
| When you then want contact details | [Instagram Contact Scraper](https://apify.com/khadinakbar/instagram-contact-scraper) | Emails and phones from bio and contact button |
| When you want to check audience quality | [Instagram Fake Follower Auditor](https://apify.com/khadinakbar/instagram-fake-follower-auditor) | Audience-quality score per profile |
| When you want to know how old an account is | [Instagram Account Age Checker](https://apify.com/khadinakbar/instagram-account-age-checker) | Estimated creation date per account |

### Best results

| Starting situation | Helpful action | Expected outcome |
|---|---|---|
| Ranking a long list of accounts | Turn off `scrapeRecentPosts` | Shorter rows with all the profile numbers |
| Checking how active an account is | Keep `maxRecentPosts` at 6 to 12 | Recent captions and dates |
| Mixed handles and URLs | Paste them as they are | One row per account, duplicates skipped |
| Needing the full post history | Use Instagram Posts Scraper | Every post, beyond the latest 12 |

### Builder's note

I found that most people want a quick read on an account before deciding anything else, so each row starts with followers, verification and the website, followed by the latest posts. I learned that Instagram's public profile data reports a reliable total post count mainly for smaller accounts, so the Actor includes `postsCount` only when that number is the true total.

### FAQ

#### Do I need an Instagram account?

No. The Actor reads public profile data and needs no login or cookies.

#### Why is postsCount missing for some accounts?

Instagram's public profile data reports the total post count mainly for smaller accounts. For larger ones the Actor leaves the field out so every number you get is the real one.

#### Can I get the account's age?

Yes. Set `includeAccountAge` to true and each profile also gets `estimatedCreatedAt`, `estimatedCreatedYear`, `estimatedCreatedMonth`, `estimatedAccountAgeYears`, `accountAgeConfidence` and `accountAgeMethod`. Instagram does not publish a creation date, so this is an estimate worked out from the numeric ID Instagram gives every new account. It is usually right to within a few months (checked against Instagram's own join dates, the estimate was exact to the month for two of three accounts and three months off for the third). Treat it as an age band, not an official date. There is no extra charge. Instagram's registration country is not available and is not returned.

#### Can it check that an email is real?

Partly. Set `verifyEmails` to true and every profile with a public email gets `emailCheck`: `mx_ok` when the email's domain has a mail server, `no_mail_server` when it does not, `invalid_format` for a malformed address and `unknown` when the lookup timed out. This catches dead domains and typos before you send. It cannot prove that one specific mailbox exists.

#### Does it return emails?

When an account publishes an email or phone on its contact button or in its bio, it appears in `email` and `phone`.

#### Can I keep only accounts with an email or phone?

Yes. Set `onlyWithContact` to true. Profiles without a public email or phone are skipped and not charged.

#### What happens with an unknown username?

It is listed in `OUTPUT.notFound` and is free.

#### Can I get more than 12 posts?

Each profile row carries up to 12 recent posts. For complete post lists, use Instagram Posts Scraper.

### Responsible use

This Actor collects public Instagram profile data, which can include personal data protected by laws such as the GDPR and CCPA. Use it only with a lawful basis, honor opt-outs, and respect Instagram's terms. Read Apify's guide on [whether web scraping is legal](https://blog.apify.com/is-web-scraping-legal/) for more context. Instagram is a trademark of Meta Platforms, Inc. This independent Actor is not affiliated with, associated with, or endorsed by Instagram or Meta. For questions or bugs, open a ticket in the Issues tab.

# Changelog

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

# Actor input Schema

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

One or more Instagram accounts to scrape. Accepts bare usernames ('natgeo'), @-handles ('@nasa'), or full profile URLs ('https://instagram.com/nike'). Returns one record per profile; private accounts return metadata only (no posts). NOT for hashtags or post URLs — use a hashtag/post scraper for those. Free Apify plan runs return up to 25 results per run.

## `onlyWithContact` (type: `boolean`):

Enable this to save only profiles that show a public email or phone (from the contact button or the bio). The default is off. Profiles without one are skipped and not charged.

## `includeAccountAge` (type: `boolean`):

Adds the estimated month and year the account was created, its age in years, and how reliable the estimate is. The estimate comes from the numeric ID Instagram assigned when the account was created, so it is usually right to within a few months and is not an official date. Included in the normal profile price. The default is off.

## `scrapeRecentPosts` (type: `boolean`):

Whether to include the profile's most recent posts (up to 12) in each record, with caption, like and comment counts, media type, thumbnail, and timestamp. Defaults to true. Set to false for lighter, profile-only records when you only need follower and contact data.

## `maxRecentPosts` (type: `integer`):

Maximum recent posts to include per profile. Instagram's public profile endpoint returns at most 12 per request, so larger values are automatically capped at 12 (no error). Set 0, or turn off 'Include recent posts', for none. Defaults to 12.

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

Proxy settings used to reach Instagram. Residential proxies are strongly recommended — Instagram blocks datacenter IPs. Defaults to Apify Proxy with the RESIDENTIAL group. Leave as default unless you have a specific proxy requirement.

## `verifyEmails` (type: `boolean`):

Adds an emailCheck field to every profile that has a public email: mx_ok (the domain accepts mail), no_mail_server, invalid_format or unknown. It proves the domain can receive email, not that the mailbox exists. Included in the normal profile price. The default is off.

## Actor input object example

```json
{
  "usernames": [
    "nasa",
    "https://www.instagram.com/nike/"
  ],
  "onlyWithContact": false,
  "includeAccountAge": false,
  "scrapeRecentPosts": true,
  "maxRecentPosts": 12,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "verifyEmails": false
}
```

# Actor output Schema

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

Array of profile objects with metrics, contact data, and recent posts.

# 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": [
        "humansofny",
        "natgeo"
    ],
    "maxRecentPosts": 12,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/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": [
        "humansofny",
        "natgeo",
    ],
    "maxRecentPosts": 12,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

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

```

## MCP server setup

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