# Instagram B2B Email Scraper & Phone Leads (`simpleapi/instagram-b2b-email-scraper`) Actor

📸 Instagram B2B Email Scraper (instagram-b2b-email-scraper) extracts verified business emails & contact info from Instagram profiles, bios and linked sites. 🎯 Filter by hashtag, niche, location. 🚀 Ideal for B2B lead gen, outreach & sales. ⚙️ CSV/CRM export & email validation.

- **URL**: https://apify.com/simpleapi/instagram-b2b-email-scraper.md
- **Developed by:** [SimpleAPI](https://apify.com/simpleapi) (community)
- **Categories:** Automation, Lead generation, Social media
- **Stats:** 5 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$19.99/month + usage

To use this Actor, you pay a monthly rental fee to the developer. The rent is subtracted from your prepaid usage every month after the free trial period. You also pay for the Apify platform usage, which gets cheaper the higher Apify subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#rental-actors

## 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 Scraper — Business Emails, Phone Leads and Verified Profiles

Instagram B2B Email Scraper & Phone Leads finds business emails and phone numbers for Instagram business accounts — no Instagram login required. Targeted Google searches DISCOVER accounts in your niche; every contact is then read from that account's own live Instagram bio and bio links, so the email and phone on a row provably belong to the handle in its `url`. Each lead also carries real follower/verification data, the keyword and B2B pattern that surfaced it, and the Google result it was found through. It's built for B2B sales teams, outreach agencies, and lead-generation pipelines that need real, dial-code-targeted contact data at scale.

### What is Instagram B2B Email Scraper & Phone Leads?

Instagram B2B Email Scraper & Phone Leads is an Apify Actor that discovers Instagram-linked business contacts through Google Search rather than logging into Instagram directly — no Instagram account or session cookie is needed. Key capabilities:

- Search by keyword across Instagram profiles, posts, and reels via Google to discover accounts, with an optional geographic search modifier
- Collect emails, phone numbers, or leads that have both, controlled by `contactTypes`
- Run in B2B mode (corporate email search patterns, e.g. "email for bookings", "contact @ domain") or personal mode (Gmail/Outlook domain filtering)
- Target and filter phone numbers by country name or dial code
- Every lead carries real, live Instagram profile data (followers, following, full name, verified, private, bio, bio link) read from Instagram's own server-rendered payload
- Smart proxy rotation with automatic tier escalation for stable Google Search access

### What data can I extract with Instagram B2B Email Scraper & Phone Leads?

| Field | Example Value | Use Case |
| --- | --- | --- |
| `email` | `"bookings@studiofit.com"` | The primary contact target for outreach |
| `phoneNumber` | `"+442071234567"` | Direct phone contact, normalized and optionally country-filtered |
| `dialCode` | `"+44"` | The number's own country calling code |
| `country` | `"United Kingdom"` | The number's own country, resolved by libphonenumber from the number itself |
| `keyword` | `"fitness coach"` | Identify which search term surfaced this lead |
| `pattern` | `"email_for_bookings"` | Identify which B2B search pattern found this lead (B2B mode only) |
| `leadType` | `"b2b"` | Distinguish B2B corporate leads from personal-domain leads |
| `emailSource` | `"instagram_bio"` | Where the email was read from: `instagram_bio` or `instagram_bio_link` |
| `phoneSource` | `"instagram_bio_link"` | Where the number was read from: `instagram_bio` or `instagram_bio_link` (e.g. a `wa.me` link) |
| `url` | `"https://www.instagram.com/studiofitofficial/"` | The Instagram account the contact belongs to |
| `username` | `"studiofitofficial"` | The account handle |
| `fullName` | `"Studio Fit"` | The account's display name |
| `sourceUrl` | `"https://www.instagram.com/reel/DYKf_zGsUgc/"` | The Google result (often a post or reel) that led to this account |
| `network` | `"Instagram.com"` | Confirm the source platform |
| `location` | `"London"` | Confirm the geographic search modifier applied, if any |
| `scraped_at` | `"2026-07-26T14:02:11Z"` | Record when this lead was collected |
| `followersCount` | `18420` | Gauge account size and outreach potential |
| `verified` | `false` | Prioritize verified accounts if desired |
| `bio` | `"Personal training studio in London"` | Qualify the lead's stated business description |
| `externalUrl` | `"https://studiofit.com/"` | Cross-reference the lead's own website |

#### Where every contact comes from

A Google result for `site:instagram.com` is almost always a post or reel, and the snippet Google shows for it is the post *caption*. Captions credit guest artists, tag partner studios and quote other people's booking details constantly, so an address scraped from a snippet is not provably the account's own — and pairing it with that account's URL is simply a wrong record.

This Actor therefore treats Google as a pure **discovery** surface. For each result it resolves the account that owns it (a post page's `og:url` names its owner), loads that account's live Instagram profile, and reads the contact out of two fields and only two: the account's `biography` text and its `bio_links` array — where a `mailto:` link or a WhatsApp deep link such as `wa.me/447859882379` *is* the business's contact. `emailSource` and `phoneSource` record which of the two every value came from. Captions, comments and SERP snippets are never consulted.

The same profile payload supplies `followersCount`, `followingCount`, `fullName`, `verified`, `isPrivate`, `bio` and `externalUrl`, so every lead arrives already qualified. No login, session cookie or Instagram account is needed for any of it. Phone numbers are validated against the real numbering plan of the country their prefix claims (Google's libphonenumber), and `dialCode` / `country` are read off the accepted number rather than echoed from your input.

**On business category, business-account flag and lookalike profiles:** these are deliberately *not* offered. They live only behind `/api/v1/users/web_profile_info/`, and that route is closed: measured with a confirmed-live Instagram session from a residential exit, it returns HTTP 429 to both bot-shaped and fully browser-shaped authenticated requests; the authenticated profile page returns the *viewer's* own record rather than the target's; and `/api/v1/users/<pk>/info/` accepts the session and answers `{"user":{},"status":"ok"}` -- an empty object. The logged-out payload this Actor reads has never carried them. Rather than ship columns that are permanently `null` and a session-cookie input that provably changes nothing, both were removed.

#### Country, location and B2B pattern targeting

`country` accepts a country name or dial code (e.g. `"United Kingdom (+44)"` or just `"+91"`); when it resolves to a dial code, phone matches are both normalized and filtered to that code. `searchLocation` adds a geographic term to the underlying Google query (e.g. "London"). In B2B mode, `b2bSearchPatterns` selects which named corporate-email search patterns run (leave empty to run all of them); in personal mode, `personalDomainAllowlist` restricts results to specific email domains.

### Why not build this yourself?

Instagram's own Graph API requires a Business or Creator account and app review for any profile data access, and has no endpoint for keyword-based discovery of contact information across arbitrary public profiles, posts, or reels — that isn't a gap this Actor works around lightly. Building an equivalent tool means handling Google SERP HTML parsing across changing result-block layouts, a three-tier proxy escalation ladder (direct → datacenter → residential) for when Google rate-limits or blocks a request, country/dial-code-aware phone number parsing and normalization, and — for profile enrichment — knowing that instagram.com serves a full server-rendered data payload to a plain HTTP client but a contentless JavaScript shell to anything that looks like Chrome, which is the opposite of what a scraper author would assume. Phone parsing is where naive implementations quietly produce garbage: a loose regex plus "prepend the dial code" will happily emit `+18893094` from a truncated 7-digit fragment, or relabel an ordinary US number as `+443233643929`. This Actor validates every candidate against the target country's real numbering plan (Google's libphonenumber) and checks the line type before a number is allowed into the dataset. All of that is implemented and already handled in this Actor's source.

### How to use data extracted from Instagram?

#### B2B sales and lead generation

Run `targetKeywords` for your ideal customer profile (e.g. "yoga studio", "personal trainer") with `collectionMode` set to `b2b` and `contactTypes` set to `both` to get leads carrying both an email and a phone number in the same bio, filtered to your target market with `country`. Every row already includes `followersCount` and `verified`, so your sales team can prioritize the highest-potential accounts without a second enrichment pass.

#### Marketing and outreach agencies

Agencies running lead generation for multiple clients can run one keyword set per client and use `b2bSearchPatterns` to target the specific corporate-contact patterns that convert best for that client's vertical (e.g. `email_for_bookings` for service businesses), then export `email`, `phoneNumber`, and `followersCount` directly into that client's CRM import template.

#### Market and lead-density research

Run the same keyword across multiple `country` values to compare how many qualified leads (with a real phone number and a healthy `followersCount`) exist per market, using `maxContactLeads` to cap each market's sample size consistently for a fair comparison.

#### AI agents and automated pipelines

An agent can call this Actor as a lead-discovery tool inside a larger outreach pipeline — passing a target niche as `targetKeywords`, filtering the returned dataset on `contactTypes` and `verified`, and feeding qualified leads directly into a CRM or email-sequencing API without manual review of every raw Google result.

### 🔼 Input sample

| Parameter | Required | Type | Description | Example Value |
| --- | --- | --- | --- | --- |
| `targetKeywords` | No | array | Search terms for Instagram via Google (e.g. marketing, fitness, real estate) | `["fitness coach"]` |
| `contactTypes` | No | string (enum) | `email` (default), `phone`, or `both` (require both on the same lead) | `"both"` |
| `country` | No | string | Country name and/or dial code to target and filter phone matches by | `"United Kingdom (+44)"` |
| `collectionMode` | No | string (enum) | `b2b` (default, corporate email patterns) or `personal` (Gmail/Outlook domain filter) | `"b2b"` |
| `personalDomainAllowlist` | No | array | Personal mode only: domains to filter results to | `["@gmail.com", "@outlook.com"]` |
| `b2bSearchPatterns` | No | array | B2B mode only: named search patterns to run; empty = all patterns | `["email_for_bookings", "bio_email_basic"]` |
| `contactSourcePlatform` | No | string (enum) | Target platform; only `"Instagram.com"` is supported | `"Instagram.com"` |
| `searchLocation` | No | string | Geographic filter added to the search query | `"London"` |
| `maxContactLeads` | No | integer (1-50,000) | Maximum leads to collect across all keywords/patterns | `10` (default) |
| `maxLeadsPerPattern` | No | integer (1-5,000) | Cap leads per B2B search pattern (B2B mode only) | `15` (default) |
| `smartProxyRotation` | No | boolean | Enable Apify proxy with automatic tier escalation | `true` (default) |
| `maxRuntimeMinutes` | No | integer (1-720) | Wall-clock budget; the run stops paging when it expires | `20` (default) |
| `proxyConfiguration` | No | object | Advanced proxy override for the Google leg (ignored when `smartProxyRotation` is off) | `{"useApifyProxy": true, "apifyProxyGroups": ["GOOGLE_SERP"]}` |

```json
{
  "targetKeywords": ["fitness coach", "personal trainer"],
  "contactTypes": "both",
  "country": "United Kingdom (+44)",
  "collectionMode": "b2b",
  "maxContactLeads": 100
}
```

**Common pitfall:** `contactTypes: "both"` requires the *same account's bio* to carry an email **and** a phone number — a much narrower bar than `"email"` or `"phone"` alone, because most bios publish only one. A second pitfall: leaving `country` empty means a number written in national trunk form (`020 7953 3831`) has no resolvable country and is skipped rather than guessed — set `country` whenever your targets are outside the NANP.

### 🔽 Output sample

Output is typed, normalized JSON — one row per lead (exportable as JSON, CSV, or Excel from the dataset, or via API).

```json
{
  "url": "https://www.instagram.com/mdtattoostudio/",
  "sourceUrl": "https://www.instagram.com/p/DY5KbZ6AQg_/",
  "email": "bookings@mdtattoostudio.com",
  "emailSource": "instagram_bio",
  "phoneNumber": "+18059101444",
  "phoneSource": "instagram_bio",
  "dialCode": "+1",
  "country": "United States",
  "username": "mdtattoostudio",
  "fullName": "MD Tattoo Studio",
  "followersCount": 57030,
  "followingCount": 1128,
  "verified": true,
  "isPrivate": false,
  "bio": "For Appointments, Text, Email, or Come On In! \ud83d\udc83\n\ud83d\udcac (805) 910-1444\n\ud83d\udce7 bookings@mdtattoostudio.com\nWalk-ins are always welcome\nThousand Oaks, California",
  "externalUrl": "https://linktr.ee/tattooshop",
  "network": "Instagram.com",
  "keyword": "tattoo studio",
  "pattern": "bio_email_basic",
  "leadType": "b2b",
  "location": null,
  "scraped_at": "2026-08-30T06:36:50Z"
}
```

Every field shown above is a real dataset column. Any value the live fetch could not establish is emitted as `null` — never `0`, never `""`, never a plausible-looking guess.

### How do you filter and target specific leads?

`collectionMode` is the category-versus-query axis here: `b2b` runs named corporate-contact search patterns (`b2bSearchPatterns` — leave empty to run all of them, or name specific ones like `email_for_bookings` or `contact_at_domain` for a narrower, higher-relevance sweep), while `personal` runs a Gmail/Outlook-style domain search filtered by `personalDomainAllowlist`. Scope precision comes from `country` (name or dial code — resolving it also filters and normalizes phone matches to that code) combined with `searchLocation` for a city/region-level narrowing of the underlying Google query. The closest thing to a quality threshold is `contactTypes`: set to `"both"` it requires a lead to carry both a matched email and phone number on the same source, a much stricter bar than either alone; and `followersCount` / `verified` come directly from Instagram's own profile data on every row, not inferred from a search snippet. Volume is controlled by `maxContactLeads` (the run-wide cap) and, in B2B mode, `maxLeadsPerPattern` (a per-pattern cap so one high-yield pattern doesn't crowd out the others).

```json
{ "targetKeywords": ["yoga studio"], "collectionMode": "b2b", "b2bSearchPatterns": ["email_for_bookings"], "contactTypes": "both", "country": "+1" }
```

```json
{ "targetKeywords": ["freelance photographer"], "collectionMode": "personal", "personalDomainAllowlist": ["@gmail.com"], "maxContactLeads": 50 }
```

```json
{ "targetKeywords": ["real estate agent"], "searchLocation": "Miami", "contactTypes": "both", "country": "United States" }
```

### ▶️ Want to try other Instagram scrapers?

| Scraper Name | What it extracts |
| --- | --- |
| Instagram Profile Scraper | Full public profile details for a known username or URL |
| Instagram Related Person Scraper | Related/lookalike profile networks for a given account |
| Instagram Phone Number Scraper | Phone-number-focused lead discovery from Instagram content |
| Instagram Hashtag Scraper | Posts and profiles discovered by hashtag |
| LinkedIn B2B Email Scraper | Corporate email and phone leads sourced from LinkedIn |
| Alibaba Email Scraper & Trade Assurance Details | Supplier contact leads sourced from Alibaba |

### How to extract Instagram data programmatically

Every run is a standard Apify Actor call — one API request with your token, JSON input, JSON leads back. No Instagram login is required.

#### Python example

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_API_TOKEN>")

run_input = {
    "targetKeywords": ["fitness coach"],
    "contactTypes": "both",
    "country": "United Kingdom (+44)",
    "maxContactLeads": 50,
}

run = client.actor("<YOUR_USERNAME>/instagram-b2b-email-scraper-phone-leads").call(run_input=run_input)

for lead in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(lead["email"], lead["phoneNumber"], lead["keyword"])
```

#### Export to spreadsheets or CRM

Export the dataset directly as CSV or Excel, then map `email` and `phoneNumber` to your CRM's contact fields, `keyword`/`pattern` to a lead-source column, and `followersCount`/`verified` (when enrichment is on) to a segmentation column for outreach targeting.

### Is it legal to scrape Instagram contact leads?

Discovered emails and phone numbers are personal or business-contact data, so GDPR and CCPA obligations apply to how you store and use them — the same as any lead-generation dataset containing individual contact details. Instagram's own bio/profile fields are public by design (visible to any logged-out visitor), but downstream storage and use of contact data for marketing purposes should follow applicable data-protection and anti-spam rules (e.g. CAN-SPAM, GDPR lawful-basis requirements). Consult legal counsel for commercial applications involving bulk storage of personal contact data.

### ❓ FAQ

#### Does this actually extract phone numbers, not just emails?

Yes. `contactTypes` lets you collect phone numbers only, emails only, or require both on the same lead, and choosing `phone` also switches the Google query set to phone-oriented patterns ("call or text", "whatsapp", "📞") instead of the email-oriented ones. Every number is validated against its country's real numbering plan with Google's libphonenumber, and the line type is checked too — so truncated fragments, follower counts, years, and foreign numbers wearing the wrong country code are rejected rather than shipped.

#### How accurate is the enriched profile data?

`followersCount`, `followingCount`, `fullName`, `verified`, `isPrivate`, `bio` and `externalUrl` are read from the lead's live Instagram page at request time — the same data the profile itself displays. If the username can't be resolved or a fetch fails, the affected fields return `null` rather than a guessed value. Business category and lookalike profiles are not offered at all; see the enrichment section for the measurements behind that.

#### How many leads can I get per run?

Set `maxContactLeads` (1-50,000, default 10) for the overall run cap, and `maxLeadsPerPattern` (1-5,000, default 15) to cap how many leads any single B2B pattern can contribute.

#### Do I need an Instagram account to use this?

No. Lead discovery runs entirely through Google Search, and profile enrichment reads Instagram's public server-rendered profile page. Every field this Actor returns is obtainable fully logged-out, and it never asks you for a cookie.

#### What's the difference between B2B mode and personal mode?

`b2b` mode runs corporate-contact search patterns (e.g. "email for bookings") aimed at business accounts; `personal` mode instead filters results to specific consumer email domains you supply via `personalDomainAllowlist` (e.g. Gmail, Outlook).

#### Can I target leads by country?

Yes — set `country` to a country name, ISO code and/or dial code (e.g. `"United Kingdom (+44)"`, `"United States"`, `"GB"`, or just `"+91"`). Matches are normalized to E.164 and validated against that country's numbering plan. Because the United States and Canada share `+1`, naming the country (not just the dial code) is what lets the area code decide between them — asking for Canada will not return US numbers.

#### Does Instagram B2B Email Scraper & Phone Leads work with Claude, ChatGPT, and AI agent frameworks?

It has no dedicated MCP server registration in this Actor's current setup, but it is callable as a standard Apify API endpoint by any agent framework that can make an authenticated HTTP request and parse JSON.

#### How does this compare to other Instagram lead-generation scrapers?

No independently verifiable competitor listing could be confirmed at the time of writing, so no specific comparison is made here. This Actor's distinguishing combination is dial-code phone targeting plus optional real (not inferred) profile enrichment in the same run.

### Conclusion

Instagram B2B Email Scraper & Phone Leads turns keyword-driven Google discovery into structured, dial-code-targeted contact leads — with genuine, libphonenumber-validated phone extraction and real Instagram profile data on every row, all computed without ever logging into Instagram. Because every contact is read from the account's own bio rather than from a search snippet, the email and phone on a row are attributable to the handle beside them. Start a run with your target keywords and country.

# Actor input Schema

## `targetKeywords` (type: `array`):

🔎 Search terms used to DISCOVER Instagram business accounts via Google (e.g. marketing, tattoo studio, real estate). ✨ Add one or many keywords. (base key `keywords` still accepted)

## `contactTypes` (type: `string`):

📧 email = only accounts whose bio carries an email | 📱 phone = only accounts whose bio (or WhatsApp bio link) carries a VALIDATED phone number | 🤝 both = require BOTH on the same account. 📱/🤝 also switch the default Google query set to phone-oriented patterns. (legacy base key `extractPhone: true` is honoured as `both` when this field is left unset)

## `country` (type: `string`):

🌍 Country name, ISO code and/or dial code (e.g. 'United Kingdom (+44)', 'United States', 'GB', or just '+91'). 🎯 Phone matches are normalized AND validated against that country's real numbering plan — for +1 the area code decides between 🇺🇸 US and 🇨🇦 Canada. 💡 Setting it also RECOVERS numbers written in national format ('01284 723939'), which are un-resolvable without a country. Leave empty for no country targeting.

## `collectionMode` (type: `string`):

🏢 b2b = corporate email search patterns (personal webmail domains excluded from the results) | 👤 personal = Gmail/Outlook-style discovery restricted to 📬 Custom Email Domains. Controls how the Google queries are built and how bio emails are filtered. (base key `mode` still accepted)

## `personalDomainAllowlist` (type: `array`):

👤 Personal mode only: narrows BOTH the Google query and the result filter to these domains (e.g. @gmail.com, @outlook.com). ⏭️ Ignored in B2B mode. (base key `customDomains` still accepted)

## `b2bSearchPatterns` (type: `array`):

🧩 Leave EMPTY (recommended) to auto-pick the right set: email patterns for 📧/🤝, phone patterns for 📱. Or name specific keys — 📧 email keys: email\_for\_bookings, bio\_email\_basic, job\_applications, email\_direct\_mention, cta\_get\_in\_touch, careers\_hiring, hours\_contact, hr\_recruitment, customer\_service, team\_department, email\_mention\_variations, bio\_for\_collab, interested\_in, multiple\_locations, professional\_services, booking\_inquiries, cta\_more\_info, email\_for\_rates, email\_us\_at\_variations, membership\_join, contact\_at\_domain, business\_account, business\_development, contact\_info\_section, franchise\_contact, sponsor\_me, bio\_email\_emoji\_extended, dm\_or\_email, WhatsApp\_business. 📱 phone keys: phone\_whatsapp, phone\_call\_or\_text, phone\_call\_us, phone\_number\_label, phone\_bookings, phone\_emoji, phone\_enquiries. (base key `patterns` still accepted)

## `contactSourcePlatform` (type: `string`):

📱 Target social platform for lead discovery. (base key `platform` still accepted)

## `searchLocation` (type: `string`):

🗺️ Geographic phrase added to every search query (e.g. London, New York). 🌍 Leave empty for global results. (base key `location` still accepted)

## `maxContactLeads` (type: `integer`):

🎯 Hard cap on leads collected across all keywords and patterns. ℹ️ Only accounts whose LIVE bio actually carries the requested contact type are counted, so a high cap simply means the run keeps searching. (base key `maxEmails` still accepted)

## `maxLeadsPerPattern` (type: `integer`):

📈 Cap leads collected per search pattern before moving to the next one (🏢 B2B mode only). Keeps one productive pattern from consuming the whole budget. (base key `maxEmailsPerPattern` still accepted)

## `maxRuntimeMinutes` (type: `integer`):

🛑 Wall-clock budget for the whole run. When it expires the actor stops paging and finishes with whatever it has, instead of grinding on a doomed query until the platform timeout.

## `smartProxyRotation` (type: `boolean`):

✅ ON = Apify proxy with automatic tier escalation (GOOGLE\_SERP for Google, RESIDENTIAL for instagram.com) and per-request session rotation. ❌ OFF = direct connection only; this OVERRIDES 🛡️ Proxy Configuration below. ⭐ Google blocks Apify datacenter IPs, so leave this ON. (base key `useProxy` still accepted)

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

🔧 Optional proxy override for the GOOGLE SEARCH leg, used only when 🛡️ Smart Proxy Rotation is ON. 🎯 Leave as GOOGLE\_SERP — it is the only Apify group tuned for Google Search. ℹ️ instagram.com is always fetched over RESIDENTIAL, because the GOOGLE\_SERP group is scoped to google.com and cannot reach it. (base key `proxyOverride` still accepted)

## Actor input object example

```json
{
  "targetKeywords": [
    "tattoo studio"
  ],
  "contactTypes": "email",
  "country": "",
  "collectionMode": "b2b",
  "personalDomainAllowlist": [
    "@gmail.com",
    "@outlook.com"
  ],
  "b2bSearchPatterns": [],
  "contactSourcePlatform": "Instagram.com",
  "searchLocation": "",
  "maxContactLeads": 10,
  "maxLeadsPerPattern": 15,
  "maxRuntimeMinutes": 20,
  "smartProxyRotation": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}
```

# Actor output Schema

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

All scraped items in the Actor's default dataset.

## `phoneLeads` (type: `string`):

Phone-focused columns: number, dial code, country, where it was found, account and profile URL.

## `b2bLeads` (type: `string`):

Email-focused columns for B2B leads: email, phone, where it was found, account, pattern, keyword and profile URL.

# 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 = {
    "targetKeywords": [
        "tattoo studio"
    ],
    "contactTypes": "email",
    "country": "",
    "collectionMode": "b2b",
    "personalDomainAllowlist": [
        "@gmail.com",
        "@outlook.com"
    ],
    "b2bSearchPatterns": [],
    "contactSourcePlatform": "Instagram.com",
    "searchLocation": "",
    "maxContactLeads": 10,
    "maxLeadsPerPattern": 15,
    "maxRuntimeMinutes": 20,
    "smartProxyRotation": true,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "GOOGLE_SERP"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("simpleapi/instagram-b2b-email-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 = {
    "targetKeywords": ["tattoo studio"],
    "contactTypes": "email",
    "country": "",
    "collectionMode": "b2b",
    "personalDomainAllowlist": [
        "@gmail.com",
        "@outlook.com",
    ],
    "b2bSearchPatterns": [],
    "contactSourcePlatform": "Instagram.com",
    "searchLocation": "",
    "maxContactLeads": 10,
    "maxLeadsPerPattern": 15,
    "maxRuntimeMinutes": 20,
    "smartProxyRotation": True,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["GOOGLE_SERP"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("simpleapi/instagram-b2b-email-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 '{
  "targetKeywords": [
    "tattoo studio"
  ],
  "contactTypes": "email",
  "country": "",
  "collectionMode": "b2b",
  "personalDomainAllowlist": [
    "@gmail.com",
    "@outlook.com"
  ],
  "b2bSearchPatterns": [],
  "contactSourcePlatform": "Instagram.com",
  "searchLocation": "",
  "maxContactLeads": 10,
  "maxLeadsPerPattern": 15,
  "maxRuntimeMinutes": 20,
  "smartProxyRotation": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}' |
apify call simpleapi/instagram-b2b-email-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,simpleapi/instagram-b2b-email-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/M9splOOZxR564Y35I/builds/qkS64g2ViIpq8okjw/openapi.json
