# Instagram Public Contact Scraper (`automation-lab/instagram-contact-scraper`) Actor

Extract owner-published emails, phones, biography, external URL, categories, identity, and public counters from supplied Instagram profile URLs.

- **URL**: https://apify.com/automation-lab/instagram-contact-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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/platform/actors/running/actors-in-store#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 Public Contact Scraper

Extract owner-published contact details and current public profile data from supplied Instagram profile URLs.

Instagram Public Contact Scraper turns each successfully resolved public profile into one normalized dataset record. It reads public email and phone fields when Instagram returns them, scans the profile biography for owner-published contact strings, and includes identity, biography, external URL, category, account flags, and public counters.

No Instagram login or buyer cookie is required.

### What does this Instagram scraper do?

Provide one or more public Instagram profile URLs and receive structured records ready for prospect research, creator evaluation, spreadsheets, CRMs, scheduled snapshots, or data pipelines.

The Actor:

- accepts explicit public profile URLs;
- rejects post, reel, story, explore, and non-Instagram URLs;
- deduplicates usernames case-insensitively;
- extracts only public profile and biography data;
- streams one record per successful profile;
- charges only for records that are successfully saved;
- fails visibly when any requested profile cannot be resolved, while preserving successful rows.

It does not search Instagram for accounts, scrape followers, follow link-in-bio pages, access private content, or require login credentials.

### Who is it for?

**Lead generation teams** can refresh owner-published contact fields for a known list of business or creator profiles.

**Influencer and partnership teams** can combine public identity, biography, categories, counters, and contact details in one table.

**Researchers and analysts** can schedule snapshots and compare profile metadata over time.

**Developers and data engineers** can send normalized records to a database, spreadsheet, webhook, CRM, or warehouse through Apify integrations and APIs.

Use this Actor when you already know the profile URLs. Choose a discovery-focused Actor when your first job is finding profiles by keyword, hashtag, or post.

### Why use this Actor?

- **Focused output:** one stable record type for public profile contact research.
- **No buyer login:** the supported workflow does not ask for an Instagram password or session cookie.
- **Owner-published provenance:** emails and phones come from public profile fields or biography text.
- **Useful even without contact fields:** identity, biography, link, categories, flags, and counters remain available.
- **Batch-safe input:** duplicate profiles are removed and `maxProfiles` stops work in input order.
- **Explicit failure behavior:** unresolved inputs do not silently disappear and are not charged as results.
- **Cost-aware requests:** the lower-cost SHADER proxy is the tested default; residential routing remains user-selectable.

### What Instagram data is extracted?

| Field | Description |
| --- | --- |
| `instagramUserId` | Stable public Instagram user identifier |
| `username` | Current public username |
| `fullName` | Owner-published profile display name |
| `biography` | Owner-published biography |
| `emails` | Deduplicated public emails from profile fields or biography |
| `phones` | Deduplicated public phones from profile fields or biography |
| `externalUrl` | Public external link shown on the profile |
| `category` | Instagram profile category when available |
| `businessCategory` | Human-readable business category when available |
| `profileUrl` | Canonical Instagram profile URL |
| `isVerified` | Whether Instagram marks the account verified |
| `isPrivate` | Whether the profile is private |
| `isBusinessAccount` | Whether Instagram marks it as a business account |
| `isProfessionalAccount` | Whether Instagram marks it as a professional account |
| `followersCount` | Current public follower count |
| `followingCount` | Current public following count |
| `postsCount` | Current public post count |
| `profilePicUrl` | Public profile image URL |
| `scrapedAt` | UTC extraction timestamp |

Instagram does not publish every field for every profile. Optional text fields may be `null`, and contact arrays may be empty.

### How to scrape public Instagram profile contacts

1. Open the Actor input page.
2. Add complete profile URLs such as `https://www.instagram.com/nasa/`.
3. Set `maxProfiles` if only the first part of the list should run.
4. Keep the default SHADER proxy for normal batches, or choose another proxy route when needed.
5. Click **Start**.
6. Open the **Instagram contacts** dataset view.
7. Export results as JSON, CSV, Excel, XML, or another supported dataset format.
8. For recurring research, save the input as an Apify Task and attach a schedule or integration.

### Input parameters

#### `profileUrls`

Required array of 1 to 1,000 public Instagram profile URLs.

Accepted example:

```text
https://www.instagram.com/nasa/
```

Post, reel, story, explore, account, API, and non-Instagram URLs are rejected before scraping begins.

#### `maxProfiles`

Optional integer from 1 to 1,000. The Actor processes at most this many unique profiles in input order. The default is 100.

#### `proxyConfiguration`

The tested default uses Apify's `SHADER` proxy group. You can select residential proxy for stricter routing or disable Apify Proxy for tiny direct tests.

Direct requests can work for small inputs but Instagram may challenge repeated requests from one IP. The Actor uses bounded retries and a fresh coherent proxy session after retryable upstream responses.

