Skip to main content

Instagram comments API: full pagination with the min_id cursor

· 3 min read
Product documentation and integration guides

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_id is 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:

  1. 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.
  2. 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.