Instagram Scraper - Profiles, Posts and Reels avatar

Instagram Scraper - Profiles, Posts and Reels

Pricing

from $0.44 / 1,000 results

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

Instagram Scraper - Profiles, Posts and Reels

Scrape Instagram 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

89

Total users

30

Monthly active users

23 hours

Issues response

a day ago

Last modified

Categories

Share

Give it an Instagram username or a post link and get 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 signed-out run sees the grid Instagram serves a visitor. On most accounts that is the whole grid. On a few it is smaller than what you see while logged in. One profile's walk also stops after 60 pages of 12 posts, about 720, so a very large account does not come back complete in one run.

InputUsernames, or profile, post and reel links
OutputOne row per profile, post or reel: caption, likes, comments, views, media links, owner, tagged users, timestamp
Ceiling5,000 rows per run
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. 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. Rows are deduplicated inside a run, so nothing is returned or billed twice.

πŸ“‹ 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

▢️ 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.

A profile row and a post row cost the same. You pay for rows that carry data, so the sample row, diagnostic rows, posts dropped by your date filter and duplicates inside a run are not charged. resultsLimit is the ceiling on both the rows and the spend.

πŸ“₯ 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.
resultsLimit50Rows across the whole run, profiles and posts together. 1 to 5,000. This is also your spend cap.
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.
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, because Instagram sends one count for plays and views.
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.

🧾 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. Until 12 October 2026 this code was called BLOCKED.
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. postsDelivered says how many arrived, and only those were charged. A new run starts from the top.
BAD_INPUTonlyPostsNewerThan was not a date. Nothing was read.
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.

After any of these except TIME_LIMIT, which ends the run, the run carries on to the next item. None of these rows is billed, and only one case fails the run: when the time limit stopped it before any result came back, the run ends as failed, with a TIME_LIMIT row saying so.

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 comments or stories. Those are separate actors, linked below.
  • 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

❓ Questions people ask

Do I need an Instagram account to scrape posts?

No. Everything above works signed out. 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, or the walk reached 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?

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-scraper. Either way the run happens on your Apify account at the same price.

This reads public profiles and public posts 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.