Instagram Scraper API - Profiles, Posts and Reels avatar

Instagram Scraper API - Profiles, Posts and Reels

Pricing

from $0.44 / 1,000 results

Go to Apify Store
Instagram Scraper API - Profiles, Posts and Reels

Instagram Scraper API - Profiles, Posts and Reels

Instagram scraper for profiles, posts and reels. A username gives the profile row plus the posts on its grid; a post or reel link gives that one item. Rows have the caption, likes, comments, views, media links, tagged users and timestamp. $0.45 per 1,000 rows.

Pricing

from $0.44 / 1,000 results

Rating

5.0

(2)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

115

Total users

27

Monthly active users

23 hours

Issues response

4 hours ago

Last modified

Categories

Security

Limited permissions

Share

Instagram scraper for a username or a post link, flat rows back: the account's profile row plus the posts and reels on its public grid, or the one post or reel you linked, with caption, likes, comments, views, media links and tagged people. One row per thing, ready for a sheet.

The part worth knowing up front: a run reads the public grid. On most accounts that is the whole grid. On a few it is smaller than what you see while logged in. On the free Apify plan a profile stops at 12 posts; a paid plan gets the rest, up to about 720.

InputUsernames, profile, post and reel links, accounts whose tagged posts or live stories you want, place links
OutputOne row per profile, post, reel or place: caption, likes, comments, views, media links, post type, length, sound, place, owner, tagged users, timestamp
Ceiling5,000 rows per run, and 12 posts a profile on the free plan
Account neededNone
Price$0.45 per 1,000 rows on the free plan, down to $0.435 on Business. The free plan's $5 a month covers about 11,000

🔍 What Instagram Scraper does

Public accounts are supported, including brands and creators with a business category set. On some business accounts postsCount and isBusinessAccount come back null; the rest of the row is filled in.

A username returns that account's profile row, then its grid in the grid's own order: pinned tiles first, then newest first. Every media row carries isPinned, and skipPinnedPosts drops the pinned ones if you want plain publication order. Reels an account keeps off its grid are a separate set, and includeReelsTabOnly adds them on top of the grid.

A post or reel link returns that one item, whether or not it is still on the grid: one row, billed once. That holds for links with the account name in front (instagram.com/nasa/p/...) and for the instagram.com/share/ links the app's Share button copies. You can mix usernames and links in one run.

Hashtags and mentions are parsed out of the caption for you. Tagged users, collaborators and sponsors come back as their own arrays with ids, names and links.

📋 What data you get from each Instagram profile and post

What you getField
What the row is: a profile, a photo, a video or a carouseltype
Profile: handle, display name, numeric id, linkusername, fullName, id, url
Profile: bio, bio link and picturebiography, externalUrl, profilePicUrl
Profile: follower, following and post countsfollowersCount, followsCount, postsCount
Profile: verified, business and private flagsverified, isBusinessAccount, private
Post: link and shortcodeurl, shortCode
Post: caption, and the hashtags and handles in itcaption, hashtags, mentions
Post: likes, comments and video viewslikesCount, commentsCount, videoViewCount, videoPlayCount
Post: cover image, video file and every carousel framedisplayUrl, videoUrl, images, dimensions, isVideo
Post: who posted it and whenownerUsername, ownerId, timestamp
Post: tagged people, co-authors and sponsorstaggedUsers, coauthorProfiles, coauthorUsernames, sponsorProfiles
Post: paid partnership, hidden likes, comments off, pinnedisPaidPartnership, isSponsored, likesAndViewCountsDisabled, isCommentsDisabled, isPinned
Post: Instagram's alt text for the imageaccessibilityCaption
Post: numeric id, type (reel, photo, video, carousel) and lengthpostId, postType, videoDuration
Post: the poster's name, badge, privacy, picture and countsownerFullName, ownerIsVerified, ownerIsPrivate, ownerProfilePicUrl, ownerFollowersCount, ownerFollowsCount, ownerPostsCount
Post: the place it is tagged atlocationName, locationId, locationLat, locationLng
Post: its soundmusicTitle, musicArtist, audioId, isOriginalAudio
Post: every carousel slide with its own image and video linkcarouselSlides
Profile: category, highlights, new-account flag, every bio linkbusinessCategory, highlightCount, joinedRecently, bioLinks
Profile: Facebook page, Threads, live story, adults-only flagfacebookPageUrl, threadsUrl, hasPublicStory, isAgeRestricted
Profile: business address and related accountsbusinessAddress, relatedProfiles
Tagged posts: the account tagged and howmentionedUsername, mentionTypes, timestampIsApproximate
Place: name, category, address, coordinates, post count, phone, opening statuslocationId, locationName, category, address, city, zip, latitude, longitude, postCount, phone, openingStatus, priceRange
Story (paid plan): one row per story up nowstoryId, ownerUsername, ownerFullName, mediaType, timestamp, expiresAt, displayUrl, videoUrl, videoDuration, url
Comment under a post link (paid plan)id, text, ownerUsername, ownerId, likesCount, repliesCount, timestamp, isReply, parentCommentId, postShortCode, postUrl
Every row: the input it came frominputUrl
Optional add-ons, from 9 November 2026facebookPlayCount, facebookLikesCount, instagramPlayCount, facebookCountsFound, audioUrl, topComments

