Instagram Post Scraper avatar

Instagram Post Scraper

Pricing

from $0.17 / 1,000 instagram posts

Go to Apify Store
Instagram Post Scraper

Instagram Post Scraper

Instagram post scraper API for posts and reels from links or shortcodes. One row per post: caption, likes, comments, publish time, the media (every carousel image and video URL), owner, hashtags, mentions, tagged users, location and music. $0.18 per 1,000 posts, less on paid plans.

Pricing

from $0.17 / 1,000 instagram posts

Rating

5.0

(1)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

87

Total users

41

Monthly active users

a day ago

Last modified

Categories

Features

Limited permissions

Share

Instagram post scraper for post, reel or IGTV links, one row per post: the full caption, like and comment counts, the exact publish time, every image and video URL including all the frames of a carousel, the owner, the hashtags, the mentions and the tagged users. Bare shortcodes, numeric post ids and links from the app's Share button work too, so a messy list is fine.

Two things are missing on purpose, and it is better to know now: there is no comment text, and videoViewCount is usually null, because Instagram does not publish the play count to a logged-out reader. Likes and comments are there on both posts and reels.

InputPost, reel or IGTV links, share links, bare shortcodes or numeric post ids
OutputOne row per post: caption, likes, comments, publish time, every image and video URL, owner, hashtags, mentions, tagged users, location and its coordinates, music, the sound's id
Ceiling5,000 links per run
Account neededNone
Price$0.18 per 1,000 posts on the free plan, down to $0.174 on Business. The free plan's $5 a month covers about 27,000. Optional plays, shares and Facebook counts, paid plans only: $1.38 per 1,000 posts checked on Starter, down to $1.34 on Business; from 16 November 2026, $4.94 on Starter, down to $4.83 on Business

🔍 What Instagram Post Scraper does

You give it links, it gives you rows. instagram.com/p/<code>/, /reel/<code>/, /tv/<code>/, a link copied from a profile grid or the Share button, the numeric post id, or just DbtErSrlB2J on its own. Mix them freely in one run.

Carousels come back whole: images and videos hold every frame in order, and childPosts has one object per frame with its own shortcode and size. A reel fills in videoUrl and videoDuration.

Duplicate links are removed before anything is charged, including the same post supplied once as a URL and once as a bare code. A link that is dead, deleted or withheld comes back as a free labelled row rather than a charge. A run the platform restarts never charges a post twice.

📋 What data you get from each Instagram post

What you getField
Link, shortcode and numeric idurl, shortCode, id
What kind of post it istype, productType, isReel
Caption, and the hashtags and handles in itcaption, hashtags, mentions
Likes and commentslikesCount, commentsCount
Video views and lengthvideoViewCount, videoDuration
Publish timetimestamp
Cover, video file and every carousel framedisplayUrl, videoUrl, images, videos, childPosts, childPostsCount
Size and alt textdimensionsWidth, dimensionsHeight, alt
The account that posted itownerUsername, ownerFullName, ownerId, ownerIsVerified, ownerIsPrivate, ownerProfilePicUrl, ownerProfileUrl
Tagged people, co-authors and sponsorstaggedUsers, coauthorProfiles, coauthorProducers, sponsorProfiles
Paid partnership, hidden likes, comments offisSponsored, isPaidPartnership, likesAndViewCountsDisabled, isCommentsDisabled
Location and musiclocationName, locationId, locationLatitude, locationLongitude, musicArtist, musicTitle
The sound: its id, own or licensed, explicitaudioId, isOriginalAudio, isExplicitAudio
The share link a row came fromshareUrl
Plays, shares, saves, reposts and the sound's link, as a paid extrainstagramPlayCount, totalPlayCount, sharesCount, savesCount, repostsCount, audioUrl
Facebook plays, likes and comments, in the same paid extrafacebookPlayCount, facebookLikesCount, facebookCommentsCount, totalLikesCount, totalCommentsCount, facebookCountsFound

▶️ How to scrape Instagram posts

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

Hand it no links at all and it writes one free sample row, so you see the shape before spending anything.

💰 How much does it cost to scrape Instagram posts?

$0.18 per 1,000 posts. That is the free plan's price; paid plans pay a little less: $0.178 on Starter, $0.176 on Scale and $0.174 on Business. On the free plan, the $5 Apify gives you each month covers about 27,000 posts.

You pay per post row delivered. Duplicate links are collapsed before the run starts, so the same post is never charged twice. The sample row, every diagnostic row, posts left out by the date filter, and links that were never valid Instagram links cost you nothing.

Plays, shares and Facebook counts, if you tick them: $1.38 per 1,000 posts checked on Starter, $1.36 on Scale and $1.34 on Business, on top of the post price. From 16 November 2026 they cost $4.94 per 1,000 on Starter, $4.89 on Scale and $4.83 on Business. Every post checked is charged, whatever numbers come back for it, and the option needs a paid Apify plan.

📥 What you give it

