Instagram Post Scraper - Captions, Likes, Media
Pricing
from $0.17 / 1,000 instagram posts
Instagram Post Scraper - Captions, Likes, Media
Scrape Instagram posts and reels from links or shortcodes. One row per post: caption, likes, comments, publish time, 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
Maintained by CommunityActor stats
0
Bookmarked
60
Total users
21
Monthly active users
5 days ago
Last modified
Categories
Share
Paste Instagram post, reel or IGTV links and get 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 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: caption, likes, comments, publish time, every image and video URL, owner, hashtags, mentions, tagged users, location, music |
| Ceiling | 5,000 links per run |
| Account needed | None |
| 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 Facebook counts, paid plans only: $1.38 per 1,000 posts checked on Starter, down to $1.34 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 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 withheld comes back as a free labelled row rather than a charge.
📋 What data you get from each Instagram post
| What you get | Field |
|---|---|
| Link, shortcode and numeric id | url, shortCode, id |
| What kind of post it is | type, productType, isReel |
| Caption, and the hashtags and handles in it | caption, hashtags, mentions |
| Likes and comments | likesCount, commentsCount |
| Video views and length | videoViewCount, videoDuration |
| Publish time | timestamp |
| Cover, video file and every carousel frame | displayUrl, videoUrl, images, videos, childPosts, childPostsCount |
| Size and alt text | dimensionsWidth, dimensionsHeight, alt |
| The account that posted it | ownerUsername, ownerFullName, ownerId, ownerIsVerified, ownerIsPrivate, ownerProfilePicUrl, ownerProfileUrl |
| Tagged people, co-authors and sponsors | taggedUsers, coauthorProfiles, coauthorProducers, sponsorProfiles |
| Paid partnership, hidden likes, comments off | isSponsored, isPaidPartnership, likesAndViewCountsDisabled, isCommentsDisabled |
| Location and music | locationName, locationId, musicArtist, musicTitle |
| Facebook plays, likes and comments, as a paid extra | facebookPlayCount, facebookLikesCount, facebookCommentsCount, totalPlayCount, totalLikesCount, totalCommentsCount, instagramPlayCount, facebookCountsFound |
▶️ How to scrape Instagram posts
- Open Instagram Post Scraper and click Try for free.
- Paste your links into Post or reel links, one per line.
- Set Maximum posts while you are testing, since you pay per post.
- Click Start.
- 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 labelled sample row, which is not charged, so you can 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, and links that were never valid Instagram links cost you nothing.
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. Every post checked is charged, whether or not Facebook 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}
| 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 | Adds Facebook plays, likes and comments for posts that were also shared to Facebook, plus the Instagram-and-Facebook totals. $1.38 per 1,000 posts checked on Starter, down to $1.34 on Business, on top of the post price, and it needs a paid Apify plan. |
sessionCookies | none | Optional, and rarely needed. Your own Instagram cookie, tried on a post a logged-out run could not read. |
proxyUrls | none | Leave 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"}
| Field | How to read it |
|---|---|
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. |
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. |
totalPlayCount, totalLikesCount, totalCommentsCount | Instagram and Facebook added together, the way Instagram's app shows a shared post. null unless Facebook numbers came back. |
🧾 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. 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.
| Code | What it means |
|---|---|
NOT_FOUND | Instagram says the post is gone, or the link is wrong. |
LOGIN_REQUIRED | The post is real, but Instagram shows it only to signed-in viewers, so a logged-out run cannot read it. |
BAD_INPUT | That entry is not an Instagram post link or a shortcode. |
RATE_LIMITED | Instagram refused that link this time. Re-running usually clears it. |
NOT_SERVED | This post was not served this run. Re-run it later. Until 12 October 2026 this code was called BLOCKED. |
SERVER_ERROR, NETWORK | Instagram was unreachable or answered badly. Re-run it. |
TIME_BUDGET | The run ran out of time before reading every link. One row lists the unread ones in unreadShortCodes. The run ends as failed only when the time limit stopped it before any post came back. |
NO_RESULTS | Nothing in the list parsed at all, so the run stopped rather than working through dead links. |
ENGINE_SWITCHED | The run switched to a slower way of reading posts part way through. Nothing was lost and nothing extra was charged. |
FACEBOOK_COUNTS_OFF | You ticked 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_STOPPED | Facebook counts stopped part-way, at the maximum cost you set for the run. Later posts have the Facebook fields empty. |
PROXY_INPUT_ADJUSTED | A connection setting in your input could not be used and was replaced. The run carried on. |
CHARGE_ERROR, UNEXPECTED_ERROR | Something went wrong inside the run. Not charged, and the run still ends normally. |
A diagnostic row never fails the run and 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:
- Paste the post and reel links your creators sent you here.
- Keep the rows where
isReelistrueand copy theirurl. - 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_FOUNDorLOGIN_REQUIREDrow instead of data. 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_RESULTSrow 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_BUDGETrow 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, and Instagram does not show the Facebook side on every check. When it holds it back,
the row says
facebookCountsFound: nulland 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 want | Use |
|---|---|
| Posts and reels from links you already have | This one |
| Posts from an account's grid | Instagram Scraper |
| One row per account, with engagement | Instagram Profile Scraper |
| Comments under a post or reel | Instagram Comments Scraper |
| Play counts for the reels on a profile | Instagram Reel Scraper |
| Posts under a hashtag | Instagram Hashtag Scraper |
| Posts that tag or mention an account | Instagram Mentions Scraper |
❓ Questions people ask
Do I need an Instagram account to scrape posts?
No. Public posts are read logged out, and that covers the vast majority of links. The cookie field is optional and takes your own Instagram cookie.
Does a carousel cost more than a photo?
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, so they drift from what you see later. 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. For play counts across a profile's reels, use Instagram Reel Scraper from the table above.
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-post-scraper. Either way the
run happens on your Apify account at the same price.
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.
🆘 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.