Instagram Post Scraper
Scrape Instagram posts and reels by link or shortcode. Rows carry caption, likes, comments, publish time, carousel media, hashtags. No login. $0.18 per 1,000.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
postUrls,maxItems,includeFacebookCounts(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.00018 per Instagram post = $0.18 per 1,000
| You are charged for | When | Price |
|---|---|---|
| Instagram post scraped | One Instagram post or reel returned as a full data row. Sample and diagnostic rows are never charged. | $0.00018 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-08-15, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
postUrls | One or more Instagram post, reel or IGTV links, for example https://www.instagram.com/p/DbtErSrlB2J/ or https://www.instagram.com/reel/DcCH2ZygIiP/. Bare shortcodes such as DbtErSrlB2J work too. Duplicates are removed before anything is charged. Up to 5,000 links per run. | array |
maxItems | Stop after this many posts, counting from the top of your list. Leave it empty to scrape every link you supplied. Keep it low while you are testing, you pay per post. | integer |
includeFacebookCounts | Available from 12 October 2026. Until then, ticking it changes nothing and costs nothing. For posts that were also shared to Facebook, it adds the Facebook plays, likes and comments and the Instagram-plus-Facebook totals. It costs $1.40 per 1,000 posts checked, on top of the post price, and every post checked is charged, whether or not Facebook numbers come back. Instagram does not show the Facebook side on every check, so some rows say unknown. Needs a paid Apify plan. | boolean |
sessionCookies | Leave this empty for public posts. Runs are logged out and that is enough for the vast majority of links. Instagram does sometimes refuse a logged-out reader on a specific post, and those links come back as free diagnostic rows; if that happens often, paste your own Instagram cookie here and the run reads through your account's own rate limit instead. In Chrome: F12 → Application → Cookies → instagram.com. The `sessionid` cookie is the one that matters; `csrftoken` alongside it is better. Paste it as `sessionid=...; csrftoken=...`, one entry per account. Prefer a throwaway account over your main one. Use an account you own and are authorised to automate. | array |
proxyUrls | Leave this empty for a normal run. Fill it in only if you want the traffic to leave through proxy servers you already pay for, one URL per line, in the form http://user:pass@host:port. | array |
What you get
A structured dataset — each result includes fields like:
shortCodeurltypeownerUsernamecaptionlikesCountcommentsCounttimestampdisplayUrlvideoUrlchildPostsCounthashtagsmentionslocationNameisSponsoredlikesAndViewCountsDisabledisCommentsDisabledfacebookCountsFoundfacebookPlayCountfacebookLikesCountfacebookCommentsCounttotalPlayCounttotalLikesCounttotalCommentsCounttaggedUserscoauthorProfilessponsorProfilesisPaidPartnershipExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
1 ready-to-run use cases
Instagram Post Engagement by URL
Get likes, comments, caption and media links for specific Instagram posts. Paste the post URLs and run. No login.
Related tools in Social Media Scrapers
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
Instagram Profile Scraper
Scrape Instagram profiles from handles or URLs. Get the bio, exact follower and post counts, verified flag, category and bio links. $0.70 per 1,000.
Instagram Reel Scraper
Scrape reels from any public Instagram profile. Play counts, likes, comments, captions, duration, MP4 and cover links, audio. $0.35 per 1,000 reels.
LinkedIn Post Search Scraper
Scrape public LinkedIn posts by keyword: author, text, exact date, reactions, comments and post URL. No login or cookies. $0.90 per 1,000 posts.
LinkedIn Profile Search Scraper
Find public LinkedIn profiles by keyword, title, company, school or location: name, headline, role, profile URL. No login. $0.50 per 1,000.
YouTube Shorts Scraper
Scrape YouTube Shorts by channel or keyword. Titles, ids, URLs, exact views and likes, publish dates, thumbnails. No API key. $0.40/1k.
TikTok Scraper - Profiles, Videos, Hashtags & Search
Scrape TikTok profiles, videos, hashtags and search. Play, like, comment and share counts. No login needed from you. $0.25 per 1,000.
Where this tool sits
- Categories
- Social Media Scrapers
Instagram Post Scraper: one row per post or reel, from links you already have
Paste Instagram post, reel or IGTV links and get one row each: the full caption, the 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 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.
| Input | Post, reel or IGTV links, or bare shortcodes |
| Output | One row per post |
| Ceiling | 5,000 links per run |
| Account needed | None from you |
| Price | $0.18 per 1,000 posts, flat on every plan. Optional Facebook counts: $1.40 per 1,000 posts checked, from 12 October 2026 |
🔍 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 just DbtErSrlB2J on its own. Mix them freely in one run.
Carousels come back whole. images and videos hold every frame in carousel order, childPosts holds one object per frame with its own shortcode and dimensions, and childPostsCount tells you how many there were. A reel fills in videoUrl and videoDuration and carries type: "Video" with productType: "clips".
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 on a private account comes back as a free labelled row rather than a charge.
📥 What you give it
{
"postUrls": [
"https://www.instagram.com/p/DbtErSrlB2J/",
"https://www.instagram.com/reel/DcCH2ZygIiP/",
"DbwWBxpDm_0"
],
"maxItems": 10
}
| Field | Default | What it is |
|---|---|---|
postUrls | none | The links you want. Up to 5,000 per run, duplicates removed first. |
maxItems | none | Stop 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. |
includeFacebookCounts | off | From 12 October 2026. Adds Facebook plays, likes and comments for posts that were also shared to Facebook, plus the Instagram-and-Facebook totals. $1.40 per 1,000 posts checked, on top of the post price, and it needs a paid Apify plan. Ticking it before then changes nothing and costs nothing. |
sessionCookies | none | Optional, and rarely needed. Your own Instagram cookie, used to read through your account's own rate limit. The value sits in the run input, so use an account you are happy to automate. |
proxyUrls | none | Leave it empty unless you have your own servers you want the traffic to leave through. |
Hand it no links at all and it writes one labelled sample row, free, so you can see the shape before spending anything.
📤 What you get back
A real row from a real run. 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,
"source": "graphql",
"scrapedAt": "2026-09-21T01:45:41.661Z"
}
| Field | What it is |
|---|---|
type | Image, Video or Sidecar. Sidecar is Instagram's name for a carousel. |
productType | The finer kind: feed, clips for a reel, carousel_container, igtv. |
shortCode | Unique per post. The right key for joining runs together. |
timestamp | When it was published, in UTC. It never moves, so sort and filter on this one. |
likesCount, commentsCount | A snapshot at read time. Both come back null when the account has hidden its counts, and likesAndViewCountsDisabled says so. |
taggedUsers, coauthorProfiles, sponsorProfiles | Profile objects with id, username, full name, link and picture. Tagged users carry x and y coordinates when Instagram supplies them. |
locationName, musicTitle, alt | Filled in when the post carries them, null when it does not. Nothing is guessed. |
source | Which public route answered for this row. |
facebookCountsFound | Only 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. |
facebookPlayCount, facebookLikesCount, facebookCommentsCount | The Facebook side of a shared post. null when none came back. |
totalPlayCount, totalLikesCount, totalCommentsCount | Instagram and Facebook added together, the way Instagram's app shows a shared post. null unless Facebook numbers came back. |
instagramPlayCount | Instagram plays on their own, for reels, whenever the Facebook check answered. |
🧾 Reading the output
Three kinds of row land in your dataset, and one flag separates them.
| Row | How to spot it | Billed |
|---|---|---|
| A real post | ok: true and charged: true | yes |
| The sample row | _sample: true, charged: false | no |
| A diagnostic | _diagnostic: true, charged: false, an errorCode | no |
Filter on charged == true and you have your posts. Read that flag as the marker that separates a real row from a sample or a diagnostic, not as a receipt.
| Code | What it means |
|---|---|
NOT_FOUND | Deleted, or on a private account. Nothing public to read. |
BAD_INPUT | That entry is not an Instagram post link or a shortcode. |
RATE_LIMITED, BLOCKED | Instagram refused that link this time. Re-running usually clears it. |
SERVER_ERROR, NETWORK | Instagram was unreachable or answered badly. Re-run it. |
TIME_BUDGET | The run ran out of time before reaching that link. |
NO_RESULTS | Nothing in the list parsed at all, so the run stopped rather than working through dead links. |
FACEBOOK_COUNTS_OFF | You ticked Facebook counts but this run could not use them: before 12 October 2026, on a free Apify plan, or unavailable on this run. Nothing was looked up or charged for them. |
FACEBOOK_COUNTS_STOPPED | Facebook counts stopped part-way, at the maximum cost you set for the run. Later posts have the Facebook fields empty. |
A diagnostic row never fails the run and is never billed.
▶️ How to run it
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.
💰 How much does it cost?
$0.18 per 1,000 posts. Flat on every Apify plan, no volume tiers.
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, and links that were never valid Instagram links cost you nothing.
Facebook counts, if you tick them: $1.40 per 1,000 posts checked, from 12 October 2026, on top of the post price. Every post checked is charged, whether or not Facebook numbers come back for it, and the option needs a paid Apify plan.
💡 What people use it for
- Turning a list of links from a brief into a table of captions, counts and media, in one run.
- Pulling every frame of a competitor's carousels for a creative review.
- Logging the like and comment counts of the same posts weekly to see how they age.
- Collecting reel video files and durations for a cut-down or a highlights reel.
🚧 What it does not do
- No comment text. The count is there, the comments are not. That is a separate actor, linked
below.
- It will not walk a profile grid. Give it links. If you want everything an account has posted,
use the profile-level actor below.
- Nothing private. A post on a private account comes back
NOT_FOUND, and no input reaches it. videoViewCountis usuallynull. Instagram does not publish the play count to a logged-out
reader. Likes and comments are there.
- 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, the next 25 unread links get a
TIME_BUDGETrow each and the
rest get no row at all.
- Media links expire. They are signed, short-lived links, so download anything you want to keep.
- Facebook numbers are not on every shared post. They exist only for posts the account also shared
to Facebook, and Instagram does not show the Facebook side on every check. When it holds it back, the row says facebookCountsFound: null and the check is still charged.
- Counts are a snapshot at read time, not at publish time.
🧭 Which Instagram scraper do you need?
| If you want | Use |
|---|---|
| One post or reel you already have the link for | This one |
| Everything on an account's grid | Instagram Scraper |
| One row per account, with contact details and engagement | Instagram Profile Scraper |
| Comments under a post or reel | Instagram Comments Scraper |
| Posts under a hashtag | Instagram Hashtag Scraper |
❓ Questions people ask
Do I need an Instagram account? No. Public posts are read logged out, and that covers the vast majority of links.
Does a carousel cost more than a photo? No. One row, one charge, however many frames are in it.
What if I paste the same post twice? It is fetched and charged once. That includes the same shortcode supplied once as a URL and once on its own.
Can I get the comments? Not here. Use the comments actor linked above.
Is scraping Instagram legal? 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.
Can I run it on a schedule? Yes. Re-running the same links is safe and gives you a fresh snapshot of the counts.
🆘 If something breaks
Open the Issues tab on the actor page. Include one of the links that failed and the run ID, and the log is enough for us to see what happened.