Instagram Comments Scraper avatar

Instagram Comments Scraper

Pricing

from $4.56 / 1,000 comment returneds

Go to Apify Store
Instagram Comments Scraper

Instagram Comments Scraper

Instagram comment scraper for public posts and reels, no login. Paste post links, get one row per comment: author, user ID, text, likes, exact timestamp and whether the post's own account wrote it. Reads the newest comments Instagram shows a signed-out visitor. A post that returns nothing is free.

Pricing

from $4.56 / 1,000 comment returneds

Rating

0.0

(0)

Developer

Adrian Voss

Adrian Voss

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

One row per Instagram comment, without a login. Paste post or reel links and get a flat row per comment: the author's username and numeric user ID, the comment text, its like count, the exact time it was written, whether the post's own account wrote it, and the untouched source object. Field names are frozen and drop straight into a Sheet, a Clay table, an n8n workflow or an AI agent with no post-processing.

Read this before you buy: a signed-out visitor sees only the newest 10 to 14 comments on a post. That is Instagram's limit, not this actor's, and no amount of paying changes it — see "What you can and cannot get without logging in". If you need every comment on a 9,000-comment post, this is the wrong tool and you should say so to yourself now rather than after a run.

Who it's for

A brand watching its own posts wants to know what was said in the last hour, on a schedule, without a person refreshing a phone — and wants owner replies flagged so it can see which complaints have already been answered. A giveaway operator needs the entrants from the current window as a table, with usernames and user IDs, not a screenshot. A social listening or sentiment pipeline needs comment text with a real timestamp attached, in a shape it can feed to a model. And an agent that already knows which posts matter needs one HTTP call that answers "what are people saying on this post right now".

All four want the same thing: the recent comment stream, cheap, in a fixed shape, on a schedule. That is what this actor is. It is a monitor, not an archive.

Why this one

  • Newest first, always. Instagram hands a signed-out visitor its most recent comments, in strict reverse-chronological order — verified on every fixture and asserted by the test suite, so a change in that ordering fails a test rather than quietly reordering your data. Run it every hour and you have a live comment feed for the posts you care about.
  • No login, no cookies, no account risk. Nothing here logs in, stores a session, or asks you for credentials. There is no account of yours to get restricted.
  • The row shape is the product. shortcode, comment_id, parent_id, author, author_id, text, like_count, posted_at, is_owner_reply, reply_count, raw. Frozen names, so a scheduled workflow or an agent can be pointed at this safely. Everything this actor does not surface as its own column is still there, untouched, in raw.
  • author_id, not just author. Usernames change; numeric user IDs do not. If you are deduplicating entrants or matching commenters across posts over time, the ID is the join key and the username is a label.
  • One request per post. The entire payload arrives in the post page itself, so there are no follow-up hops to pay for. That is why this is cheap.
  • Never charged for a miss. A deleted post, a post with comments turned off, an age-gated post, a blocked request — each returns a row explaining what happened and costs nothing.
  • It tells you when it came up short. Every run writes an OUTPUT record listing each post where your limit could not be filled and exactly how many comments were available. You are never left guessing whether 11 rows means "11 comments exist" or "something broke".

What you get

One row per comment by default (turn off "Expand rows" in Advanced to get one row per post instead, with everything nested under comments).

FieldWhat it is
shortcodeThe post the comment is on, e.g. DdcI4o0Prsz
comment_idInstagram's own comment ID, as a string — these exceed what a spreadsheet stores as a number
parent_idThe comment this one replies to. Always empty here — see below
authorThe commenter's username
author_idThe commenter's numeric user ID, as a string. Stable across username changes
textThe comment itself, emoji and all
like_countLikes on the comment. Real, but usually 0 — see below
posted_atWhen the comment was written, ISO-8601 UTC, to the second
is_owner_replytrue when the account that posted the post wrote this comment. Matched on user ID, never on username
reply_countInstagram's count of replies under this comment. Always empty here — see below
rawThe untouched source object, including is_covered, restricted_status, has_translation and giphy_media_info

In grouped mode each post also carries commentCount (what you were billed for), totalComments (how many the post has in total, which is usually far more), and truncated.

What you can and cannot get without logging in

This section exists because the honest answer is the most important thing on this page.

You get: the newest 10 to 14 top-level comments on any public post or reel, with every field in the table above that is marked as filled. Measured on three real posts across two accounts: 10, 11, 13 and 14 comments per page load.