▶️ How to scrape Instagram posts

  1. Open Instagram Scraper and click Try for free.
  2. Type a handle into Profile usernames, or paste links into Start URLs (profiles or posts).
  3. Set Max results. Start at 50 while you look at the output shape.
  4. Click Start.
  5. Download the dataset as JSON, CSV or Excel, or pull it from the Apify API.

Start it with both lists empty and you get one labelled sample row, which is not charged.

💰 How much does it cost to scrape Instagram posts?

$0.45 per 1,000 rows. That is the free plan's price; paid plans pay a little less: $0.445 on Starter, $0.44 on Scale and $0.435 on Business. On the free plan, the $5 Apify gives you each month covers about 11,000 rows.

Profile, post, place, story and comment rows cost the same. You pay for rows that carry data, so the sample row, diagnostic rows, posts your date or type filter leaves out and duplicates inside a run are not charged. resultsLimit is the ceiling on both the rows and the spend.

The three add-ons start on 9 November 2026 and need a paid Apify plan. Before then a free row says so.

Add-on, from 9 November 2026StarterScaleBusiness
Facebook counts, per 1,000 posts checked$4.94$4.89$4.83
Audio link, per 1,000 posts checked$4.94$4.89$4.83
Comments, per 1,000 comments$0.396$0.391$0.387

📥 What you give it

{
"usernames": ["nasa"],
"onlyPostsNewerThan": "2 weeks",
"resultsLimit": 50
}
FieldDefaultWhat it is
usernamesnoneHandles with or without @. Each returns its profile row plus its grid.
startUrlsnonePaste links instead. A profile link reads that grid; a /p/, /reel/ or /tv/ link reads that one item, with or without the account name in front, and so does a /share/ link from the app. A stories, hashtag or place page gets a free row naming the field that reads it.
mentionsOfnoneAccounts whose Tagged tab you want: public posts by other people that tag or mention them.
placesnonePlace links (instagram.com/explore/locations/...) or place ids. One place row each, then recent posts tagged there on a paid Apify plan.
storiesOfnoneAccounts whose stories are up now, one row per story, on a paid Apify plan. An account with none gets a free row.
commentsAsRowsnoneUp to this many comments under each post link, one row each, on a paid Apify plan.
resultsLimit50Rows across the whole run, profiles and posts together. 1 to 5,000. This is also your spend cap.
resultsPerProfilenonePosts per profile (and per tagged account). 0 returns the profile or place row only and reads no posts.
postTypesallreels, photos or carousels to keep only that kind. A post link you paste always comes back.
onlyPostsNewerThannoneA day (2026-05-01) or a window (7 days, 2 weeks, 1 month); the form gives you a calendar. Days count in UTC, and pinned tiles have to meet the date too. A value that is not a date stops the run with a BAD_INPUT row before anything is read.
skipPinnedPostsoffDrop the tiles pinned to the top of the grid, up to three of them.
includeReelsTabOnlyoffAlso return reels the account keeps off its grid, such as trial reels. It adds them; it does not limit the run to reels.
posterCountsOnLinksoffFill the poster's follower, following and post counts on post links too, at one more profile read per poster. Profile runs fill them anyway.
includeFacebookCountsoffAdd-on from 9 November 2026: Instagram plays, Facebook plays and Facebook likes. Needs a paid Apify plan.
includeAudioLinkoffAdd-on from 9 November 2026: the link to a reel's or video's sound. A link only, nothing is downloaded. Needs a paid Apify plan.
commentsPerPostnoneAdd-on from 9 November 2026: up to 15 of each post's comments on the post row. Needs a paid Apify plan.
sessionCookiesnoneOptional. Your own Instagram cookie, used from the first request so the run sees what your account sees. Treat the value like a password.
proxyConfigurationnoneLeave it alone unless you have your own servers to use.
notionConnector, notionParentIdnoneOptional. Write each row into a Notion database as well as the dataset.

