# 🌟Instagram Lead Finder (`databuddy/instagram-lead-finder`) Actor

- **URL**: https://apify.com/databuddy/instagram-lead-finder.md
- **Developed by:** [Sarthak](https://apify.com/databuddy) (community)
- **Security:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00005 / actor start

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

## 📸 Instagram Lead Finder — Email, Phone & Influencer Scraper

Turn a list of Instagram usernames into an outreach-ready lead list. For every profile you get the full public profile, **every public email and phone number** (bio, business contact buttons and link-in-bio pages), **engagement rate**, **influencer tier**, a **0–100 lead score with A–D grade**, posting activity, recent posts and similar accounts for discovery.

No login. No cookies. Export to CSV, Excel, JSON or connect through the API.

**Keywords:** instagram scraper · instagram email scraper · instagram phone number scraper · instagram profile scraper · instagram lead generation · influencer finder · engagement rate calculator · link in bio email extractor · linktree email scraper · B2B leads · influencer marketing

***

### ✨ Why this one

| | This actor | Typical Instagram scrapers |
|---|---|---|
| Emails from bio + business button | ✅ | ✅ |
| Emails & phones from **Linktree / Beacons / Stan / websites** | ✅ (optional) | ❌ |
| Obfuscated emails (`name [at] brand [dot] com`) and fancy-font bios | ✅ | ❌ |
| **Evidence column** — the exact phrase every contact came from | ✅ | ❌ |
| Engagement rate that ignores pinned posts | ✅ | ❌ |
| Posting activity (last post, days between posts) | ✅ | ❌ |
| Lead score **with the reason for every point** | ✅ | ❌ |
| Bio keyword filter (exact phrase / all words / any word) | ✅ | ❌ |
| Skip profiles you already paid for in earlier runs | ✅ | ❌ |
| Only charged for profiles you keep — filtered profiles are free | ✅ | ❌ |

### 🎯 Use cases

- **Influencer marketing** — find creators by tier and real engagement, get their contact.
- **B2B & agency lead generation** — collect business emails and phones of brands, shops, coaches, agents.
- **Discovery** — start from a few accounts and pull Instagram's "similar accounts" automatically.
- **Scheduled prospecting** — run daily and only pay for new leads.

### 🔧 Input

```json
{
  "usernames": ["natgeo", "@garyvee", "https://www.instagram.com/hubspot/"],
  "scanBioLinks": true,
  "scrapeRelatedProfiles": true,
  "onlyWithContact": true,
  "influencerTiers": ["micro", "macro"],
  "bioKeywords": ["fitness coach", "ecommerce"],
  "keywordMatchMode": "exact",
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

| Option | What it does |
|---|---|
| `usernames` | Handles, @handles or profile URLs. Duplicates removed. |
| `maxResults` | Stop after N saved profiles (0 = no limit). |
| `scrapeRelatedProfiles` / `maxRelatedPerProfile` | Also scrape the "similar accounts" Instagram shows (one level deep). |
| `scanBioLinks` | Open the external URL / bio links and collect public emails and phones there. |
| `includeRecentPosts`, `recentPostsLimit`, `excludePinnedPosts` | Recent posts in the output and how engagement is calculated. |
| `minFollowers`, `maxFollowers`, `influencerTiers` | Audience size filters. |
| `onlyWithContact`, `onlyBusinessAccounts`, `minLeadGrade` | Lead quality filters. |
| `minEngagementRate`, `includeUnclearEngagement` | Engagement filter, and what to do when engagement can't be measured. |
| `includePrivateAccounts` | Keep or skip private accounts. |
| `bioKeywords`, `keywordMatchMode` | Match name/bio/category: exact phrase, all words, any word or off. Capitals, accents, hyphens and plurals are treated as equal (e-commerce = ecommerce, coach = coaches). |
| `skipPreviouslyScraped`, `dedupeStoreName` | Remember saved usernames across runs and skip them next time. |
| `proxyConfiguration` | **Use Apify Residential.** Instagram blocks datacenter IPs. |

### 📤 Output (55 fields per profile)

**Profile:** username, full name, profile URL, user ID, biography, followers, following, posts, verified, business account, professional account, private, category, business category, business address, external URL, bio links, profile picture (HD), IGTV count, highlight reels, reels, pronouns.

**Contacts:** business email, business phone, emails found in bio, phones found in bio, emails from bio links, phones from bio links, all emails, all phones, primary email, primary phone, has contact, **contact evidence**.

**Influencer metrics:** engagement rate %, average likes, average comments, average video views, posts analysed, engagement note, last post date, days since last post, average days between posts, influencer tier.

**Lead scoring:** lead score (0–100), lead grade (A–D), lead score reasons, keyword match evidence.

**Discovery:** related profiles, related profile count, recent posts (URL, type, date, likes, comments, views, caption, pinned).

```json
{
  "username": "acme.fitness",
  "full_name": "Acme Fitness",
  "followers": 106192,
  "influencer_tier": "macro",
  "engagement_rate_pct": 2.87,
  "lead_score": 75,
  "lead_grade": "A - Hot Lead",
  "primary_email": "team@acmefitness.com",
  "primary_phone": "+14155550123",
  "contact_evidence": [
    "team@acmefitness.com ← link page linktr.ee/acme.fitness: mailto link",
    "+14155550123 ← bio: \"📞 +1 415 555 0123\""
  ],
  "lead_score_reasons": ["+30 email found", "+15 phone found", "+10 average engagement (2.87%)", "+10 active (last post 1 day ago)"]
}
```

**Every input gets a row.** Profiles that can't be scraped appear with `status` = `blocked`, `not_found` or `invalid_input`, the exact `error` and a `fix_hint` telling you what to change. These rows are never charged (turn them off with `includeFailedProfiles: false`). Successful rows have `status` = `ok`.

The dataset has three views: **Overview** (all fields), **Contacts only** and **Influencer metrics**.

#### Lead score

| Points | Signal |
|---|---|
| +30 | Email found |
| +15 | Phone found |
| +10 | Business or creator account |
| +5 | Website or link in bio |
| +5 | Verified |
| +5 to +20 | Engagement (0.5% / 1% / 3% / 6%+) |
| +5 / +10 | Posted in the last 60 / 14 days |
| +5 | 1K+ followers |
| −10 | Private account |

**A - Hot Lead** 75–100 · **B - Warm Lead** 50–74 · **C - Cool Lead** 25–49 · **D - Cold Lead** 0–24

#### Influencer tiers

sub-nano < 1K · nano 1K–10K · micro 10K–100K · macro 100K–1M · mega 1M+

### 📊 Run summary

Every run writes a `RUN_SUMMARY` record (Storage → Key-value store): profiles saved, saved with contact, charged events, results per input profile, request and block counts, field fill rates and **every skip reason with examples** — so you always know why a profile is missing.

### 💰 Pricing

Pay per result. You are charged only for profiles that are saved to your dataset:

| Event | When |
|---|---|
| `profile-lead` | Profile saved, no public email or phone found |
| `profile-lead-with-contact` | Profile saved with at least one email or phone |

Profiles that are not found, blocked, duplicated, already seen in a previous run, or removed by your filters are **never charged**. Set "Max cost per run" and the actor stops cleanly at your budget.

### ❓ FAQ

**Why are some emails missing?** Many accounts don't publish one. Turn on `scanBioLinks` — link-in-bio pages often list an email that isn't in the bio.

**Why is engagement empty for some profiles?** Private accounts, accounts with no posts and accounts that hide like counts can't be measured. The field stays empty (never estimated) and `engagement_note` says why.

**Why are related profiles empty?** Instagram doesn't show similar accounts for every profile to logged-out visitors. The summary counts how often this happened.

**My run finished with no profiles.** Open the Output tab: each profile has a `status` and `fix_hint`. `blocked` almost always means the run wasn't on the RESIDENTIAL proxy group, or Instagram was rate-limiting at that moment — run again.

**I'm getting blocked.** Use the Apify **RESIDENTIAL** proxy group. Blocked requests are retried on a new IP automatically.

### ⚖️ Notes

This actor reads public Instagram profile data only. Contact details are those the account owner chose to publish. You are responsible for using the data in line with Instagram's terms and privacy laws in your market (GDPR, CAN-SPAM, etc.), including how you contact people.

# Actor input Schema

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

One per line. Accepts plain handles (natgeo), handles with @ (@natgeo) or profile URLs (https://www.instagram.com/natgeo/). Duplicates are removed automatically.

## `maxResults` (type: `integer`):

Stop after this many profiles are saved (and charged). 0 = no limit.

## `includeFailedProfiles` (type: `boolean`):

Adds a row (status = blocked / not_found / invalid_input) for every profile that could not be scraped, with the reason and how to fix it. These rows are never charged.

## `scrapeRelatedProfiles` (type: `boolean`):

Instagram shows 'similar accounts' on many profiles. When on, those accounts are added to the queue and scraped too (one level deep). Great for finding more influencers in the same niche.

## `maxRelatedPerProfile` (type: `integer`):

How many related accounts to follow from each input profile when discovery is on.

## `scanBioLinks` (type: `boolean`):

Opens the external URL and bio links (Linktree, Beacons, Stan, websites…) and collects public emails and phone numbers found there. Slower, but finds far more contacts. Each contact found this way shows its source page in the evidence column.

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

Add the latest posts (likes, comments, video views, caption, URL) to each profile. Engagement rate is calculated from these posts either way.

## `recentPostsLimit` (type: `integer`):

How many of the latest posts to analyse (Instagram returns up to 12 without login).

## `excludePinnedPosts` (type: `boolean`):

Pinned posts are often old viral posts and inflate engagement. When on, they are left out of the engagement rate.

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

Skip profiles with fewer followers. 0 = no minimum.

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

Skip profiles with more followers. 0 = no maximum.

## `influencerTiers` (type: `array`):

Keep only these tiers. Leave empty to keep all. Tiers: under 1K = sub-nano, 1K–10K = nano, 10K–100K = micro, 100K–1M = macro, 1M+ = mega.

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

Skip profiles where no public email or phone number was found.

## `onlyBusinessAccounts` (type: `boolean`):

Skip personal accounts. Keeps profiles Instagram marks as business or professional.

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

Skip profiles below this grade. A = Hot (75–100), B = Warm (50–74), C = Cool (25–49), D = Cold (0–24).

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

Skip profiles with a lower engagement rate, e.g. 1.5 for 1.5%. 0 = no minimum.

## `includeUnclearEngagement` (type: `boolean`):

When a min engagement rate is set, profiles where engagement cannot be measured (private, no posts, hidden likes) are kept if this is on and skipped if off. Their engagement fields stay empty — never guessed.

## `includePrivateAccounts` (type: `boolean`):

Private accounts still show bio, follower counts and business contact, but no posts. Turn off to skip them.

## `bioKeywords` (type: `array`):

Keep only profiles whose name, bio or category matches at least one of these keywords (e.g. 'real estate', 'fitness coach', 'ecommerce'). Leave empty to keep all. Hyphens, accents, capitals and simple plurals are treated as equal (e-commerce = ecommerce = E-Commerce).

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

Exact phrase: the words must appear together in order. All words: every word must appear anywhere. Any word: one word is enough. Off: ignore bio keywords.

## `skipPreviouslyScraped` (type: `boolean`):

Remembers every saved username in a named key-value store and skips them in later runs. Useful for scheduled runs so you only pay for new leads.

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

Name of the key-value store that remembers saved usernames. Use different names to keep separate lists. Lowercase letters, numbers and hyphens only.

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

Instagram blocks datacenter IPs. Apify Residential proxy is strongly recommended.

## Actor input object example

```json
{
  "usernames": [
    "natgeo",
    "garyvee",
    "hubspot"
  ],
  "maxResults": 0,
  "includeFailedProfiles": true,
  "scrapeRelatedProfiles": false,
  "maxRelatedPerProfile": 10,
  "scanBioLinks": false,
  "includeRecentPosts": true,
  "recentPostsLimit": 12,
  "excludePinnedPosts": true,
  "minFollowers": 0,
  "maxFollowers": 0,
  "influencerTiers": [],
  "onlyWithContact": false,
  "onlyBusinessAccounts": false,
  "minLeadGrade": "D",
  "minEngagementRate": 0,
  "includeUnclearEngagement": true,
  "includePrivateAccounts": true,
  "bioKeywords": [],
  "keywordMatchMode": "exact",
  "skipPreviouslyScraped": false,
  "dedupeStoreName": "instagram-lead-finder-seen",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

No description

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

No description

## `runSummary` (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": [
        "natgeo",
        "garyvee",
        "hubspot"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("databuddy/instagram-lead-finder").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": [
        "natgeo",
        "garyvee",
        "hubspot",
    ],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("databuddy/instagram-lead-finder").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": [
    "natgeo",
    "garyvee",
    "hubspot"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call databuddy/instagram-lead-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,databuddy/instagram-lead-finder"
        }
    }
}
```

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/LrdvxbvkEEGZNoQMW/builds/0ukwKVZsdLA2DFjwB/openapi.json
