Instagram Profile Scraper - Follower Counts, Bio avatar

Instagram Profile Scraper - Follower Counts, Bio

Pricing

from $0.67 / 1,000 profiles

Go to Apify Store
Instagram Profile Scraper - Follower Counts, Bio

Instagram Profile Scraper - Follower Counts, Bio

Scrape Instagram profiles from handles or profile links. One row per account: bio and bio links, exact follower, following and post counts, verified and private flags, category, published e-mail and phone, and engagement over recent posts. $0.70 per 1,000 profiles.

Pricing

from $0.67 / 1,000 profiles

Rating

1.8

(3)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

3

Bookmarked

1.7K

Total users

152

Monthly active users

16 hours

Issues response

an hour ago

Last modified

Categories

Share

Paste Instagram handles or profile links and get one row per account: the bio, exact follower, following and post counts, the verified and private flags, the business category, and whatever e-mail, phone and links the account publishes. Private accounts come back with their bio, counts and flags, never their posts.

One thing to know before you build on it. The engagement figures are worked out from the recent posts Instagram shows a logged-out visitor, which is 6 to 12 of them at most. That makes them a picture of current form, not a lifetime average, and on some accounts those posts do not come back at all. Every row carries postsAnalysed so you can see which you got.

InputHandles, @handles or instagram.com/... profile links
OutputOne row per profile: bio and bio links, exact counts, verified and private flags, category, published e-mail and phone, engagement over recent posts
Ceiling1,000 profiles per run
SpeedRoughly 4 to 9 profiles a minute, so 100 handles take 11 to 25 minutes
Account neededNone
Price$0.70 per 1,000 profiles on the free plan, down to $0.67 on Business. The free plan's $5 a month covers about 7,000

๐Ÿ” What Instagram Profile Scraper does

You hand it a list of accounts, it hands back a table. nasa, @nasa, instagram.com/nasa and https://www.instagram.com/nasa/ all mean the same thing, so you can mix whatever forms your list already has. Duplicates are dropped before anything is charged.

Counts come back exact, not rounded the way the app prints them: 104,282,031 followers, not "104M". A field that no public page reports for an account comes back null rather than guessed.

Every row also carries two worked-out blocks at no extra cost, engagement and signals, so you can sort a list of accounts without doing the arithmetic yourself.

๐Ÿ“‹ What data you get from each Instagram profile

What you getField
Handle, display name and the numeric account idusername, fullName, id
Bio, and every link in itbiography, externalUrl, externalUrls
Exact follower, following and post countsfollowersCount, followsCount, postsCount
Verified, private, business and creator flagsverified, private, isBusinessAccount, isProfessionalAccount
CategorycategoryName, businessCategoryName
Published business e-mail, phone and addressbusinessEmail, businessPhoneNumber, businessAddress
Every e-mail and phone number found, published or written into the bioemailsFound, phonesFound
Hashtags and @mentions in the biobioHashtags, bioMentions
Profile picture, normal and largeprofilePicUrl, profilePicUrlHD
Accounts Instagram lists as relatedrelatedProfiles
Highlight and video countshighlightReelCount, igtvVideoCount
Average and median likes and comments, engagement rate, posts per week, last post date, top hashtags and mentions, best recent postengagement
Follower tier, follower-to-following ratio, contact route, link count, bio lengthsignals
Account type: personal, creator or businessaccountType
Median views of the recent videos, those views against followers, days since the last videovideoStats
Country, join date (as text and as a timestamp) and former-username count, as a paid extraaccountAbout
The recent posts themselves, when you switch them onlatestPosts
The handle a related profile was found under, when you ask for related profilesrelatedOf

โ–ถ๏ธ How to scrape Instagram profiles

  1. Open Instagram Profile Scraper and click Try for free.
  2. Paste your handles into Instagram usernames or profile URLs, one per line.
  3. Set Maximum profiles while you are testing, since you pay per profile.
  4. Click Start.
  5. Download the dataset as JSON, CSV or Excel, or pull it from the Apify API.

Want to see the row shape first? Clear the list and start it empty. You get one labelled sample row, and it is not charged.

๐Ÿ’ฐ How much does it cost to scrape Instagram profiles?

$0.70 per 1,000 profiles. That is the free plan's price; paid plans pay a little less: $0.69 on Starter, $0.68 on Scale and $0.67 on Business. On the free plan, the $5 Apify gives you each month covers about 7,000 profiles.

