Instagram Comments Scraper
Pricing
from $1.50 / 1,000 comment results
Instagram Comments Scraper
Scrape public Instagram comments and replies from Posts and Reels. Extract comment text, timestamps, likes, usernames, user IDs, profile pictures, mentions and thread relationships. Process multiple URLs and export clean JSON, CSV or Excel.
Pricing
from $1.50 / 1,000 comment results
Rating
0.0
(0)
Developer
Delowar Munna
Maintained by CommunityActor stats
0
Bookmarked
6
Total users
0
Monthly active users
9 days ago
Last modified
Categories
Share

Scrape public Instagram comments and replies from Posts and Reels. Extract comment text, timestamps, likes, usernames, user IDs, profile pictures, mentions and thread relationships. Process multiple URLs and export clean JSON, CSV or Excel.
What this actor does
Instagram Comments Scraper takes a list of Instagram Post or Reel URLs and returns one flat row per comment or reply:
- 💬 Comment: ID, text (unchanged), timestamp, likes, reply count,
@mentions, comment link - 🧵 Thread:
isReply,threadingDepth,rootCommentId,parentCommentId,replyToCommentId. Replies are their own rows, so threads stay intact in spreadsheets, SQL and AI pipelines - 👤 Commenter: user ID, username, full name, profile URL, profile picture, verified and private flags
- 🖼️ Source context: post ID, shortcode, URL, type (
POST/REEL/VIDEO/CAROUSEL), owner username, caption preview - 🚦 Status rows: every input that yields no comments (comments disabled, deleted, invalid URL, …) gets a free status row, so inputs always reconcile with outputs
It covers image posts, video posts, carousels, Reels and legacy /tv/ links. No Instagram login, password, cookies or Meta token is needed.
It extracts comments and only comments. For full post metadata use a posts or Reels scraper, and to enrich commenters feed ownerUsername into Instagram Profile Scraper.
How it works
- Normalize URLs.
/p/,/reel/,/reels/,/tv/and/{username}/p/…links are accepted. Tracking parameters (igsh,utm_*,img_index) are stripped and duplicate links to the same post are merged. - Resolve the post from its public page: type, owner, caption, availability.
- Page through comments in Instagram's own order, then load each comment's replies. Comment pages of one post are fetched in order; replies for a few comments at a time load in parallel.
- Fall back instead of failing. Instagram often refuses anonymous comment loading. When it redirects to its login page, the actor switches that post to an alternative source right away. Rate limits and blocks get one retry on a fresh session/IP first. When Instagram refuses several requests in a row, posts go to the alternative source first and the actor keeps checking whether Instagram has recovered. On the alternative source, the next page of comments loads while the current page's replies are fetched, so rows start appearing within seconds.
- Deduplicate and export. Each comment ID is saved, and charged, once per run.
Input
| Field | Type | Default | Description |
|---|---|---|---|
startUrls | array | required (prefilled with a sample Reel) | Post / Reel / TV URLs (up to 1,000 per run) |
resultsLimit | int | 100 | Max comment and reply rows per URL |
includeReplies | bool | true | Also collect replies, one row each |
sort | enum | RECENT | RECENT (newest first) or TOP (Instagram's most relevant first) |
commentsNewerThan | string | empty | Keep comments after this point: 24 hours, 7 days, 2 weeks, 2026-09-01, … |
commentsOlderThan | string | empty | Keep comments before this point |
includePostDetails | bool | true | Add the post context object to every row |
proxyConfiguration | object | Apify Proxy on | Proxy settings (see Proxy policy) |
maxConcurrency | int | 5 | Posts processed in parallel (1–10) |
maxRetries | int | 3 | Retries per request on rate limits / temporary errors |
debugMode | bool | false | Verbose logging |
Example 1: Minimal
{"startUrls": [{ "url": "https://www.instagram.com/reel/DeR1rDbOo2m/" }],"resultsLimit": 100}
Example 2: Up to 500 comments and replies, newest first
{"startUrls": [{ "url": "https://www.instagram.com/reels/DeR1rDbOo2m/" }],"resultsLimit": 500,"includeReplies": true,"sort": "RECENT"}
Example 3: Last 30 days only
With RECENT, the actor stops paging as soon as it reaches comments older than the window, so you pay neither for the older comments nor for the time spent fetching them.
{"startUrls": [{ "url": "https://www.instagram.com/reel/DeR1rDbOo2m/" }],"resultsLimit": 1000,"includeReplies": true,"sort": "RECENT","commentsNewerThan": "30 days"}
Example 4: Top comments only, no replies, minimal rows
{"startUrls": [{ "url": "https://www.instagram.com/reel/DeR1rDbOo2m/" }],"resultsLimit": 50,"includeReplies": false,"sort": "TOP","includePostDetails": false}
Output
One row per comment or reply. Unavailable values are null (a missing like count is null, never a fake 0). Every row has the same columns, so CSV/Excel exports stay stable. The dataset has four tabs: Comments, Threads, Commenters & posts and Status & errors.
The samples below are real rows from a run on reels/DeR1rDbOo2m with resultsLimit: 100 (100 rows: 86 comments + 14 replies). Profile picture URLs are shortened.
Comments tab

{"ownerUsername": "talisasg","text": "insoportable mal","timestamp": "2026-10-09T15:42:28.000Z","likesCount": 3,"repliesCount": 3,"isReply": false,"mentionedUsers": [],"commentUrl": "https://www.instagram.com/p/DeR1rDbOo2m/c/18126650533830415/","postUrl": "https://www.instagram.com/reel/DeR1rDbOo2m/","commentId": "18126650533830415","ownerId": "225407155","scrapedAt": "2026-10-09T16:13:11.977Z"}
Threads tab
A reply row from the same thread. It points at its root comment, and mentionedUsers picks up the @mention:
{"postId": "4004217598789717414","rootCommentId": "18126650533830415","commentId": "17884853547688420","parentCommentId": "18126650533830415","replyToCommentId": "18126650533830415","threadingDepth": 1,"isReply": true,"ownerUsername": "crab.83643369","text": "@talisasg 😍😍","timestamp": "2026-10-09T15:59:25.000Z"}
Commenters & posts tab
{"owner": {"id": "42060298184","username": "aghalondon","fullName": "Agha beauty/ Men’s Skincare","profileUrl": "https://www.instagram.com/aghalondon/","profilePicUrl": "https://scontent-iad3-2.cdninstagram.com/v/t51.82787-19/649242314_18059727068402185_8936880996156801292_n.jpg?…","isVerified": true,"isPrivate": false},"ownerUsername": "aghalondon","text": "🔥🔥🔥🔥🔥","post": {"id": "4004217598789717414","shortCode": "DeR1rDbOo2m","url": "https://www.instagram.com/reel/DeR1rDbOo2m/","type": "REEL","ownerUsername": "oakleymeta","captionPreview": "“Hey Meta, how many putts have I taken today?” This and more putting green questions answered by @meta.ai with @arccosgolf or @18birdiesapp. \n\n*18Birdies app or Arccos game tracking subscription requi…"},"postUrl": "https://www.instagram.com/reel/DeR1rDbOo2m/"}
Status & errors tab
Free status row for a deleted post (from a run on a URL that no longer exists):
{"inputUrl": "https://www.instagram.com/p/DPwhVB-jo9k/","rowType": "error","error": "POST_NOT_FOUND","errorMessage": "Fallback source returned no data: \"The requested resource does not exist. Please check the input parameters and verify manually (post, video, comment, user, etc.).\" (data keys: status, errorMessage, attempts)","postUrl": "https://www.instagram.com/p/DPwhVB-jo9k/","scrapedAt": "2026-10-09T15:46:49.965Z"}
All comment columns of a status row are null.
Full row (all fields)
{"rowType": "comment","commentId": "18126650533830415","commentUrl": "https://www.instagram.com/p/DeR1rDbOo2m/c/18126650533830415/","text": "insoportable mal","timestamp": "2026-10-09T15:42:28.000Z","likesCount": 3,"repliesCount": 3,"isReply": false,"threadingDepth": 0,"rootCommentId": "18126650533830415","parentCommentId": null,"replyToCommentId": null,"mentionedUsers": [],"ownerUsername": "talisasg","ownerId": "225407155","owner": {"id": "225407155","username": "talisasg","fullName": "Talisa Sg","profileUrl": "https://www.instagram.com/talisasg/","profilePicUrl": "https://scontent-iad3-1.cdninstagram.com/v/t51.82787-19/788081894_18623082562063156_3896261708583324431_n.jpg?…","isVerified": false,"isPrivate": false},"isEdited": false,"hasTranslation": null,"postId": "4004217598789717414","postUrl": "https://www.instagram.com/reel/DeR1rDbOo2m/","post": {"id": "4004217598789717414","shortCode": "DeR1rDbOo2m","url": "https://www.instagram.com/reel/DeR1rDbOo2m/","type": "REEL","ownerUsername": "oakleymeta","captionPreview": "“Hey Meta, how many putts have I taken today?” This and more putting green questions answered by @meta.ai with @arccosgolf or @18birdiesapp. \n\n*18Birdies app or Arccos game tracking subscription requi…"},"error": null,"errorMessage": null,"inputUrl": "https://www.instagram.com/reels/DeR1rDbOo2m/","scrapedAt": "2026-10-09T16:13:11.977Z"}
commentUrl uses Instagram's /p/ form, which opens Reels too. inputUrl keeps the URL exactly as you entered it; postUrl is the canonical one.
Status values
| Status | Meaning |
|---|---|
NO_COMMENTS | The content has no public comments, or none inside your date window |
COMMENTS_DISABLED | Comments are turned off for this content |
INVALID_URL | Not a Post/Reel URL (profile, hashtag, search, story, other site, malformed) |
POST_NOT_FOUND | The Post or Reel doesn't exist or was deleted |
PRIVATE_OR_LOGIN_REQUIRED | Private or restricted content, or Instagram refused anonymous access and the alternative source couldn't help |
CONTENT_UNAVAILABLE | Gated for logged-out visitors (private, age-restricted), or Instagram kept serving its error page |
RATE_LIMITED / BLOCKED | Instagram throttled the request and the alternative source couldn't return it either |
PARTIAL_RESULT | Some comments were saved (and charged), then pagination stopped early. The message says why |
TEMPORARY_INSTAGRAM_ERROR / PROVIDER_ERROR | Instagram, network or alternative-source error persisted through retries |
Inputs that end in a retry-worthy status (rate limits, blocks, partial results, temporary errors) are collected in a ready-to-run RETRY_INPUT record in the key-value store.
Run summary
Each run writes a RUN_SUMMARY record to the key-value store: input/success/failed URL counts, comments and replies saved, duplicates skipped, comments outside the date window, comments-disabled count, status counts, which route served each post, whether your spending limit stopped the run, and timing (runtime and when the first rows were saved).
FAQ
Which URLs work? instagram.com/p/{code}/, /reel/{code}/, /reels/{code}/, /tv/{code}/ (where Instagram still resolves it) and /{username}/p/{code}/. www., bare and m. hosts are all accepted.
Do I need to log in or provide cookies? No. The actor never asks for credentials, cookies or tokens.
Are Reels supported? Yes, along with image posts, video posts and carousels.
Are replies included? How deep? Yes by default. Instagram threads are two levels deep: a comment and its replies (threadingDepth 0 and 1). A reply to a reply is attached to the same root comment. replyToCommentId holds the specific reply it answered when Instagram exposes it, otherwise the root comment.
What does resultsLimit mean? The maximum number of rows, comments plus replies, saved per input URL.
How fast is it? On our latest test run, 100 rows from one Reel took about 30 seconds, with the first rows saved after about 5 seconds. Comment pages of one post load one after another, so a very large post takes longer. Several posts run in parallel (maxConcurrency).
Can I sort comments? Yes. RECENT and TOP use Instagram's own ordering. TOP is never simulated by re-sorting a partial list.
Can I filter by date? Yes, with commentsNewerThan / commentsOlderThan. Each row is checked on its own timestamp, replies included. Replies are loaded only for comments inside the window. Comments outside the window are never charged.
Are comment likes included? Yes, as likesCount, or null when Instagram doesn't return it.
Why might I get fewer comments than Instagram displays? Instagram's displayed count includes comments that are hidden, filtered as offensive or spam, restricted, or deleted, and it counts replies the public list can't reach. repliesCount is Instagram's total and can be higher than the replies saved when resultsLimit is reached.
What happens when comments are disabled? You get one free COMMENTS_DISABLED status row for that URL, and the rest of the run continues.
Can I schedule recurring runs or use the API? Yes. Use Apify Schedules for recurring runs (with commentsNewerThan set to the schedule interval, each run picks up only new comments) and the Apify API, SDKs, integrations or MCP server for automation and AI agents.
How do I enrich commenter profiles? Pass the ownerUsername values into Instagram Profile Scraper for follower counts, bio, links and business contact fields.
Pricing
Pay per event, per delivered unique comment or reply. You are not charged for invalid URLs, duplicates, comments outside your date filter, status/error rows, post resolution, pagination, retries or the run summary. There is no start fee. The rate per comment can differ by Apify plan, so see the Pricing tab for the current rate on yours. This README deliberately doesn't quote figures.
The actor respects the spending limit you set for a run. It never saves more comments than the limit pays for, and it doesn't start fetching what the remaining budget can't cover. When the limit is reached the run stops cleanly. A post cut short gets a free PARTIAL_RESULT row saying so. That post and any posts not yet started are listed in RETRY_INPUT, so you can continue with a larger budget. A re-run starts each post from the beginning, so comments already saved are collected again.
🚦 Proxy policy
Use Apify Datacenter proxy (the default) or no proxy for normal runs. Both are supported: when Instagram throttles the proxy's IPs, comments are served by the alternative source instead. If you enable Apify Proxy without choosing a country, exits are pinned to the US to avoid regionally blocked IPs. Pick a country in the proxy editor to override.
Apify Residential proxy is not supported. The actor fails at startup if apifyProxyGroups includes RESIDENTIAL. In pay-per-event actors, residential bandwidth is billed per GB to the developer, not the run user, so a single bandwidth-heavy run could cost more than the per-result revenue.
If you need residential routing, supply your own residential provider in the proxy editor's Custom proxy URLs field. That traffic goes through your provider, not Apify, and is unaffected:
http://user:pass@proxy.iproyal.com:12321http://user:pass@proxy.brightdata.com:22225http://user:pass@proxy.oxylabs.io:7777
Limitations
- Public content only. Private accounts and content gated for logged-out visitors are not supported. They return a free status row.
- Instagram limits anonymous comment loading. Many comment requests are served by the alternative source rather than Instagram directly. Results are the same comments, but a post that neither source can load ends as a free
RATE_LIMITED,BLOCKEDorPRIVATE_OR_LOGIN_REQUIREDrow. - Hidden, filtered and deleted comments aren't returned, and the actor doesn't attempt to reconstruct a logged-in user's personalised comment view.
- Date-window scanning is bounded. When comments can't be skipped by date (
TOPsort, orcommentsOlderThan), the actor pages through comments outside the window without charging for them. It stops after 50 such pages in a row on one post, or 500 across the run, and marks the postPARTIAL_RESULT.RECENTwithcommentsNewerThanstops early and never hits this. isEditedisnullwhenever Instagram doesn't expose an edit flag for a comment.- Profile picture URLs expire after a while, as all Instagram CDN links do. Download them promptly if you need them.
- Post type comes from the post itself when it can be resolved. Otherwise it falls back to the URL (
/reel/→REEL,/tv/→VIDEO,/p/→POST).
Legal and privacy
This is an unofficial tool and is not affiliated with, endorsed by or sponsored by Instagram or Meta. It collects only publicly available comment data and doesn't log in, collect credentials or bypass private-account controls.
Public commenter information (usernames, names, profile pictures, comment text) can still be personal data. You are responsible for processing it lawfully (e.g. under GDPR/CCPA). Collect only what you need for your purpose, and don't use it for harassment, unlawful discrimination or sensitive profiling.
Local development
cd actornpm installnpm test # unit tests (URL normalizer, comment parser, threading, response classification)npm start # run with INPUT.json