You do not get, at any price, without a login:

Why
Comment 15 and beyondInstagram embeds the newest comments directly in the post page and offers a "next page" cursor alongside them. That cursor is a decoy: every signed-out request that could consume it is refused. This was tested against the real pagination query and against the page's own content query with the page's own variables — both come back empty for a signed-out caller, which proves the channel is closed rather than the cursor being wrong.
Replies to commentsInstagram's signed-out post page carries no reply threads at all. parent_id and reply_count are therefore always empty, and the "Include replies" switch cannot do anything. It is kept only so saved inputs and API calls stay valid, and turning it on writes a note into the run's OUTPUT record instead of pretending.
Realistic like countslike_count is read correctly, but the comments you get are the newest ones, and a comment posted four minutes ago has no likes yet. Across 25 live rows, one had a like. Do not sort or filter on this field.
A representative sampleThe newest dozen comments on a viral post are not a sample of its 9,000 comments. They are the last dozen minutes. Treat this as a live feed, not a survey.

If that list rules out your use case, use a logged-in comment scraper instead. It will cost more and carry account risk, and it will do the job this one cannot.

How to use

  1. In the Apify Console. Open the actor page and click Start — the urls field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
  2. Via the API. Call it directly with a POST request — no Console needed once you have an API token:
    curl "https://api.apify.com/v2/acts/accountable_eel~ig-comments-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"urls":["DdcI4o0Prsz","DdcjXAeFyr8"]}'
  3. On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.

Because the reach per run is the newest comments only, scheduling is how you get depth. An hourly run over the same post accumulates the full comment stream in your dataset over time, a dozen at a time, which one-off runs cannot do.

Input

{
"urls": [
"DdcI4o0Prsz",
"DdcjXAeFyr8"
]
}

One Instagram post or reel per line. A full link or just the shortcode from it both work. No login and no cookies: this reads only the comments a signed-out visitor can see, which is the newest dozen or so per post. Accepted formats: https://www.instagram.com/p/DdcI4o0Prsz/, https://www.instagram.com/reel/DdcI4o0Prsz/, DdcjXAeFyr8.

Post links, reel links, IGTV links, the instagram.com/<name>/p/<code>/ form from a profile grid, links with a ?img_index= on the end, and bare shortcodes are all accepted and all normalise to the same thing. A profile link is rejected with a message saying so, rather than being quietly treated as a post.

Most comments to return per post is also your budget control, since you pay per comment returned. Setting it above about 14 has no effect other than telling you, in the run's OUTPUT record, that it could not be filled.

Sample output

queryfoundstatusshortcodecommentCounttotalCommentstruncatedcommentscomment_idparent_idauthorauthor_idtextlike_countposted_atis_owner_replyreply_countrawscrapedAt
DdcI4o0PrsztrueOK<all comments found (full list)><parent comment id (empty for top-level)><written by the post's author>1970-01-01T00:00:00.000Z

A real expanded row from a live run:

{
"query": "DdcjXAeFyr8",
"found": true,
"status": "OK",
"shortcode": "DdcjXAeFyr8",
"comment_id": "18073828469713536",
"parent_id": null,
"author": "allisonlinda511",
"author_id": "26531589248",
"text": "🥰",
"like_count": 0,
"posted_at": "2026-09-20T13:07:36.000Z",
"is_owner_reply": false,
"reply_count": null,
"raw": { "…": "the untouched source object" }
}

And the run's OUTPUT record from that same run:

{
"requested": 2,
"returned": 25,
"errors": [],
"caps": [
{
"shortcode": "DdcjXAeFyr8",
"available": 14,
"reason": "Instagram preloads only the newest 12 or so comments into a logged-out post page… This post has 990 comments in total; 14 were readable, so a limit of 30 cannot be filled."
}
]
}

A miss comes back as a row with "found": false and is never charged.

Pricing

  • Comment returned: $6 per 1,000 comments

Plus a $0.00005 start fee per run. Each event above is billed independently, only when it actually returns data — misses (found:false) are never charged.

You are billed per comment returned, not per post looked up. A post that comes back empty — deleted, comments off, age-gated, blocked — costs nothing beyond the flat start fee. A post that returns 11 comments bills 11.

That also means the practical cost of a post is roughly a dozen comments' worth, whatever your limit says.

Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

curl "https://api.apify.com/v2/acts/accountable_eel~ig-comments-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
-X POST \
-H "Content-Type: application/json" \
-d '{"urls":["DdcI4o0Prsz","DdcjXAeFyr8"]}'