📤 What you get back

A real post row from a run on 30 September 2026, with the image links cut short:

{
"ok": true,
"type": "image",
"shortCode": "Dd4OWyWjFsh",
"url": "https://www.instagram.com/p/Dd4OWyWjFsh/",
"caption": "I spy with my X-ray eyes 👀\n\nUsing @NASAChandraXray, astronomers discovered a new class of \"hypersoft\" objects that give off very low-energy, difficult to detect X-rays. These objects exist in multiple galaxies, including this one, the Pinwheel Galaxy.\n\n#NASA #Space #Galaxy",
"hashtags": ["NASA", "Space", "Galaxy"],
"mentions": ["NASAChandraXray"],
"likesCount": 240993,
"commentsCount": 664,
"videoPlayCount": null,
"videoViewCount": null,
"displayUrl": "https://scontent-iad6-1.cdninstagram.com/v/t51.82787-15/...",
"videoUrl": null,
"images": ["https://scontent-iad6-1.cdninstagram.com/v/t51.82787-15/..."],
"isVideo": false,
"dimensions": {"height": 1441, "width": 1439},
"ownerUsername": "nasa",
"ownerId": "528817151",
"timestamp": "2026-09-29T16:48:08.000Z",
"accessibilityCaption": null,
"taggedUsers": [],
"sponsorProfiles": [],
"coauthorProfiles": [],
"coauthorUsernames": [],
"isPaidPartnership": false,
"isSponsored": false,
"likesAndViewCountsDisabled": false,
"isCommentsDisabled": false,
"isPinned": false
}
FieldHow to read it
shortCodeUnique per post. Use it as your dedupe key across runs.
ownerUsernameOn a collaboration post this can be the other account, with the one you asked for in coauthorUsernames.
videoViewCount, videoPlayCountnull on photos. On a reel the two usually hold the same number.
isSponsoredThe same flag as isPaidPartnership, kept under both names.
displayUrl, videoUrl, imagesSigned and time limited. Download anything you want to keep.
postsCount, isBusinessAccountOn the profile row, null on some business accounts. The rest of the profile row is still there.
postIdText, not a number, so it is never rounded.
locationLat, locationLngThe tagged place's page, not where the photo was taken.
timestamp on tagged postsWorked out from the post id, so it can be a few minutes off; timestampIsApproximate says so.
businessCategory, highlightCount, joinedRecentlynull on some business accounts.

🧾 Reading the output

Three kinds of row can land in your dataset.

RowHow to spot itBilled
A profile, post or reelok: true and a typeyes
The sample row_sample: true, charged: falseno
A diagnosticok: false and an errorCodeno

Filter on ok == true and you have your data. Diagnostic rows carry one of these codes:

CodeWhat it means
NOT_FOUNDInstagram showed the item or account as gone, private or suspended.
NOT_SERVEDThis request was not served this run. Re-run it later. Runs before 13 October 2026 wrote BLOCKED here.
RATE_LIMITED, SERVER_ERROR, NETWORKInstagram was busy or unreachable for that item. Try again in a few minutes.
PARTIALA profile's posts stopped coming part way, or a free-plan run reached its 12 posts a profile. postsDelivered says how many arrived, and only those were charged. A new run starts from the top.
BAD_INPUTAn option had a value it cannot use, so nothing was read. Or a /share/ link was cut short, or a link needs another field.
OPTION_STARTS_SOON, OPTION_OFFAn add-on, stories, comment rows or posts at a place did not run: it needs a paid Apify plan, or it was an add-on asked for before they started on 9 November 2026. The rest of the run went ahead.
NO_RESULTSThe run finished with nothing to return for your input.
TIME_LIMITThe run got close to its time limit and stopped on its own. The results delivered before that are complete and charged. Give the run more time, or ask for fewer results, to get the rest.
UNEXPECTED_ERRORThe run stopped early on an unexpected error. The results before this row are kept.

None of these rows is billed. The run carries on after each one except TIME_LIMIT, which ends it, and even then it still ends as succeeded, with an amber status message.

One quirk of the Overview table: it shows post columns, so a profile row reads as an almost empty line there. Open the row itself or download the JSON and it is all present.

💡 What people use it for

  • Pulling a competitor's recent posts every Monday and diffing the like and comment counts.
  • Checking one post or reel at a time from links a team drops into a channel.
  • Measuring posting cadence: timestamp across a grid tells you how often an account actually posts.

From a grid to what the comments say, in three steps:

  1. Run this on a username with onlyPostsNewerThan set to 30 days.
  2. Sort the rows on commentsCount and copy the url of the posts at the top.
  3. Paste those links into Instagram Comments Scraper and read what people actually said.

🚧 What it does not do

  • No hashtag feeds or keyword search, and only the top comments under a link. Separate actors do those, linked below.
  • No website on place rows, and the phone is empty when the place lists none.
  • A private account returns the profile shell only. Bio, counts and private: true come through. There is nothing public behind it to read.
  • Recent posts, not the full archive. About 720 posts per profile at most, so on a very large account use onlyPostsNewerThan to make the walk purposeful.
  • A signed-out run can see a smaller grid. If a profile shows more in your browser than the run returned, that is the difference.
  • Media links expire. They are signed, short-lived links. Fetch anything you want to keep.
  • Counts are a snapshot at read time, not at publish time.
  • 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
A profile plus the posts on its gridThis one
One row per account, with engagementInstagram Profile Scraper
Posts and reels from links you already haveInstagram Post Scraper
The reels on a profile's reels tab, with play counts and MP4 linksInstagram Reel Scraper
Posts under a hashtagInstagram Hashtag Scraper
Comments under a post or reelInstagram Comments Scraper
Stories a profile has up right nowInstagram Stories Scraper
Followers or following lists of a profileInstagram Followers & Following Scraper

❓ Questions people ask

Do I need an Instagram account to scrape posts?

No. Profiles with their first 12 posts, post links, tagged posts and places are read the way a signed-out visitor sees them. Later posts, stories, comment rows and posts at a place need a paid Apify plan. The cookie field is optional.

Is resultsLimit per username or per run?

Per run, and the profile row counts towards it. Ask for 100 across three handles and you get 100 rows in total, not 300.

Why did I get fewer posts than I asked for?

The account has fewer, your date filter dropped them, the free plan stopped at 12, or the walk hit its 720-post ceiling. If the posts stopped for any other reason, a free PARTIAL row says so.

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

Counts keep moving, and the row holds them as they were when it was read. If posts are 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?

The API tab has code for Python, JavaScript and the CLI. MCP clients like Claude and ChatGPT use https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/instagram-scraper; coding assistants can load our skill file. All three bill your Apify account at the same price.

This reads public profiles, posts and place 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 username or link you used and the run ID, and the log is enough for us to see what happened.