### Example input

```json
{
  "profileUrls": [
    "https://www.instagram.com/nasa/",
    "https://www.instagram.com/instagram/"
  ],
  "maxProfiles": 2,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["SHADER"]
  }
}
```

Duplicate URLs and username casing differences are collapsed before the limit is applied.

### Example output

A current record has this shape; volatile counters and media URLs are shortened here:

```json
{
  "instagramUserId": "528817151",
  "username": "nasa",
  "fullName": "NASA",
  "biography": "Making the seemingly impossible, possible. ✨",
  "emails": [],
  "phones": [],
  "externalUrl": "https://www.nasa.gov/",
  "category": "GOVERNMENT_ORGANIZATION",
  "businessCategory": "Government Agencies",
  "profileUrl": "https://www.instagram.com/nasa/",
  "isVerified": true,
  "isPrivate": false,
  "isBusinessAccount": true,
  "isProfessionalAccount": true,
  "followersCount": 104249366,
  "followingCount": 92,
  "postsCount": 4871,
  "profilePicUrl": "https://scontent.cdninstagram.com/...",
  "scrapedAt": "2026-08-06T20:06:55.076Z"
}
```

The default dataset contains only successful profile records. A failed input is described in the run log and terminal error, not emitted as a paid placeholder row.

### How much does it cost to extract Instagram profile contacts?

Pay-per-event pricing has two parts:

- **Start:** $0.005 once per valid run.
- **Profile contact record:** tiered per successfully saved record; BRONZE is $0.005 per profile.

At BRONZE pricing, example Actor charges are:

| Successful profiles | BRONZE calculation |
| ---: | --- |
| 1 | $0.005 start + 1 × $0.005 profile |
| 10 | $0.005 start + 10 × $0.005 profiles |
| 100 | $0.005 start + 100 × $0.005 profiles |

Failed profiles have no per-record charge. Proxy and platform usage treatment follows your Apify plan and the active pricing shown in Console. Tier prices decrease at higher customer tiers; Console is the source of truth for the tier active on your account.

### Tips for reliable contact research

- Supply canonical profile URLs rather than post or share URLs.
- Keep the default proxy for repeated or scheduled batches.
- Start with a small representative list before running hundreds of profiles.
- Treat empty `emails` or `phones` arrays as a valid result: many owners publish no contact string.
- Use `scrapedAt` as the snapshot timestamp when comparing scheduled runs.
- Store the stable `instagramUserId` as the entity key because usernames can change.
- Inspect `externalUrl` manually or with a separate authorized workflow; this Actor does not crawl external websites.
- Avoid treating follower counters as perfectly synchronized; Instagram can update public counters between requests.

### Limits and failure behavior

Instagram can rate-limit, challenge, remove, rename, or restrict profiles without notice.

The Actor makes three bounded attempts for retryable 400, 401, 403, 429, and server-error responses. It rotates the request session between attempts instead of repeating an identical blocked request indefinitely.

A missing or unavailable profile fails that input. If a batch contains both successful and failed profiles, successful rows remain in the dataset and are charged, failed rows are not charged, and the overall run fails so incomplete coverage is visible.

Private profiles may expose only the public metadata Instagram chooses to return. This Actor does not bypass privacy settings.

The Actor processes profiles sequentially to reduce challenge rates and uses 256 MB of memory. Very large batches can take longer than tiny tests.

### Integrations and recurring workflows

#### Spreadsheet or CRM enrichment

Run a saved Task from a list of known profile URLs, then export the default dataset to Google Sheets, Airtable, Salesforce, HubSpot, or another integration supported by Apify.

#### Scheduled profile snapshots

Create a Task, attach a daily or weekly schedule, and store each run's dataset. Compare `emails`, `phones`, `biography`, `externalUrl`, categories, and counters using `instagramUserId` plus `scrapedAt`.

#### Webhook pipeline

Attach a run-succeeded webhook and fetch the default dataset from the run payload. A failed mixed batch still preserves successful rows, so error handlers can inspect and retry only unresolved URLs.

#### Dataset API export

Use the dataset API to request JSON, CSV, Excel, or XML without changing the Actor's output contract.

### Run with the Apify API

Replace `APIFY_TOKEN` with your token.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~instagram-contact-scraper/runs?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "profileUrls": ["https://www.instagram.com/nasa/"],
    "maxProfiles": 1
  }'
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/instagram-contact-scraper').call({
  profileUrls: ['https://www.instagram.com/nasa/'],
  maxProfiles: 1,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("APIFY_TOKEN")