{
"postUrls": [
"https://www.instagram.com/p/DbtErSrlB2J/",
"https://www.instagram.com/reel/DcCH2ZygIiP/",
"DbwWBxpDm_0"
],
"maxItems": 10
}
FieldDefaultWhat it is
postUrlsnoneThe links you want: post, reel or IGTV links, links from the Share button, bare shortcodes, or numeric post ids written as text. Up to 5,000 per run, duplicates removed first.
maxItemsnoneStop after this many posts, counting from the top of your list. Leave it empty to read every link. The input form starts you at 10.
onlyPostsNewerThannoneKeep posts published on or after a day (2026-08-01, UTC) or within a window (7 days, 2 months). Older posts are left out, not charged, and listed in one free LEFT_OUT_BY_DATE row. Anything that is not a date stops the run before it reads a link.
includeFacebookCountsoffAdds Instagram plays, shares, saves, reposts and the sound's link, plus Facebook plays, likes and comments for posts also shared there, and the Instagram-and-Facebook totals. $1.38 per 1,000 posts checked on Starter, down to $1.34 on Business ($4.94 down to $4.83 from 16 November 2026), on top of the post price, and it needs a paid Apify plan.
sessionCookiesnoneOptional, and rarely needed. Your own Instagram cookie, tried on a post a logged-out run could not read.
proxyUrlsnoneLeave it empty unless you have your own servers you want the traffic to leave through.

📤 What you get back

A real row from a run on 21 September 2026. The caption is cut short in the middle, the media links are trimmed, and the eight carousel frames are shown as two:

{
"ok": true,
"charged": true,
"recordType": "post",
"inputUrl": "https://www.instagram.com/p/DbtErSrlB2J/",
"id": "3957840214710558089",
"shortCode": "DbtErSrlB2J",
"url": "https://www.instagram.com/p/DbtErSrlB2J/",
"type": "Sidecar",
"productType": "carousel_container",
"isReel": false,
"isSponsored": false,
"caption": "Where in the (Martian) world is Curiosity?\n \nOur Curiosity Mars rover has started its climb up a Martian valley called Valle Grande. ...\n \n#NASA #Mars #CuriosityRover",
"hashtags": ["NASA", "Mars", "CuriosityRover"],
"mentions": [],
"likesCount": 284607,
"commentsCount": 1759,
"videoViewCount": null,
"likesAndViewCountsDisabled": false,
"isCommentsDisabled": false,
"timestamp": "2026-08-06T15:49:01.000Z",
"displayUrl": "https://scontent-mia3-3.cdninstagram.com/v/t51.82787-15/766074877_...",
"videoUrl": null,
"videoDuration": null,
"images": [
"https://scontent-mia3-3.cdninstagram.com/v/t51.82787-15/766074877_...",
"https://scontent-mia5-1.cdninstagram.com/v/t51.82787-15/766287913_..."
],
"videos": [],
"childPosts": [
{ "id": "3957839638910891589", "shortCode": "DbtEi6bPnZF", "type": "Image", "displayUrl": "https://scontent-mia3-3.cdninstagram.com/..." }
],
"childPostsCount": 8,
"dimensionsWidth": 495,
"dimensionsHeight": 292,
"alt": null,
"ownerId": "528817151",
"ownerUsername": "nasa",
"ownerFullName": "NASA",
"ownerIsVerified": true,
"ownerIsPrivate": false,
"ownerProfilePicUrl": "https://scontent-mia5-1.cdninstagram.com/v/t51.2885-19/...",
"ownerProfileUrl": "https://www.instagram.com/nasa/",
"coauthorProducers": [],
"coauthorProfiles": [],
"taggedUsers": [],
"sponsorProfiles": [],
"locationName": null,
"locationId": null,
"musicArtist": null,
"musicTitle": null,
"scrapedAt": "2026-09-21T01:45:41.661Z",
"audioId": null,
"isOriginalAudio": null,
"isExplicitAudio": null,
"locationLatitude": null,
"locationLongitude": null,
"shareUrl": null
}
FieldHow to read it
typeImage, Video or Sidecar. Sidecar is Instagram's name for a carousel.
productTypeThe finer kind: feed, clips for a reel, carousel_container, igtv.
shortCodeUnique per post. The right key for joining runs together.
timestampWhen it was published, in UTC. It never moves, so sort and filter on this one.
likesCount, commentsCountA snapshot at read time. Both come back null when the account has hidden its counts, and likesAndViewCountsDisabled says so.
taggedUsers, coauthorProfiles, sponsorProfilesProfile objects with id, username, full name, link and picture. Tagged users carry x and y coordinates when Instagram supplies them.
locationName, musicTitle, altFilled in when the post carries them, null when it does not. Nothing is guessed.
locationLatitude, locationLongitudeThe tagged place's coordinates, not where the phone was. null without a place.
audioIdThe sound's id, the same on every reel that uses it. instagram.com/reels/audio/<audioId>/ is its page. isOriginalAudio is true for the creator's own sound, false for a licensed track. All three are null on posts without a sound.
shareUrlThe share link you pasted, on the row it led to. null for every other link.
facebookCountsFoundOnly with includeFacebookCounts on. true when Facebook numbers came back, false when Instagram showed the whole post and it carries none, null when this check could not tell.
totalPlayCount, totalLikesCount, totalCommentsCountInstagram and Facebook added together, the way Instagram's app shows a shared post. The likes and comments totals are null unless Facebook numbers came back; the plays total is null only when the check could not tell.
instagramPlayCount, sharesCount, savesCount, repostsCount, audioUrlOnly with includeFacebookCounts on. Saves and reposts are not on every check, and sharesCount is null when the post has shares switched off. audioUrl is a signed, short-lived link, like the media links.

