If you are searching for an “Instagram email finder API”, the honest answer is uncomfortable: the private Instagram data that a paid API can return does not include the creator’s email address or phone number. Those fields exist in Instagram’s own business-contact model, but a public-data extraction layer cannot legitimately hand them to you, and this API does not.
What you can get is a stable set of contact signals that are public by design: the bio, the external link, the business or brand category, the declared contact method, and location fields. For most outreach and CRM use cases, that is enough to route a creator correctly — and it is defensible, because you are reading what the creator published. This guide shows exactly which fields you get, with no invented columns.
Read this before you plan the pipeline. GramScraper deliberately filters structured contact fields out of API responses. A response will not contain the profile’s public_email or its phone fields, even when the account has set them, because those datasets are outside the product’s offer. Any guide that promises you an email-address-per-follower API from a public-data provider is describing something that does not exist here.
What the profile endpoint returns
A single call — /v1/user/by/username — is the whole creator-data toolkit. It costs 1 credit and returns the profile object. The contact-relevant fields are:
| Field | What it tells you |
|---|---|
biography | The full bio text. Often contains an email or a DM instruction in plain text — see the extraction section below. |
external_url | The link in the bio. Frequently a Linktree, a media kit, or a brand site — the natural next hop for outreach. |
category_name | The account category (for example a creator or business vertical), when set. |
business_category_name | The business category, when the account is a business account. |
business_contact_method | How the account says it wants to be contacted — for example CALL or UNKNOWN. |
is_business / account_type | Whether this is a business account, and Instagram’s numeric account-type code. is_business is the reliable boolean to branch on. |
city_name, address_street, zip | Business location fields, when the account has published them. |
latitude / longitude | Business map coordinates, when set. |
follower_count / following_count / media_count | Audience size signals, used to prioritise. See the followers API page for tracking those over time. |
is_verified | Verification status. |
Profile routes available for this: /v1/user/by/username, /v2/user/by/username, /v1/user/by/id, /v1/user/by/url, plus the richer /gql/user/web_profile_info and /gql/user/about. The v2 and GraphQL variants also expose bio_links, Instagram’s multi-link feature, which can hold more than the single external_url.
Worked example: a real business account
Fetching a well-known business account shows the shape of the data. This is a real response body, trimmed to the contact-relevant keys:
curl -s -H "Authorization: Bearer gs_your_key" \
"https://gramscraper.com/api/instagram/v1/user/by/username?username=nike"{
"pk": 13460080,
"username": "nike",
"full_name": "Nike",
"biography": "Just Do It.",
"external_url": "http://empli.fi/nike",
"is_business": true,
"account_type": 2,
"business_contact_method": "CALL",
"category_name": null,
"business_category_name": null,
"address_street": "One Bowerman Dr",
"city_name": "Beaverton, Oregon",
"zip": "97005",
"latitude": 45.5076448,
"longitude": -122.8269159,
"public_phone_country_code": "",
"follower_count": 291166543,
"following_count": 266,
"media_count": 1667,
"is_verified": true
}Read that response carefully and the honest picture is right there. You get the bio, the bio link, the declared contact method, the category slots, and a full business address with coordinates. You do not get a public_email, and the phone-number fields that would carry a business number are absent. public_phone_country_code exists as an (empty) country-code slot but arrives without its number, so treat it as unusable.
Category fields are often null even on large verified accounts, as nike shows. Never treat category_name as guaranteed — design your logic to fall back to biography and external_url.
Node.js
const BASE = "https://gramscraper.com/api/instagram";
const KEY = process.env.GRAMSCRAPER_API_KEY;
async function creatorRecord(username) {
const url = new URL(`${BASE}/v1/user/by/username`);
url.searchParams.set("username", username);
const res = await fetch(url, { headers: { Authorization: `Bearer ${KEY}` } });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const p = await res.json();
return {
username: p.username,
full_name: p.full_name,
followers: p.follower_count,
verified: p.is_verified,
is_business: p.is_business,
bio: p.biography || "",
link: p.external_url || null,
category: p.category_name || p.business_category_name || null,
contact_method: p.business_contact_method || null,
city: p.city_name || null,
// Record what you actually got, so nothing silently becomes a fact.
has_email_field: false,
};
}
console.log(await creatorRecord("natgeo"));Python
import os, re, requests
BASE = "https://gramscraper.com/api/instagram"
HEADERS = {"Authorization": f"Bearer {os.environ['GRAMSCRAPER_API_KEY']}"}
def creator_record(username):
r = requests.get(
f"{BASE}/v1/user/by/username",
headers=HEADERS,
params={"username": username},
)
r.raise_for_status()
p = r.json()
return {
"username": p.get("username"),
"full_name": p.get("full_name"),
"followers": p.get("follower_count"),
"verified": p.get("is_verified"),
"is_business": p.get("is_business"),
"bio": p.get("biography") or "",
"link": p.get("external_url"),
"category": p.get("category_name") or p.get("business_category_name"),
"contact_method": p.get("business_contact_method"),
"city": p.get("city_name"),
}
print(creator_record("natgeo"))Extracting a work email from the bio — the legitimate path
Creators who want inbound mail usually publish it themselves. Your job is to read what they chose to publish, not to guess a private address. Parse the bio and the bio link:
import re
EMAIL_RE = re.compile(r"[\w.+-]+@[\w-]+\.[\w.-]+")
URL_RE = re.compile(r"https?://\S+|[\w-]+\.(?:com|co|io|net|link)/\S*")
def contact_signals(profile):
bio = profile.get("bio") or ""
signals = {
"emails": EMAIL_RE.findall(bio),
"links": URL_RE.findall(bio.replace("\n", " ")),
"dm_instruction": bool(re.search(r"\bdm\b|direct message", bio, re.I)),
"external_url": profile.get("link"),
}
# The bio link is a first-class signal even when the bio has no address.
return signalsTwo practical rules. First, only treat an address found in the bio as usable when it is clearly published for business contact — a “for collabs: [email protected]” is a standing invitation, whereas a personal address appearing incidentally is not. Second, always follow external_url: for creators represented by an agency, that link is usually the fastest correct route, and mail sent to an agency gets answered faster than a cold DM.
Following the link one hop
A media kit or Linktree page is a normal web page. Fetch it yourself and look for a contact route. That is ordinary web scraping of a page the creator published for exactly this purpose — not a bypass of Instagram’s contact model — and it is where most of your real coverage will come from.
What people build with this
Influencer outreach lists
Filter a candidate list by follower_count band, is_verified, and category, then pull external_url as the outreach destination. A CRM row becomes: handle, name, size, category, city, contact route.
CRM enrichment
You already have a creator in your CRM; you want to know whether they have since added a business category, changed their bio link, or moved city. Re-run the lookup and diff. At 1 credit each, refreshing 500 creators is 500 credits.
Market mapping
Pull the same fields across a niche — for example 200 accounts in a category — and aggregate on category and city to see how a market is distributed. This uses only fields that reliably exist, so the output is not full of empty columns.
Honest limitations
- No email, no phone. Structured contact fields are filtered from responses by design. There is no flag or plan that re-enables them here.
- No follower or following lists. This API returns the follower count, not the list of individual followers. That is covered on the followers API page and in the followers export guide.
- Category is frequently null. As the real example above shows, do not depend on it.
- Location fields are business fields. They exist for business accounts that published them; a personal creator account will usually have none.
- Bio text is unstructured. A regex finds what looks like an address; it cannot tell you whether the address is current, personal, or intended for you.
- Private accounts return nothing. And collecting personal data carries legal duties. Have a lawful basis, honour opt-outs, and follow the platform’s terms.
Get 100 free API credits
Run a real creator through the profile endpoint and confirm the field set against your requirement before you build. Starter is $9 for 10,000 non-expiring credits.
Create a free account →