π Instagram Profile Contact Enricher
Pricing
$19.99/month + usage
π Instagram Profile Contact Enricher
Instagram Profile Phone Number Scraper collects phone contact data to support audience research and outreach. Analyze niches, regions, or trends while identifying direct contact points efficiently.
Pricing
$19.99/month + usage
Rating
0.0
(0)
Developer
SimpleAPI
Maintained by CommunityActor stats
0
Bookmarked
22
Total users
1
Monthly active users
17 days ago
Last modified
Categories
Share
Instagram Contact Scraper β Phone, Email and Link-in-Bio Data
Paste a list of Instagram usernames, handles, profile URLs, post URLs, or numeric user IDs, and get back one contact row per profile: business phone, business email, E.164-validated bio phone/email/WhatsApp, category, verification and business flags, follower count, and every contact hiding behind a Linktree/Beacons/Carrd-style link-in-bio page. Every value traces to Instagram's own web_profile_info payload or a page that was actually fetched β nothing is guessed or filled with a fake 0. Built for sales teams, lead-gen agencies, and researchers who already have a list and need it enriched, not discovered.
What is Instagram Contact Scraper?
Instagram Contact Scraper (Actor name: instagram-profile-contact-enricher) is a bring-your-own-list enricher: it does not search or discover profiles by keyword β you supply the usernames, and it turns each one into a structured contact row. No Instagram login, cookies, or developer account are required; it reads Instagram's public, logged-out web_profile_info endpoint with a Chrome-TLS-impersonating client, falling back to a four-layer HTML parse if the JSON API is unavailable.
- Direct-list enrichment, not discovery β accepts plain usernames,
@handles, profile URLs, post/reel URLs (the post owner is resolved and enriched), and numeric user IDs, all in oneprofilesarray. - Authoritative contact fields β
businessPhone,businessEmail, plus bio-parsedphonesFromBio,emailsFromBio, andwhatsapp, each validated with libphonenumber so follower counts, years, and post IDs are rejected rather than emitted as fake phone numbers. - Link-in-bio unwrapping β the differentiator: when a bio link points at a known aggregator (Linktree, Beacons, Stan.store, Carrd, and more), the actor fetches that page plus one hop of its destination links and scans them for contacts the profile itself never surfaces.
- Account signals β
categoryName,isBusinessAccount,isVerified,isPrivate,followerCountfor qualifying leads before you export them. - Five result filters β
hasPhoneOnly,hasEmailOnly,businessOnly,verifiedOnly,minFollowersβ so you only pay for rows that already match your targeting criteria. - Standard Apify export β results land in the Actor's dataset and download as JSON, CSV, Excel, XML, or HTML directly from the Apify Console, or via the Apify API/SDK.
What data can I extract with Instagram Contact Scraper?
Each dataset row can carry up to 31 fields; the dataset's default table view surfaces 29 of them (inputRaw and postShortcode are written to every row but excluded from the default view β open the row as JSON to see them).
| Field | Example value | Use case |
|---|---|---|
type | "contact" | Row kind: contact for an enriched profile, error for a failed target |
inputRaw | "@natgeo" | The exact string you supplied, unmodified |
inputType | "username" | How the input was parsed: username, profileUrl, postUrl, userId, or invalid |
username | "natgeo" | Resolved Instagram handle |
userId | "787132" | Instagram's numeric user ID |
fullName | "National Geographic" | Display name |
profileUrl | "https://www.instagram.com/natgeo" | Canonical profile URL |
postUrl | "https://www.instagram.com/p/C123abcD/" | Populated when the input was a post/reel URL |
postShortcode | "C123abcD" | Shortcode parsed from a post/reel URL |
businessPhone | "+12065551234" | Raw business/contact phone as Instagram returns it |
phoneE164 | "+12065551234" | businessPhone normalized and validated to E.164 |
phoneCountry | "United States" | Country/region resolved from the validated phone |
businessEmail | "press@natgeo.com" | Business/public contact email |
emailDomain | "natgeo.com" | Domain parsed from businessEmail |
externalUrl | "https://on.natgeo.com/instagram" | The profile's single "link in bio" URL field |
categoryName | "Media/News Company" | Business category label |
isBusinessAccount | true | Business/professional account flag |
isVerified | true | Blue-tick verification flag |
isPrivate | false | Private-account flag |
followerCount | 281000000 | Follower count |
biography | "Inspiring the explorer in everyone." | Bio text, scanned for the fields below |
phonesFromBio | ["+442079460000"] | Valid phone numbers extracted from bio + links, E.164-normalized |
emailsFromBio | ["hello@studio.com"] | Emails extracted from bio + links (library/telemetry domains dropped) |
whatsapp | "+12065551234" | Phone parsed from a wa.me / api.whatsapp.com bio link |
linktree | "https://linktr.ee/studio" | Linktree URL detected in bio/links |
bioLinks | [{"title": "Shop", "url": "https://..."}] | All bio links with their display titles |
linkInBioContacts | [{"url": "...", "emails": [], "phones": [], "socials": []}] | One entry per aggregator/destination page that was actually fetched and yielded a contact |
linkInBioNote | "Fetched a JS-rendered link-in-bio page..." | Human-readable explanation when unwrapping ran but found nothing |
pagesScanned | 3 | Number of link-in-bio pages actually fetched with HTTP 200 |
scrapedAt | "2026-07-26T10:00:00Z" | ISO-8601 UTC scrape timestamp |
error | null | Failure reason on type: "error" rows; null on success |
Contact and business signals
The core payoff fields are businessPhone/phoneE164/phoneCountry and businessEmail/emailDomain, sourced directly from Instagram's business_email, business_phone_number, contact_phone_number, and public_phone_number fields. Instagram auth-gates these for logged-out requests on many accounts β see the limitation below β which is why the Actor also runs phonesFromBio, emailsFromBio, whatsapp, and linkInBioContacts as independent recovery paths from the same profile. A lead with phoneE164 set from the authoritative field and a second phone in linkInBioContacts from an unwrapped Linktree page is common and both are kept, not deduplicated against each other.
Targeting and segmentation fields
categoryName, isBusinessAccount, isVerified, and followerCount let you segment a bulk list without opening each profile: filter to verified accounts over a follower threshold, or to business accounts in a specific category, before you ever look at the contact fields. isPrivate flags accounts where Instagram still returns metadata (name, bio, category, follower count) but withholds posts and, in practice, contact fields. inputType tells you which of the five accepted input formats matched, useful for auditing a mixed list of usernames and URLs.
Why not build this yourself?
Instagram's official Graph API is scoped to accounts you or your client own and have connected through Meta's app-review and business-verification process β it does not offer bulk lookup of arbitrary third-party public profiles by username, which is the exact job this Actor does. Building an equivalent in-house means maintaining your own Chrome-TLS-impersonating HTTP client, a rotating residential proxy pool, exponential backoff tuned to Instagram's 401/429 variance, a four-layer HTML parser for when the JSON endpoint is unavailable, and β for the link-in-bio differentiator β a bounded crawler that recognizes dozens of link-aggregator platforms and safely stops at page-count, timeout, and total-time budgets. This Actor ships all of that, plus libphonenumber-validated E.164 phone parsing so raw digit strings (prices, follower counts, years) never get emitted as fake phone numbers.
Build it yourself if you need a bespoke pipeline embedded in your own infrastructure with full control over retry and proxy behavior. Use this Actor if you want a paste-a-list-in, get-contacts-out workflow today, billed only for rows you actually receive.
How to use data extracted from Instagram
Sales and lead-generation teams
Take a list of business-account handles from a niche or hashtag research pass, run it with businessOnly: true and hasPhoneOnly: true, and export username, phoneE164, businessEmail, categoryName, and followerCount straight into a CRM import. Because filtered-out rows are never written to the dataset (and never billed), the output is already your qualified call list, not a raw dump to clean up afterward.
Lead-gen agencies
Running the same enrichment repeatedly for different clients' target niches, an agency can hold minFollowers and verifiedOnly constant per client brief while swapping the profiles list, then diff pagesScanned and linkInBioContacts across runs to show which leads gained a discoverable contact channel since the last pass β a concrete, dated deliverable for a retainer client.
Market research and intelligence
Feed a competitor's follower export or a hashtag-derived account list through with no filters, and use categoryName, isBusinessAccount, and followerCount in aggregate to map category distribution and audience-size bands across a niche, without needing contact data at all β the filters exist precisely so research runs can skip the enrichment cost.
AI agents and automated pipelines
Because input is a flat array of strings and output is one predictable JSON row per profile with null rather than missing keys on unavailable fields, the Actor is straightforward to wrap as a tool call in an agent framework: an agent can pass a batch of handles scraped from another source and receive back a schema-stable contact list to reason over or hand to a CRM-writing tool.
πΌ Input sample
profiles is the only required field; everything else has a default.
| Parameter | Required | Type | Constraints | Description |
|---|---|---|---|---|
profiles | Yes | array (stringList) | β | Usernames, @handles, profile URLs, post/reel URLs, or numeric user IDs. Duplicates removed case-insensitively. |
unwrapLinkInBio | No | boolean | default true | Follow a bio link aggregator + one hop of its destinations and scan for contacts. |
maxLinkInBioPages | No | integer | min 0, max 25, default 5 | Upper bound on pages fetched per profile while unwrapping. |
linkInBioTimeoutSec | No | integer | min 3, max 60, default 15 | Per-page fetch timeout while unwrapping. |
linkInBioTotalBudgetSec | No | integer | min 0, max 300, default 0 | Wall-clock budget for one profile's unwrap. 0 = auto (derived from page count Γ per-page timeout). |
country | No | string (enum, 30 values) | e.g. "United Kingdom (+44)" | Default region used only to parse local (non-+) bio phone numbers into E.164. |
hasPhoneOnly | No | boolean | default false | Emit only profiles with a business, bio, WhatsApp, or link-in-bio phone. |
hasEmailOnly | No | boolean | default false | Emit only profiles with a business, bio, or link-in-bio email. |
businessOnly | No | boolean | default false | Emit only profiles where is_business_account is true. |
verifiedOnly | No | boolean | default false | Emit only verified (blue-tick) profiles. |
minFollowers | No | integer | min 0, default 0 | Emit only profiles with at least this many followers. 0 = no minimum. |
concurrency | No | integer | min 1, max 10, default 2 | Profiles enriched in parallel, each on a fresh proxy IP and TLS client. |
maxRetries | No | integer | min 1, max 10, default 3 | Retries per profile before recording an error row. |
delayMs | No | integer | min 0, max 60000, default 2000 | Base delay for per-profile jitter and retry back-off. |
proxyConfiguration | No | object (proxy editor) | prefill: RESIDENTIAL | Proxy for enrichment and link-in-bio requests. RESIDENTIAL strongly recommended. |
{"profiles": ["nike", "@natgeo", "https://www.instagram.com/p/C123abcD/"],"unwrapLinkInBio": true,"maxLinkInBioPages": 5,"country": "United States (+1)","hasEmailOnly": true,"businessOnly": true,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Common pitfall: the Actor caps every run at 10,000 profiles internally β if you supply more, it logs a warning and silently processes only the first 10,000, so split larger lists across multiple runs rather than assuming everything you pasted was enriched. A second pitfall: setting both hasPhoneOnly and hasEmailOnly to true requires each surviving row to have both a phone and an email, which can filter out otherwise-good leads that only surfaced one contact type β run once with no filters first if you're unsure how many leads you'll actually get.
π½ Output sample
Results are typed, normalized JSON with a stable 31-key schema on every row (missing values are null or an empty array/list, never omitted). Export as JSON, CSV, Excel, XML, or HTML from the Apify Console, or pull the dataset via the Apify API.
{"type": "contact","inputRaw": "@natgeo","inputType": "username","username": "natgeo","userId": "787132","fullName": "National Geographic","profileUrl": "https://www.instagram.com/natgeo","postUrl": null,"postShortcode": null,"businessPhone": null,"phoneE164": null,"phoneCountry": null,"businessEmail": "press@natgeo.com","emailDomain": "natgeo.com","externalUrl": "https://on.natgeo.com/instagram","categoryName": "Media/News Company","isBusinessAccount": true,"isVerified": true,"isPrivate": false,"followerCount": 281000000,"biography": "Inspiring the explorer in everyone.","phonesFromBio": [],"emailsFromBio": [],"whatsapp": null,"linktree": null,"bioLinks": [{ "title": null, "url": "https://on.natgeo.com/instagram" }],"linkInBioContacts": [],"linkInBioNote": null,"pagesScanned": 0,"scrapedAt": "2026-07-26T10:00:00Z","error": null}
How do you filter and target specific contacts?
This Actor is a list enricher, not a discovery tool, so targeting happens on the way out rather than on the way in: every input profile is always fetched, and the five filters decide which resulting rows you receive and pay for. hasPhoneOnly and hasEmailOnly narrow to leads with a usable contact channel, checking the business fields, the bio-parsed fields, and any link-in-bio contacts together β a profile with only a WhatsApp number found on an unwrapped Linktree page still passes hasPhoneOnly. businessOnly and verifiedOnly narrow by account type, and minFollowers sets a follower-count floor. Because non-matching rows are dropped before push_data is called, filtering also controls your bill directly: a stricter filter set means fewer charged row_result events, not just a smaller export.
The unwrapLinkInBio group is a separate, orthogonal set of volume controls for the link-in-bio crawl itself: maxLinkInBioPages bounds total pages fetched per profile (aggregator page plus its one-hop destinations), linkInBioTimeoutSec bounds each individual page fetch, and linkInBioTotalBudgetSec bounds the whole per-profile unwrap β leave it at 0 and the Actor derives a sensible budget from the other two.
{ "profiles": ["nike", "adidas", "under_armour"], "businessOnly": true, "verifiedOnly": true, "minFollowers": 100000 }
{ "profiles": ["local_bakery_nyc", "corner_coffee_co"], "hasPhoneOnly": true, "country": "United States (+1)" }
{ "profiles": ["boutique_studio_x"], "unwrapLinkInBio": true, "maxLinkInBioPages": 10, "linkInBioTotalBudgetSec": 120 }
βΆοΈ Want to try other Instagram scrapers?
| Scraper | What it extracts |
|---|---|
| Instagram Followers Enrichment Scraper | Enriches an Instagram account's follower list |
| LinkedIn Profile Contact Lookup | Contact lookup for LinkedIn profiles, same contact-enrichment pattern on a different platform |
| Facebook Group Insights Scraper | Facebook Groups search and insights |
| Facebook Group Posts & Comments Scraper | Posts, attachments, reaction breakdowns, and comments from public Facebook groups |
| Facebook Profile & Page Photos Scraper | Photos from Facebook profiles and pages |
How to extract Instagram data programmatically
Every run is a standard Apify Actor call: one API call to start the run with your JSON input, then read the resulting dataset β no separate signup or credential exchange beyond your Apify API token.
Python example
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("instagram-profile-contact-enricher").call(run_input={"profiles": ["nike", "@natgeo"],"hasEmailOnly": True,"businessOnly": True,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["username"], item["businessEmail"], item["categoryName"])
Export to spreadsheets or CRM
The dataset's CSV export maps each JSON key directly to a column header β username, phoneE164, businessEmail, categoryName, and followerCount are the columns most CRM imports need; array fields like phonesFromBio and linkInBioContacts flatten to a single delimited cell in CSV, so pull those via the JSON or API export if you need them structured.
Is it legal to scrape Instagram profiles?
Yes β this Actor reads only what a logged-out visitor can already see on a public Instagram profile page; it does not bypass a login wall or access private accounts' posts. Because the output can include personal contact data (an individual's phone number or email, whether from a business profile or a bio), GDPR and CCPA govern how you may store and use it once collected β you need a lawful basis for processing, and bulk storage of personal data for outreach carries real compliance obligations in the EU/UK and California. Consult legal counsel for commercial applications involving bulk storage of personal data.
β Frequently asked questions
What happens if a profile is deleted, renamed, or made private?
A deleted or non-existent username produces a row with type: "error" and error: "Profile not found", and that row is not charged. A profile that still exists but has gone private returns type: "contact" with isPrivate: true and the metadata Instagram still exposes (name, bio, category, follower count); contact fields on private accounts are typically null because Instagram does not surface business contact info for private profiles either.
Can I get link-in-bio contacts along with the core profile data?
Yes, in the same row β unwrapLinkInBio defaults to true, and any contacts found while unwrapping a Linktree/Beacons/Carrd-style page land in linkInBioContacts alongside the authoritative businessPhone/businessEmail and bio-parsed fields on that same record. Set unwrapLinkInBio: false to skip the extra fetches if you only need the core profile fields.
How accurate is the phone and email data?
Every phone in phoneE164, phonesFromBio, whatsapp, and linkInBioContacts has passed libphonenumber's validity check, which rejects follower counts, prices, years, and post IDs that a naive digit regex would emit as false positives. Accuracy of the contact itself (whether it's current and monitored) depends entirely on whether the account owner keeps their public listing up to date β this Actor reports what Instagram or the linked page shows at request time, not a verified-deliverable guarantee. Run a standard email/phone validation pass downstream before using contacts for outbound compliance-sensitive campaigns.
How many profiles can I get per run?
As many as you supply, up to an internal cap of 10,000 profiles per run; beyond that, the Actor logs a warning and processes only the first 10,000. There is no separate pagination step β every profile in your profiles array is queued for enrichment in the same run, subject to concurrency.
What's the actual limitation with business contact fields?
Instagram auth-gates business_email and business_phone_number for logged-out requests on many public business accounts β the account may display a "Contact" button in the app while the public web payload returns null for both fields. This is an Instagram platform limitation, not an Actor bug, which is exactly why phonesFromBio, emailsFromBio, whatsapp, and link-in-bio unwrapping exist as independent recovery paths on the same row.
Does Instagram Contact Scraper work with Claude, ChatGPT, and AI agent frameworks?
It is callable as a standard Apify Actor over HTTP by any agent framework or orchestration tool that can make an authenticated REST call β pass the API token and JSON input, read the dataset back. No dedicated MCP server registration is documented for this specific Actor.
How does it compare to other Instagram contact scrapers?
As observed on the Apify Store on 2026-07-26, khadinakbar/instagram-profile-scraper returns a flatter email/phone pair sourced the same way (business field, else bio parse) plus recent posts and related profiles, but documents no link-in-bio unwrapping. instaprism/instagram-bulk-enricher's listing advertises boolean extractEmails/extractPhones toggles and documented processing-time estimates by volume, but likewise does not document following bio links to a second page for contacts. Instagram Contact Scraper's link-in-bio unwrapping β fetching the aggregator page plus one hop of its destinations β is not documented on either competing listing as of that date.
Can I use Instagram Contact Scraper without an Instagram account or developer credentials?
Yes. You only need an Apify account and API token; the Actor never asks for an Instagram login, session cookie, or Meta developer app. It reads Instagram's public, logged-out profile data through Apify Proxy (RESIDENTIAL recommended, since Instagram blocks most datacenter IPs).
Conclusion
Instagram Contact Scraper turns a plain list of usernames, URLs, or IDs into validated business and bio contact data in one pass, and its link-in-bio unwrapping recovers phones and emails that never show up on the profile itself. It's built for teams that already have their target list and need it enriched with a stable, schema-consistent output rather than re-discovered from scratch. Start a run in the Apify Console with your profiles list, or call it from your own pipeline with the Apify API.