n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~ig-comments-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"urls":["DdcI4o0Prsz","DdcjXAeFyr8"]} (swap in an expression from an earlier node for a real value).

Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~ig-comments-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"urls":["{{post}}"]}, mapping the row's post into the urls array.

MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Instagram Scraper API: Comments by Post URL" — the agent will find and run this actor.

Tips

  • Schedule it hourly against a small set of posts. That is the design point. Each run adds the newest dozen comments, and over a day you accumulate the stream. A single run never will.
  • Deduplicate on comment_id. Consecutive scheduled runs will overlap, because the newest dozen changes slowly on a quiet post. comment_id is stable and unique.
  • Join on author_id, label with author. Usernames change between runs; IDs do not.
  • Do not filter on like_count or reply_count. Both are honest fields and both carry almost no information on this route, for the reasons in "What you can and cannot get". posted_at, text, author_id and is_owner_reply are the fields worth building on.
  • Use is_owner_reply to find answered threads. For a brand monitoring its own posts, it is the cheapest available signal for "we already responded to this".
  • Watch the OUTPUT record, not the row count. caps[] distinguishes "this post only has 11 comments" from "your limit of 500 was never reachable", and errors[] names every post that missed and why.
  • Keep concurrency low. Instagram rate-limits aggressively. The default of 2 with a Residential proxy returned every row on the first attempt in testing; pushing it higher invites HTTP 429.

vs. alternatives

This actorA logged-in comment scraper
Comments per postthe newest 10–14potentially all of them
Repliesnousually yes
Needs an Instagram accountnoyes
Account restriction risknoneyours
Billingper comment returned, misses freeusually per comment too
Best atmonitoring recent comments on known posts, on a scheduleone-off deep exports of a whole post

apify/instagram-comment-scraper, the category leader, sells at roughly $2.30 per 1,000 comments and does go deeper, because it does not work signed out. If you need depth, buy depth. This actor is the cheaper, lower-risk half of the market: recent comments, no login, a frozen row shape, and an honest statement of its ceiling.

Data & privacy

This actor reads only pages that Instagram serves to an ordinary signed-out visitor. It never logs in, never stores or transmits credentials, never sets or reuses a session cookie, and never touches private accounts or content behind a follow request.

Comments are written by identifiable people. The usernames, user IDs, profile pictures and text this actor returns are personal data under the GDPR and comparable laws, and you are the controller of whatever you collect. Have a lawful basis, keep only what you need, honour deletion requests, and do not use it to build profiles of individuals or to contact people who have not asked to hear from you. Instagram's own Terms of Use apply to you as well as to us.

FAQ

Why did I only get 11 comments when the post has 9,000? Because Instagram shows a signed-out visitor the newest dozen and refuses every route past them. The run's OUTPUT record says so explicitly, per post, with the count that was available. Nothing is wrong with the actor and you were billed only for the 11.

Can I get older comments by running it again with a different setting? No. There is no setting that reaches them. Running it repeatedly over time accumulates new comments as they are written, which is the intended way to build depth.

Why is reply_count empty on every row? Instagram's signed-out post page carries no reply data at all. The field is reported as empty rather than as 0, because "unknown" and "none" are different answers and collapsing them would mislead you.

Why is like_count zero almost everywhere? The comments returned are the newest ones. A comment written minutes ago genuinely has no likes. The field is read correctly; there is just nothing to read yet.

Does the "Include replies" switch do anything? No, and it says so in its own help text. It exists so that saved inputs and API calls that set it stay valid. Turning it on adds a note to the run's OUTPUT record.

Can I pass a profile link instead of a post link? No — you will get a BAD_FORMAT row telling you to paste the post link. This actor works per post. To go from a username to its posts, run Instagram Profile Scraper first and feed its shortcode column in here.

What happens on a post with comments turned off? A found: false row saying "comments disabled or none yet", and no charge. Instagram does not distinguish "the author turned comments off" from "nobody has commented" to a signed-out visitor, so the message names both possibilities instead of guessing.

Do I need a proxy? Yes, Residential. Apify's datacenter addresses are answered with HTTP 429 on this target; the Residential group returned every row on the first attempt. It is the default here.

  • Instagram Profile Scraper: Posts and Reels — usernames in, one row per post or reel out, with captions, hashtags, engagement and media links. Its shortcode column is this actor's input.