The About panel is the one extra: tick Country, join date and former usernames and those profiles cost $5.00 per 1,000 on top. It needs a paid Apify plan. Leave the box alone and you pay the profile price only.

What the run did with a profileCharged
Delivered itas a profile
Read it, and your filters checked it and left it outas a profile, because it was read
Left it out because a value your filters need did not come back, such as a private account's postsno
Read it as a related profile you asked foras a profile, filters included
The same handle twice in your listonce
A handle that does not exist, or one that was not servedno

The sample row and the diagnostic rows cost nothing. To cap what a run can spend, set a maximum cost in its run options (maxTotalChargeUsd in the API). The run stops once it reaches it.

๐Ÿ“ฅ What you give it

{
"usernames": ["nasa", "@gopro", "https://www.instagram.com/natgeo/"],
"maxItems": 50
}
FieldDefaultWhat it is
usernamesnoneOne entry per profile, in any of the forms above. Up to 1,000 per run.
includeAccountAboutfalseAdds country, join date and how many handles the account has used before. Priced separately, and it needs a paid Apify plan.
includeLatestPostsoffAdds the recent posts themselves to each row, with the same field names as our post scraper. They also get their own tab in the output.
maxRelatedProfilesnone, offUp to 50. After your list, also read that many of the accounts Instagram lists as related to it, skipping any already in your list. One step only, never follower lists. Each is charged as a profile.
maxItemsnoneStop after this many profiles, counting from the top. Leave it empty to read the whole list.
minFollowers, maxFollowersnone, offKeep only profiles with at least, or at most, this many followers.
accountTypenone, offKeep only personal, creator or business accounts, or creatorOrBusiness.
minEngagementRatenone, offKeep only profiles whose engagement.engagementRate is at least this. 1 means 1%.
postedWithinDaysnone, offKeep only profiles whose newest recent post is at most this many days old.
bioOrNameContainsnone, offKeep only profiles whose bio or name contains one of these words, in any case.
categoryContainsnone, offKeep only profiles whose category contains one of these words, such as product.
concurrencyempty, runs as 6How many profiles are read at once, 1 to 12. Higher finishes a long list sooner, and 6 keeps the rows most complete.
sessionCookiesnoneOptional. Your own Instagram cookie, used only to retry a handle that could not be read logged out.
proxyUrlsnoneLeave it empty unless you have your own servers you want the traffic to leave through.

A profile your filters check and leave out is charged as a profile, because it was read. The cost section above has the full list.

๐Ÿ“ค What you get back

A real row from a run on 2 October 2026, with the picture links and the bio cut short and the long lists trimmed (relatedProfiles had 49 entries).