run = client.actor("automation-lab/instagram-contact-scraper").call(run_input={
    "profileUrls": ["https://www.instagram.com/nasa/"],
    "maxProfiles": 1,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

For asynchronous workflows, start the run without waiting and poll the run status or use a webhook.

### Use with Apify MCP

#### Claude Code

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/instagram-contact-scraper"
```

#### Claude Desktop, Cursor, and VS Code

Claude Desktop, Cursor, VS Code, and other HTTP MCP clients can use equivalent JSON:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/instagram-contact-scraper"
    }
  }
}
```

Example prompts:

- “Extract public contact and profile data from these Instagram profile URLs.”
- “Run the saved Instagram prospect snapshot and summarize which records publish emails.”
- “Export the resulting public Instagram contact records as CSV.”

MCP clients still use your Apify authorization and the same Actor input, pricing, and output contract.

### Responsible use and legality

This Actor extracts data that Instagram exposes publicly for supplied profiles. Public availability does not remove your legal or ethical responsibilities.

- Follow applicable privacy, data protection, marketing, anti-spam, and platform rules.
- Use contact details only for a lawful purpose.
- Respect opt-outs, suppression lists, and communication consent requirements.
- Do not use output for harassment, discrimination, stalking, or sensitive profiling.
- Do not attempt to access private content or circumvent account restrictions.
- Minimize retention and secure exported personal data.

You are responsible for deciding whether your use case and jurisdiction permit collection and processing.

### Troubleshooting

#### Why did the run reject my URL?

Only a single Instagram profile path is accepted. Use `https://www.instagram.com/username/`, not a post, reel, story, explore page, shortened link, or URL with extra path segments.

#### Why are `emails` and `phones` empty?

The profile owner may not publish contact data, or Instagram may not return dedicated contact fields for that profile. The Actor also scans the biography, but it does not infer private contacts or crawl external sites.

#### Why did some profiles succeed but the run fail?

This is deliberate. Successful records remain available and are charged; failed profiles are not charged. The failed status prevents incomplete batches from looking complete. Inspect the log for each unresolved username.

#### What should I do after 400, 403, or 429 errors?

Keep proxy routing enabled, retry only the unresolved profiles, and avoid immediately repeating a large identical batch. A residential proxy can be selected if your chosen route is challenged, but it may have higher platform cost.

#### Why did a profile counter change between runs?

Follower, following, and post counts are live public values. Changes between requests are normal.

### Related Automation Lab Actors

- [Instagram Scraper](https://apify.com/automation-lab/instagram-scraper) for broader supplied-profile and post workflows.
- [Instagram Post & Reel Details Scraper](https://apify.com/automation-lab/instagram-post-reel-details-scraper) when your input is content URLs rather than profile URLs.

Use this Actor for focused owner-published contact and profile snapshots; use the related Actors only when the additional scope is genuinely required.

### FAQ

#### Does it require an Instagram account?

No. The supported public-profile workflow does not accept or require an Instagram password, cookie, or session token.

#### Can it discover profiles by keyword or hashtag?

No. Supply profile URLs you already know. This keeps output provenance and pricing predictable.

#### Does it follow Linktree or other external links?

No. `externalUrl` is returned as profile data, but external domains are not crawled.

#### Does one profile produce multiple paid rows?

No. Each successfully resolved profile produces one dataset row and one `item` charge event. Biography, emails, phones, counters, categories, and flags are included in that row with no separate event charge.

#### Can I schedule it?

Yes. Save the input as an Apify Task, attach a schedule, and use `instagramUserId` plus `scrapedAt` to compare snapshots.

#### What happens to duplicate URLs?

They are deduplicated by lowercase username before the profile limit is applied, so duplicates do not produce extra output records.

# Actor input Schema

## `profileUrls` (type: `array`):

Public Instagram profile URLs to inspect. Post, reel, story, and search URLs are rejected.

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

Stop after this many unique profiles, in input order.

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

Apify's lower-cost SHADER proxy is the tested default. You can select residential proxy for stricter routes or disable Apify Proxy for small direct tests.

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.instagram.com/nasa/",
    "https://www.instagram.com/instagram/"
  ],
  "maxProfiles": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "SHADER"
    ]
  }
}
```

# Actor output Schema

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

Open the default dataset in the contact-focused overview view.

# 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 = {
    "profileUrls": [
        "https://www.instagram.com/nasa/",
        "https://www.instagram.com/instagram/"
    ],
    "maxProfiles": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "SHADER"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/instagram-contact-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 = {
    "profileUrls": [
        "https://www.instagram.com/nasa/",
        "https://www.instagram.com/instagram/",
    ],
    "maxProfiles": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["SHADER"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/instagram-contact-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 '{
  "profileUrls": [
    "https://www.instagram.com/nasa/",
    "https://www.instagram.com/instagram/"
  ],
  "maxProfiles": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "SHADER"
    ]
  }
}' |
apify call automation-lab/instagram-contact-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/instagram-contact-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/T5cueaJHgN1bBicJw/builds/pz3uSSUGxEhjZNsAi/openapi.json
