Instagram Scraper - Profiles, Posts, Reels, Hashtags, Places
Pricing
from $3.50 / 1,000 profiles
Instagram Scraper - Profiles, Posts, Reels, Hashtags, Places
Gets 200 posts per account past Instagram's 12-post limit: 200 unique posts in 4 requests, zero repeats. Scrape Instagram profile data and Instagram reel play counts with no login. An empty run names one of 10 reasons instead of a silent empty table.
Pricing
from $3.50 / 1,000 profiles
Rating
0.0
(0)
Developer
Snow Leo Data
Maintained by CommunityActor stats
0
Bookmarked
7
Total users
3
Monthly active users
7 days ago
Last modified
Categories
Share
Instagram Scraper — profiles, posts, reels, hashtags and places
Public Instagram data without a login, without cookies and without a browser. One table holds all four kinds of row: profiles, posts and reels, hashtags and places.
The point of this actor is the post walk. Instagram's own page stops at 12 posts per account for a logged-out visitor. This actor keeps going through the same feed query the site itself uses: 50 posts per request, cursor after cursor. Measured on 2026-09-17 on @nasa: 200 unique posts over 4 requests, zero repeats, reaching from 2026-09-16 back to 2026-04-10.
What you get
Profile — username, user id, full name, biography, followers, following, post count, verified, private, memorialised, profile picture, every bio link with its title, external URL, pronouns, account badges, Threads username, highlight count, whether the account has reels.
Post / reel — shortcode, post id, type (photo, video, carousel, reel), product type, date, likes, comments, plays, caption, hashtags, mentions, owner username, owner id, owner full name, owner verified, image URL, video URL, width, height, carousel item count and every carousel image, tagged users, co-authors, paid-partnership flag, comments-disabled flag, alt text, reel music title and artist, Instagram's topic pills, place name and coordinates.
Hashtag — the tag, its volume when Instagram states it, Instagram's own description of the tag, related keywords, plus the 12 posts of that page.
Place — id, name, latitude, longitude, plus the 18 posts of that page, each with likes, comments and dates.
What Instagram does not give a logged-out visitor
Written plainly, because you will hit these and should know beforehand:
- Comments. No comment text is served without a login.
- Followers and following lists. Only the counts.
- Business category, contact e-mail and phone. Not in the logged-out page.
- Stories and highlights content. Only the highlight count.
- Hashtag coverage is partial. Instagram serves its logged-out hashtag
page for some tags and the login wall for others: of 5 tags tried on
2026-09-17, 2 (
travel,nature) returned 12 posts each and 3 (nasa,food,photography) returned the login wall. Closed tags are named in the run report; they do not fail the run. Tag pages also cannot be paged: the pagination query answers with null to a logged-out caller. - Hashtag volume is often missing.
travelreports 3.9B,naturereports nothing at all. An absent number isnull, never a guess. - Place pages stop at 18 posts. Their pagination query answers 401.
- Play counts exist only for reels on the account's reels tab (up to 12 per account, switch on Add play counts for recent reels). Feed posts and post pages carry no view count at all.
- Private and withheld accounts. Instagram answers with an error shell; the run report names the account and the reason instead of guessing.
How much of it costs what
| Row kind | How it is fetched | Wire traffic |
|---|---|---|
| Profile | one page | 136–164 KB (141 KB typical) |
| Post / reel from an account | GraphQL feed, 50 per call | 4.6 KB per post |
| Hashtag + its 12 posts | one page | 157 KB |
| Place + its 18 posts | one page | 333 KB |
| Post opened for place, music, photo tags | one page per post | 149 KB |
Pages are requested with gzip, which is why a profile page costs 141 KB instead of the 702 KB it weighs unpacked.
Watch mode
onlyNew remembers what earlier runs delivered and returns only what is new
or changed, each row marked NEW or UPDATED in change_type. Signed CDN
URLs change on every view, so they are deliberately left out of the change
fingerprint — otherwise every post would look updated every morning and you
would pay for the whole table again. A run that finds nothing new returns an
empty dataset and says nothing-changed in the report.
Filters
minLikes, minComments, minFollowers, postedAfter, postedBefore,
captionContains, postTypes. Two rules worth knowing:
- Filters run before billing, so rows they remove are not charged.
- A post whose owner hides like counts arrives with
likes: nulland is kept byminLikes— missing data is not a mismatch. The single exception iscaptionContains: a post with no caption cannot contain your phrase, so it is dropped. postedAfteralso stops the crawl, because the feed runs newest first. That is traffic you do not buy, not just rows you do not see.
maxItems caps the rows written to the dataset and never the crawl: with
filters on, the crawl deliberately goes deeper so that a filtered run does not
hand you an empty table.
An empty dataset always says why
no-input, nothing-requested, date-range-inverted,
follower-filter-without-profiles, charge-limit-reached, nothing-changed,
filtered-out, targets-not-available, nothing-collected,
source-returned-nothing — one of these lands in empty_reason in the run
report, and in the log as a warning. The first four are decided by your input
alone and stop the run before a single request is made.
Proxy
Instagram blocks Apify's cloud addresses by name: measured 2026-09-17, a direct profile request from the cloud returns 200 and a 499 KB page with not one field in it, while the same page through a residential address returns the real data. The proxy input is therefore preset to residential, and you can change it like in any Apify actor. The run report tells you how many requests were made and how many bytes they cost.
Output
One flat table with a result_type column (profile, post, hashtag,
location). compactOutput trims it to 18 columns for AI agents and
spreadsheets; excludeEmptyFields drops nulls, empty lists and false values.
The run report (REPORT in the key-value store) carries rows per kind, what
each filter removed, which targets Instagram refused, the traffic bought and
empty_reason.
What buyers of the big Instagram actors are asking for
Read on 2026-09-17 off the public issue boards of the seven largest Instagram actors on Apify — 156 open and closed tickets from people who already pay. Below is what they ask for and where this actor stands. Nothing here is a promise about their software; it is what their own buyers wrote.
| What the tickets say | Here |
|---|---|
| "Post count came as empty for some accounts which actually do have posts", "Not retrieving count of posts for some instagram pages" — 2 tickets | posts_count is read out of the og:description line, because the page JSON carries all_media_count: null on every account measured |
| "Number of posts downloaded exceeds 12", "Returns only a few posts", "Detailed mode — not all posts returned", "Not retrieving all posts from date" — 4 tickets | 50 posts per feed call, cursor after cursor: 200 unique posts over 4 requests, zero repeats (measured 2026-09-17 on @nasa), up to 5000 per account |
| "videoPlayCount is null", "No views returned", "I do not see any Number of Views data", "Add videoPlayCount to the latest posts output" and nine more — 15 tickets | plays comes from the reels tab, the one logged-out surface that carries play_count. Switch: Add play counts for recent reels. Honest limit: Instagram lists about 12 reels there per account, and feed posts carry no view count at all |
| "Run marked as Succeeded but returns empty latestPosts", "empty successful datasets", "Common transient no items" — 7 tickets | an empty dataset always carries one of 10 named reasons in empty_reason; four of them stop the run before the first request |
| "restricted_page conflates three different situations — two of them carry no distinguishing field" | every target Instagram refused is listed in the run report by name and reason, and does not fail the run |
"Usernames containing .com resolve to a different account's profile (greedy .com stripping)" | nike.com stays nike.com; only @, slashes and the query string are stripped |
| "Duplicated rows! The account has 68k followers, you extracted 118k" | the post walk is cursor-based and de-duplicated by shortcode: zero repeats in the 200-post measurement |
| "Expose coauthor_producers so Instagram collaboration posts are detectable" | coauthors ships on every post row |
| "paidPartnership is not returned" | is_paid_partnership ships on every post row |
| "Add profile picture (favicon/avatar) to the response" | profile_pic_url ships on every profile row |
| "Date filtered results unexpected", "Not retrieving all posts from date" — 3 tickets | postedAfter and postedBefore filter before billing, and postedAfter also stops the crawl, since the feed runs newest first |
| "Add maxRequestRetries / per-profile timeout — one blocked profile gates the whole run" | a profile that fails is reported and skipped; the run continues. The per-request retry count is fixed at 3 and is not an input yet |
| "Business address not returned for business accounts that display address on profile", "Not showing mobile number and email" — 3 tickets | not closed, and not promised: the logged-out business profile page carries no address, phone or e-mail (checked on @gopro) |
| "Mentions limited to 21 results", "Prefiltering Comments", "Instagram Search Scraper blocked" | not closed: mentions, comment text and keyword search are all behind the login wall |
Defaults
Running with the preset input returns the @nasa profile row and its 12 most
recent posts. maxItems defaults to 50 so a trial run stays cheap;
postsPerProfile defaults to 12 and goes up to 5000.
