How to Get Instagram Comment Replies (Full Threads, Not Just Top-Level)
If you've ever pulled Instagram comments and felt like half the conversation was missing, you were right. Most comment endpoints, ours included until now, return top-level comments only. The replies, the back-and-forth threads where people actually argue, ask "where can I buy this," and tag their friends, sit one level down and don't come back in that first call. For sentiment work, community research, or lead-spotting, that hidden layer is often the most valuable part.
We just shipped an endpoint that fixes it. Here's how to pull the replies under any Instagram comment and reconstruct the full thread.
The two-step model (and why it exists)
Instagram threads are two levels deep: a top-level comment, and replies to it. That maps to two calls:
- Get the top-level comments with the comments endpoint. Each comment has an
id. - Get the replies for a specific comment by passing that
idascomment_idto the new replies endpoint.
Splitting it this way keeps each call cheap and lets you fetch replies only for the comments you actually care about (the ones with lots of engagement), instead of paying to pull every reply on a post. That's the design trade-off, and it's usually the right one.
Step 1: Get the comments
Base URL is https://api.sociavault.com/v1, auth is an x-api-key header, and each call costs 1 credit. Pull the post's top-level comments first:
const API_KEY = process.env.SOCIAVAULT_API_KEY;
const BASE = "https://api.sociavault.com/v1";
async function get(path, params) {
const qs = new URLSearchParams(params).toString();
const res = await fetch(`${BASE}${path}?${qs}`, {
headers: { "x-api-key": API_KEY },
});
if (!res.ok) throw new Error(`${path} failed: ${res.status}`);
return (await res.json()).data;
}
const comments = await get("/scrape/instagram/comments", {
url: "https://www.instagram.com/p/DSx1Jt5ifjn/",
});
Each top-level comment carries an id and a child_comment_count. That count is your signal: any comment where child_comment_count is above zero has replies worth fetching.
Step 2: Get the replies for a comment
Now call the replies endpoint with the post url and the parent comment_id:
import os, requests
API_KEY = os.environ["SOCIAVAULT_API_KEY"]
BASE = "https://api.sociavault.com/v1"
def get(path, **params):
r = requests.get(f"{BASE}{path}", headers={"x-api-key": API_KEY},
params=params, timeout=60)
r.raise_for_status()
return r.json().get("data")
def all_replies(post_url, comment_id, max_pages=5):
out, cursor, pages = [], None, 0
while pages < max_pages: # cap so a loop can't overspend
params = {"url": post_url, "comment_id": comment_id}
if cursor:
params["cursor"] = cursor
data = get("/scrape/instagram/comment/replies", **params)
# NOTE: comments come back keyed by index (0, 1, 2 ...), not as a list
replies = (data or {}).get("comments", {})
out.extend(replies.values() if isinstance(replies, dict) else replies)
cursor = (data or {}).get("cursor")
pages += 1
if not cursor or not (data or {}).get("has_more"):
break
return out
One real gotcha worth calling out, because it'll trip you up if you assume otherwise: the comments field in the reply response is an object keyed by index ("0", "1", "2"), not a JSON array. Use Object.values() in JS or .values() in Python rather than iterating it like a list.
Each reply gives you the useful bits: text, created_at, parent_comment_id (tying it back to its top-level comment), and a user object with username, profile_pic_url, and is_verified. Pagination is handled by cursor plus a has_more boolean, page until has_more is false.
Rebuilding the full thread
Once you have top-level comments and their replies, stitching the thread is trivial, group replies by parent_comment_id under their parent:
function buildThreads(topLevel, repliesByComment) {
return topLevel.map((c) => ({
...c,
replies: repliesByComment[c.id] ?? [],
}));
}
Now you've got the whole conversation, not just the opening lines. That's what makes the difference for the use cases people actually care about: reading genuine sentiment (the nuance lives in replies), spotting buying intent ("is this still available?" is almost always a reply), and finding the micro-influencers whose replies drive a thread. If you're mining comments for product signal, the same logic we covered for YouTube comments as product feedback applies here, replies are where the specifics hide.
The honest limits
- You need the
comment_idfirst. Replies are fetched per parent comment, so you always run the comments call before this one. There's no "give me every reply on the post" shortcut, and that's deliberate (it keeps costs predictable). - Public data only. You get publicly visible replies. Hidden, held-for-review, or deleted replies won't appear, and private accounts' replies aren't accessible.
commentsis keyed by index, not an array. Parse it defensively (values, not list iteration) or you'll get nothing.- Reply counts can drift.
child_comment_countis a point-in-time number; by the time you fetch, a reply may have been added or removed. Treat it as a strong hint, not a guarantee. - Each page is a credit. Fetching replies for hundreds of comments adds up, target the high-engagement comments rather than paginating everything.
Frequently Asked Questions
Why don't Instagram comments include replies by default?
Because Instagram threads are two levels deep, and comment endpoints return the top level only. Replies live under each comment and are fetched separately by passing that comment's id as comment_id. This keeps each call cheap and lets you pull replies only where they matter.
How do I get the replies to a specific Instagram comment?
First call the comments endpoint to get each comment's id, then call the comment replies endpoint with the post url and that comment_id. Page through with the cursor from each response until has_more is false.
What fields do reply objects include?
Each reply has text, created_at, parent_comment_id, child_comment_count, and a user object with username, profile_pic_url, and is_verified. The response also returns cursor and has_more for pagination.
Why is the comments field an object instead of an array?
The reply response returns comments keyed by index (0, 1, 2, ...), so treat it as an object, use Object.values() in JavaScript or .values() in Python. Iterating it as a list is the most common mistake here.
How much does fetching replies cost?
Each request is 1 credit, and replies are paginated, so a comment with many replies may take several pages (several credits). Fetch replies only for high-engagement comments to keep spend predictable. You start with 50 free credits, no card.
Can I get replies for private or hidden comments?
No. This returns publicly visible replies only. Hidden, held-for-review, or deleted replies, and anything on private accounts, aren't accessible, that's consistent with only ever collecting public data.
Want the whole conversation instead of just the opening lines? Start free with 50 credits, no card required and pull your first full comment thread today. Need the video's words too? See our Instagram transcript guide.
Found this helpful?
Share it with others who might benefit
Ready to Try SociaVault?
Start extracting social media data with our powerful API. No credit card required.