How to Scrape Emails & Leads From Instagram (2026)
- A public Instagram email lives in two places: the
business_emailfield a professional account exposes through its contact button, and the bio text where many creators type an address to dodge naive scrapers. Personal private accounts expose neither. - The official Instagram Graph API never returns other users' email addresses, and it dropped even its own
email_contactsinsight on January 8, 2025. Reading the public profile is the only route to a public address. - A plain
requestscall returns HTTP 429.curl_cffiwithimpersonate="chrome"reads the profile JSON, includingbusiness_email,business_phone_number, andexternal_url. At volume the 429 returns, so a scraper API handles the proxies and retries. - Public contact data is defensible to collect after Meta v. Bright Data, but contacting people puts you under GDPR in the EU and CAN-SPAM in the US, where a single non-compliant email can cost up to $53,088.
I pointed a scraper at a list of business and creator profiles to pull their public emails, and the first lesson was that most of the addresses are not where people expect. A share of them sat in the business_email field that professional accounts expose through a contact button. The rest were typed into bio text, hidden in a link-in-bio page, or not public at all.
That gap is what this guide on how to scrape emails from Instagram is built around. Below is what I ran in July 2026 to turn a list of handles into public contact records: where the email actually lives, the Python that reads it, the block you hit at volume, and the managed route that skips the proxy work. The last section covers the part most tutorials leave out, which is what you are allowed to do with the addresses once you have them.
What emails can you actually scrape from Instagram?
The emails you can actually scrape from Instagram are the public contact addresses a professional account chooses to show, plus any address a user typed into a public bio. There is no hidden inbox to pull and no way to read a private account, so the field of play is narrow and entirely public.
Two sources cover almost every real hit:
- The
business_emailcontact field. A Business or Creator account can add an email, phone, and address behind a contact button, and Instagram returns that email in the profile JSON to a logged-out request. This is the cleanest source and the one that defines an Instagram email scraper. - The bio text. Many creators skip the contact button and paste an address like
hello@brand.comstraight into thebiographystring, often to dodge tools that only read the structured field. A regular expression over the bio recovers these.
Two more fields round out a lead even when the email is thin: the external_url website link and the account category, both public on professional accounts. What you cannot get is anything gated: private accounts return nothing, and a large brand’s contact block is sometimes withheld from logged-out responses even when the account is public. Before writing a line of code, it helps to know why the official Instagram API is not the tool that hands you any of this.
Why won’t the Instagram API give you emails?
The Instagram API will not give you other people’s emails because the official Graph API only reads accounts you manage, and it dropped even the one email-shaped metric it used to carry. There is no endpoint in the official platform that takes an arbitrary username and returns that person’s contact address.
Two changes closed the door for good. Meta deprecated the read-only Instagram Basic Display API on December 4, 2024, which removed the last public path for personal accounts. Then, with Graph API version 21 on January 8, 2025, Meta deprecated the email_contacts metric along with profile_views and website_clicks. That metric never returned addresses anyway - it counted how many times someone tapped the email button on your own account, an insight number, not a contact list.
So the only route to a public email is reading the public profile page, which is exactly what every email tool does under the hood. That route runs straight into Instagram’s block: a plain request from a datacenter IP returns a login wall or an HTTP 429 before you finish a short list, because Meta rate-limits and challenges automated traffic from cloud ranges. Clearing that block starts with having a list of profiles to read, so the first practical step is building one.
How do you build a list of Instagram profiles to scrape for emails?
You build a list of Instagram profiles to scrape for emails by starting from a niche signal - a hashtag, a keyword, a competitor’s audience - and resolving it into handles you can then read one by one. The list is the input to the extraction step, and how you gather it decides how much of it is reachable logged out.
Three methods cover most outbound work, and they differ in whether Instagram gates them behind a login.
From a hashtag or keyword search
The most reachable method is a hashtag or keyword search, because hashtag pages surface public posts and their authors without a session. You read a tag like #realtor or a keyword that matches business bios, collect the handles that appear, then read each profile’s contact fields. This is the cleanest logged-out path to a fresh list in a specific niche.
From an account’s followers or following
Pulling an account’s followers or following gives you a tightly targeted audience, but the follower list is login-gated. Instagram serves follower rosters only through app endpoints that expect a logged-in session, so a logged-out request hits a login or checkpoint wall. You can still resolve the handles once you have the list, but gathering the roster itself is the step Instagram throttles first.
From the people who liked or commented on a post
The people who liked or commented on a post are a warm, intent-rich list, and comments carry the same gate as follower rosters. Comment threads come from a GraphQL query that needs a rotating doc_id and, in practice, a session for depth. Likers are gated harder still. Treat this method as higher-effort than a hashtag pull, and lean on it when the engagement signal is worth the extra work.
However you assemble the handles, the payoff step is the same: read each profile and pull the contact fields out of its JSON. That is where the Python comes in.
How do you scrape an email from an Instagram profile with Python?
You scrape an email from an Instagram profile with Python by requesting the web_profile_info endpoint through a client that matches a real browser’s TLS fingerprint, then reading the contact fields off the JSON. A plain requests.get returns HTTP 429 with an empty body before it serves anything, because Instagram refuses Python’s default TLS signature at the handshake. The fix is curl_cffi, a curl binding that can impersonate Chrome’s exact fingerprint.
Install it with pip3 install curl_cffi, then request the profile and pull the email two ways - the structured contact field first, the bio text as a fallback:
import re
from curl_cffi import requests as creq
USERNAME = "natgeo"
url = f"https://www.instagram.com/api/v1/users/web_profile_info/?username={USERNAME}"
headers = {"x-ig-app-id": "936619743392459"} # the public web app id
r = creq.get(url, headers=headers, impersonate="chrome", timeout=20)
r.raise_for_status()
user = r.json()["data"]["user"]
# 1. The contact-button fields, set on professional accounts
email = user.get("business_email")
phone = user.get("business_phone_number")
website = user.get("external_url")
# 2. Fallback: many creators type the address into the bio instead
if not email:
match = re.search(r"[\w.+-]+@[\w-]+\.[\w.-]+", user.get("biography", ""))
email = match.group(0) if match else None
print(USERNAME, "|", email, "|", phone, "|", website)
When I ran this in July 2026, curl_cffi with impersonate="chrome" returned 200 and the full profile JSON, while the identical request through requests returned the 429. The business_email and business_phone_number fields were present in the schema for the professional accounts I checked, populated on some and blank on others, and the regex recovered a handful of addresses that lived only in the bio. I dig into the fingerprint problem, the rotating doc_id, and the other Python routes in my guide on how to scrape Instagram with Python.
The catch is the ceiling. The fingerprint trick clears the handshake, but it does not raise the rate limit - anonymous access is capped near 200 requests per hour per IP, and after a run of calls from one address the 429 comes back regardless of curl_cffi. For a few dozen profiles that is fine. For an outbound list of thousands, you need residential IPs, sticky sessions, and retry logic, which is where the managed route earns its cost.
How do you scrape Instagram emails at scale without getting blocked?
You scrape Instagram emails at scale by sending each handle to a scraper API that handles the TLS fingerprint, residential proxy rotation, and 429 retries on its own servers, then returns the contact fields as parsed JSON. This removes the part of the Python route that breaks at volume: you stop buying proxies and babysitting fingerprints, and you get an email, phone, and website back per profile from one authenticated call.
I use ChocoData for this, which reads the same public contact block the web_profile_info endpoint carries and returns it as clean JSON. A single profile is one GET request with your API key:
curl "https://chocodata.com/api/v1/instagram/profile?username=natgeo&api_key=$CHOCO_API_KEY"
The Python version is the same shape, so it loops a username list straight into a CRM or a CSV without a proxy pool on your side:
import csv, os, requests
handles = ["natgeo", "nasa", "spacex"]
rows = []
for handle in handles:
resp = requests.get(
"https://chocodata.com/api/v1/instagram/profile",
params={"username": handle, "api_key": os.environ["CHOCO_API_KEY"]},
timeout=30,
)
p = resp.json()
rows.append([p.get("username"), p.get("email"), p.get("phone"), p.get("website")])
with open("ig_leads.csv", "w", newline="") as f:
w = csv.writer(f)
w.writerow(["username", "email", "phone", "website"])
w.writerows(rows)
This returned the same contact fields the hidden endpoint would, without a fingerprint library, a residential proxy, or a login on my side. Median end-to-end response was about 2.6 seconds per profile including proxy routing, anti-bot handling, retries, and parsing. The honest limits still apply: some large accounts withhold their contact block even to a managed fetch, so no tool hits 100 percent. ChocoData’s free tier covers 1,000 requests before you commit, and paid usage works out to roughly $0.60 per 1,000 profiles, billed only on successful requests. If you would rather compare managed tools head to head before you pick one, I rank them in my best Instagram scrapers in 2026 roundup.
A clean list is only half the job. Once you hold real people’s addresses, the rules on what you may do with them decide whether the outreach is worth the risk.
Is it legal to scrape emails from Instagram?
Scraping public Instagram emails sits on defensible ground, but contacting the people behind them is governed by privacy and anti-spam law, and that second half is where the real exposure lives. Collecting a public address and sending an unlawful email are two separate acts with two separate rules.
On the collection side, a US court held in Meta v. Bright Data in January 2024 that scraping public, logged-out data does not breach Meta’s terms, since a logged-out scraper never agrees to them. That covers public data only. Meta’s Platform Terms still bar collecting data by automated means without permission, and anything behind the login wall is off the table, so the public-versus-private line is the one that matters. I walk through what that ruling does and does not cover in my guide on whether scraping Instagram is legal.
On the contact side, a scraped email is personal data. Under the EU’s GDPR you become the data controller the moment you store it, which means you need a lawful basis and must honor an opt-out. In the US, every commercial email must follow the FTC’s CAN-SPAM rules: accurate headers, a truthful subject line, and a working unsubscribe, with civil penalties reaching $53,088 per non-compliant message after the FTC’s 2025 inflation adjustment. Two habits keep a scraped list safe to use - verify every address before you send, because a raw scrape always carries dead and role-based inboxes that burn your sending reputation, and collect only the public fields you actually need. None of this is legal advice, so take your own for your use case before you run outreach at scale.
FAQ
Do you need to log in to scrape emails from Instagram?
No, the public contact fields on a professional account are readable logged out. The business_email, business_phone_number, and external_url fields sit in the same web_profile_info response as the follower count, and a logged-out request returns them for public accounts that set them. You only hit a login wall when you try to page an account's follower list or a post's comments, which Instagram serves through app endpoints that require a session. So a bio-and-contact-button email scrape needs no login, but building your target list from followers or commenters does.
How do you scrape Instagram emails in bulk from a list of usernames?
You loop a list of handles through the profile endpoint and read the contact fields off each response. In Python that is a for loop over your usernames that calls web_profile_info (or a scraper API) once per handle and appends business_email, business_phone_number, and any address parsed from the bio to a list, then writes the rows to CSV. The only limits are the rate ceiling on the DIY route and, on a managed API, your request budget. Deduplicate the handles first so you do not pay twice for the same profile.
Can you scrape email addresses from private Instagram accounts?
No, a private Instagram account exposes no email, phone, bio, or posts to a logged-out request, so there is nothing public to scrape. The contact fields only exist on public professional accounts that switched on a contact button, or in the public bio of an open account. Trying to reach a private account's data means logging in and following it, which ties the collection to an account Instagram can challenge and is a different legal question from public scraping.
Why do some Instagram business profiles return no email?
Some business profiles return no email because the owner never filled the contact field, put the address in a link-in-bio page instead of the bio text, or belongs to a large brand whose contact data Instagram withholds from logged-out responses. In my runs the business_email field was present in the schema but empty for a share of accounts, and a regex over the biography text recovered some of the missing ones. A profile with a blank contact field and no address in its bio simply has no public email to collect.