{
"ok": true,
"charged": true,
"recordType": "profile",
"inputUrl": "https://www.instagram.com/nasa/",
"id": "528817151",
"username": "nasa",
"url": "https://www.instagram.com/nasa/",
"fullName": "NASA",
"biography": "Making the seemingly impossible, possible. ...",
"externalUrl": "https://www.nasa.gov/",
"externalUrls": [
{"title": "NASA.gov Homepage", "url": "https://www.nasa.gov", "linkType": "external"},
{"title": "MAX POWER", "url": "https://www.nasa.gov/maxpower", "linkType": "external"}
],
"followersCount": 104282031,
"followsCount": 89,
"postsCount": 4940,
"verified": true,
"private": false,
"isBusinessAccount": true,
"isProfessionalAccount": true,
"categoryName": "Government Agencies",
"businessCategoryName": "Government Agencies",
"businessEmail": null,
"businessPhoneNumber": null,
"businessAddress": null,
"profilePicUrl": "https://scontent-iad6-1.cdninstagram.com/v/t51.2885-19/...",
"profilePicUrlHD": "https://scontent-iad6-1.cdninstagram.com/v/t51.2885-19/...",
"highlightReelCount": 6,
"igtvVideoCount": 171,
"hasChannel": false,
"joinedRecently": false,
"pronouns": [],
"relatedProfiles": [
{"id": "36407544", "username": "sciencechannel", "fullName": "Science Channel", "isVerified": true, "isPrivate": false, "profilePicUrl": "https://scontent-iad3-2.cdninstagram.com/v/t51.2885-19/..."}
],
"emailsFound": [],
"phonesFound": [],
"bioHashtags": [],
"bioMentions": [],
"latestPosts": [],
"fbid": "17841401474538262",
"dataSource": "profile-api",
"limitedData": false,
"scrapedAt": "2026-10-02T23:37:45.893Z",
"accountAbout": {"available": false, "country": null, "dateJoined": null, "accountAgeDays": null, "accountAgeYears": null, "formerUsernames": [], "formerUsernameCount": null, "verifiedOnAboutPanel": null},
"engagement": {
"postsAnalysed": 12,
"avgLikes": 278080.25,
"medianLikes": 183589,
"avgComments": 1012.92,
"medianComments": 870.5,
"engagementRate": 0.2676,
"engagementPerPost": 279093.17,
"videoSharePct": 8.3,
"avgCaptionLength": 446.9,
"postsPerWeek": 3.5,
"lastPostAt": "2026-10-02T20:52:45.000Z",
"daysSinceLastPost": 0,
"activeLast30Days": true,
"topHashtags": [{"tag": "nasa", "count": 5}, {"tag": "galaxy", "count": 2}, {"tag": "space", "count": 2}],
"topMentions": [{"tag": "astrokomrade", "count": 3}, {"tag": "iss", "count": 3}, {"tag": "astro_frankrubio", "count": 2}],
"topPost": {"url": "https://www.instagram.com/p/DdWyDLcGiqo/", "shortCode": "DdWyDLcGiqo", "likesCount": 744422, "commentsCount": 1777, "timestamp": "2026-09-16T17:05:45.000Z"}
},
"signals": {"followerTier": "celebrity", "followerToFollowingRatio": 1171708.21, "followsPerPost": 0.02, "hasContactInfo": false, "contactEmailCount": 0, "contactPhoneCount": 0, "externalLinkCount": 5, "bioLength": 44, "hasBioLink": true}
}
FieldHow to read it
idThe numeric account id. It survives a rename, so track it rather than the handle.
followsCountnull on a small share of rows rather than a guess. A re-run usually fills it.
externalUrlsEvery link in the bio when the account uses several. externalUrl is just the first.
profilePicUrlHDThe largest picture on offer. Signed and time limited, so download what you want to keep.
engagement.engagementRateA percentage: average likes plus comments per recent post, against followers. 0.2676 means 0.27%.
engagement.postsAnalysedHow many recent posts the figures rest on. 0 means none came back, and the rest of the block is null rather than zero.
signals.hasContactInfotrue when at least one e-mail or phone number was found. A bio link alone does not count.
accountTypebusiness, creator or personal, from the account's own settings. null when Instagram did not say, as on limitedData rows.
videoStatsOver the videos among the recent posts: recentVideos, videosWithViews, medianVideoViews, viewsToFollowersPct (the median against followers, in percent) and daysSinceLastVideo. View counts come with some answers and not others, so a row can have videos and null views. Everything is null when there are no recent videos.
accountAbout.dateJoinedAtOnly on rows that came back with the paid About panel: the join date as a timestamp, the first of that month, so "August 2013" reads 2013-08-01T00:00:00.000Z.
relatedOfOnly on rows read as related profiles: the handle from your list they were found under.
limitedDatatrue when Instagram served this profile only through its public embed card. The row has the name, followers, post count, picture and recent posts, but no bio, following count, category, links or contact fields.
dataSourceWhich public pages answered for this row. Useful when you want to know why a field is null.
latestPostsOnly with includeLatestPosts on: up to 12 recent posts, each with url, caption, likesCount, commentsCount, timestamp, hashtags, mentions, taggedUsers, coauthorProfiles, locationName, musicTitle, isPinned, likesAndViewCountsDisabled and isCommentsDisabled. A flag Instagram did not send is null, not false.

๐Ÿงพ Reading the output

Three kinds of row land in your dataset, and recordType tells them apart.

RowHow to spot itBilled
A real profilerecordType: "profile", charged: trueyes
The sample rowrecordType: "sample", _sample: trueno
A diagnosticrecordType: "diagnostic", _diagnostic: true, an errorCodeno

Filter on recordType == "profile" and you have your profiles. charged: true marks a real row; read it as that, not as a receipt.