🧾 Reading the output

Three kinds of row land in your dataset, and one flag separates them.

RowHow to spot itBilled
A real postok: true and charged: trueyes
The sample row_sample: true, charged: falseno
A diagnostic_diagnostic: true, charged: false, an errorCodeno

Filter on charged == true and you have your posts. Do not filter on recordType: the sample row carries recordType: "post" too. Read charged as the marker that separates a real row from a sample or a diagnostic, not as a receipt.

CodeWhat it means
NOT_FOUNDInstagram says the post is gone, or the link is wrong.
LOGIN_REQUIREDThe post is real, but it is behind a login.
BAD_INPUTThat entry is not an Instagram post link or a shortcode.
RATE_LIMITEDInstagram refused that link this time. Re-running usually clears it.
NOT_SERVEDThis post was not served this run. Re-run it later. Runs before 13 October 2026 wrote BLOCKED here.
SERVER_ERROR, NETWORKInstagram was unreachable or answered badly. Re-run it.
TIME_BUDGETThe run ran out of time before reading every link. One row lists the unread ones in unreadShortCodes. The run still ends as succeeded, with an amber status message, even when the time limit stopped it before any post came back.
NO_RESULTSNothing in the list parsed at all, so the run stopped rather than working through dead links.
LEFT_OUT_BY_DATEPosts older than your onlyPostsNewerThan date. One row lists them in leftOutShortCodes. Not delivered and not charged.
ENGINE_SWITCHEDThe run slowed down part way through. Nothing was lost and nothing extra was charged.
FACEBOOK_COUNTS_OFFYou ticked plays, shares and Facebook counts but this run could not use them: on a free Apify plan, or unavailable on this run. Nothing was looked up or charged for them.
FACEBOOK_COUNTS_STOPPEDThose checks stopped part-way, at the maximum cost you set for the run. Later posts have their fields empty.
PROXY_INPUT_ADJUSTEDA connection setting in your input could not be used and was replaced. The run carried on.
CHARGE_ERROR, UNEXPECTED_ERRORSomething went wrong inside the run. Not charged. If an unexpected error stopped the run before any post came back, the run ends as failed.

A diagnostic row is never billed.

💡 What people use it for

  • Turning a list of links from a brief into a table of captions, counts and media, in one run.
  • Comparing how a competitor's carousels are built, frame by frame, for a creative review.
  • Logging the like and comment counts of the same posts weekly to see how they age. Re-running the same links is safe and gives you a fresh snapshot.

A campaign report in three steps:

  1. Paste the post and reel links your creators sent you here.
  2. Keep the rows where isReel is true and copy their url.
  3. Watch those reels and note the hook each one opens with.

🚧 What it does not do

  • No comment text. The count is there, the comments are not. Those come from Instagram Comments Scraper.
  • It will not walk a profile grid. Give it links. If you want an account's posts, use Instagram Scraper.
  • Nothing private. A post on a private account comes back as a free NOT_FOUND or LOGIN_REQUIRED row instead of data.
  • videoViewCount is usually null. Instagram does not publish the play count to a logged-out reader. Ticking plays, shares and Facebook counts adds them, on paid plans.
  • A long list of dead links stops early. After 40 consecutive failures with nothing parsed, the run writes a NO_RESULTS row and stops rather than burning the rest of your list.
  • If the run hits its deadline, it stops a few seconds early, writes the posts it has, and adds one TIME_BUDGET row listing every link it did not read.
  • Media links expire. They are signed, short-lived links.
  • Facebook numbers are not on every shared post. They exist only for posts the account also shared to Facebook. When a check can't tell, the row says facebookCountsFound: null and the check is still charged.
  • 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
Posts and reels from links you already haveThis one
Posts from an account's gridInstagram Scraper
One row per account, with engagementInstagram Profile Scraper
Comments under a post or reelInstagram Comments Scraper
Play counts for the reels on a profileInstagram Reel Scraper
Posts under a hashtagInstagram Hashtag Scraper
Posts that tag or mention an accountInstagram Mentions Scraper

❓ Questions people ask

Do I need an Instagram account to scrape posts?

No, you don't. The cookie field is optional and takes your own Instagram cookie.

No. One row, one charge, however many frames are in it.

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

Likes and comments are a snapshot at read time. If a post comes back LOGIN_REQUIRED, open it in a private browser window to see whether Instagram asks you to log in there too.

Why is the view count empty on reels?

Instagram does not show play counts to a logged-out reader on a single post. On a paid plan, tick plays, shares and Facebook counts to get them. For a profile's reels, use Instagram Reel Scraper.

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-post-scraper; coding assistants can load our skill file. All three bill your Apify account at the same price.

This reads 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 and include a link that failed and the run ID. The log shows us the rest.

⌂ 换网址