Instagram comments API: full pagination with the min_id cursor
Scraping Instagram comments looks trivial until you notice pages overlapping or comments silently missing. The route has a pagination contract that is easy to get wrong; this post documents the exact protocol behind the media comments endpoint.
The endpoint
GET /ig/media/comments/{pk}?sort_order=recent&count=30&min_id=<cursor>
The media argument accepts a numeric pk or the shortcode from the
post URL (Deu3BoCBbDP from instagram.com/p/Deu3BoCBbDP/) — no
oEmbed resolution needed.
Rule one: always sort_order=recent
Without it you get a ranked preview — roughly fifteen comments Instagram considers interesting. Ranked pages come from different pool accounts and overlap between requests: collecting them produces duplicates and gaps.
With sort_order=recent the contract changes completely:
- pages are strictly chronological (newer → older)
- pages are disjoint — concatenation is the final order, no sorting needed
- the cursor
next_min_idis always present while more comments exist
Rule two: the cursor is next_min_id, never max_id
The response carries next_min_id (a long JSON string with cursor
tokens — pass it back verbatim, URL-encoded; SDKs do this for you).
next_max_id is always null on this route: the classic max_id
pagination used by followers endpoints does not work here.
from getsocialapi import Client
ig = Client(api_key="gsa_live_...").instagram
comments, cursor = [], None
while True:
page = ig.media_comments("Deu3BoCBbDP", count=30,
sort_order="recent", min_id=cursor)
comments += page["comments"]
cursor = page.get("next_min_id")
if not cursor:
break
print(len(comments), "comments collected")
Example observations
The figures below are illustrative observations, not a reproducible benchmark or a performance guarantee. Response sizes, latency and coverage depend on the target and upstream availability. Before sizing a production export, record the date, endpoint, parameters, page count and deduplicated item count for your own test.
Collecting every comment of a viral post (105 comments declared): 7
requests, 19.9 seconds total, zero duplicates, zero losses. Real
page size is 12–20 comments regardless of count (accepted range
1–50, effectively a hint).
Two honest caveats:
- The sum is below
comment_count. The counter includes spam-filtered comments nobody can see through any client. Expect 5–15% fewer items than the declared number on aged posts. - Replies need a second pass. Each root comment carries
child_comment_count; threads are collected separately.
Bonus: likers and the media card
The same media argument works for the media card
(items[0]: pk, media_type, caption, like/comment/view counts, owner)
and likers (up to ~100 users,
no pagination) — handy to enrich a comments export with post metadata.
Takeaways
sort_order=recent + verbatim next_min_id until null is the complete
protocol. Ten lines of Python, one request per ~15 comments, and the
full comment section of any public post lands in your database —
open an account and the
first 100 calls are on us.
Build with GetSocialAPI
Explore Instagram API for capabilities, pricing and integration examples. Create an account to start with 100 free calls, or follow the quickstart.