CodeWhat it means
NOT_FOUNDNo public account at that handle any more.
NOT_SERVEDThis profile was not served this run. Re-run it later. Until 12 October 2026 this code was called BLOCKED.
TIME_BUDGETThe run reached its time limit before the end of your list. The profiles it read are in the dataset; raise the timeout or split the list. The run ends as failed only when the time limit stopped it before any profile came back.
STOPPED_EARLYInstagram refused a long run of handles in a row, so the run stopped instead of working through the rest. unreadUsernames lists the handles it never reached.
BAD_INPUTNothing in your list could be read as a handle or a profile link, or a filter value could not be used. Nothing was read.
FILTERED_OUTOne row at the end listing who your filters left out: leftOutUsernames were read and charged as profiles, uncheckedUsernames were not charged.
ABOUT_PLAN_REQUIREDYou ticked the About box on a free Apify plan. Everything else still arrives.
ABOUT_PARTIAL, ABOUT_RATE_LIMITED, ABOUT_UNAVAILABLEThe About lookup stopped part way through the run. The profile rows are unaffected.
PROXY_INPUT_ADJUSTEDA connection setting in your input could not be used and was replaced. The run carried on.
CHARGE_ERRORSome charges could not be recorded, so some rows may have arrived unbilled.
UNEXPECTED_ERRORSomething broke inside the run. It is not charged, and the run still ends normally.

A diagnostic row never fails the run and is never billed.

๐Ÿ’ก What people use it for

  • Shortlisting creators. Drop in a few hundred handles, sort by follower count or category, and open Instagram only for the ones worth it.
  • Weekly tracking. Re-run the same list and diff followersCount and postsCount to see who is growing and who has gone quiet. For up to 15 accounts a run, Instagram Competitor Monitor does the diff for you.
  • Cleaning a list. verified, private and the NOT_FOUND rows tell you which handles are still real accounts.

From a hashtag to a shortlist, in three runs:

  1. Run Instagram Hashtag Scraper on a tag in your niche and copy the ownerUsername column.
  2. Paste those handles here and sort on followersCount.
  3. Put the engagement.topPost.url of each account you kept into Instagram Comments Scraper and read how its audience actually talks.

๐Ÿšง What it does not do

  • No follower or following lists. The counts only.
  • No posts unless you ask. latestPosts is empty unless you turn it on, and even then it covers the recent handful rather than a full history.
  • Nothing behind a private account. A private profile returns its bio, counts and flags. The content stays private, with latestPosts empty and the engagement block null.
  • Some rows come back limited. Now and then Instagram serves a profile only through its public embed card. Those rows carry limitedData: true, are charged like any other row, and a later re-run usually returns the full profile.
  • Country does not show on every account. Instagram puts that line on larger accounts. Smaller ones still return the join date with country null.
  • Former usernames come back as a count, not as names.
  • Entries that are not handles are dropped quietly, so check your list if a row is missing.
  • 1,000 profiles per run, and up to four hours by default. That is enough for a full list even on a slow day. If you set a shorter time limit in the run options, a long list can outlast it, so split the list.
  • It is not an official Instagram tool. Dami's Studio is independent and is not affiliated with or endorsed by Instagram or Meta, or by any other company named on this page.

๐Ÿงญ Which Instagram scraper do you need?

If you wantUse
One row per account from a list of handlesThis one
A profile plus the posts on its gridInstagram Scraper
What changed on up to 15 accounts since your last runInstagram Competitor Monitor
Handles to start from, found under a hashtagInstagram Hashtag Scraper
Comments under a post or reelInstagram Comments Scraper
The same kind of row for TikTok accountsTikTok Profile Scraper
Threads profiles and postsThreads Scraper

โ“ Questions people ask

Do I need an Instagram account to scrape profiles?

No. Profiles are read logged out and that answers almost every handle. The cookie field is there for the rare one that gets refused.

Can it get e-mails and phone numbers from Instagram profiles?

It returns the business e-mail and phone when the account publishes them, plus anything written into the bio text. Personal accounts usually publish neither.

Why do the numbers differ from what I see in the app?

The app rounds big counts and the row does not. Counts also keep moving, so two runs an hour apart disagree slightly on a big account and neither is wrong: compare against the row's scrapedAt. If a field is missing, open the profile in a private browser window. What a logged-out visitor sees there is what this actor can read.

Can I call it from code or connect it to an AI assistant?

Yes. The API tab has ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/instagram-profile-scraper. Either way the run happens on your Apify account at the same price.

This reads public profile pages only, never private accounts or messages. Results can still contain personal data, which GDPR and similar laws cover, so have a reason for collecting it. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.

๐Ÿ†˜ If something breaks

Open the Issues tab on the actor page. Include the handles you used and the run ID, and the log is enough for us to see what happened.