Threads Replies Scraper API
Pricing
from $1.00 / 1,000 results
Threads Replies Scraper API
Scrape Threads replies (comments): reply text, likes, reposts, author details and media, with nested replies on request. Requires a Threads Session ID.
Pricing
from $1.00 / 1,000 results
Rating
5.0
(1)
Developer
Rush
Maintained by CommunityActor stats
3
Bookmarked
188
Total users
42
Monthly active users
a day ago
Last modified
Categories
Security
Limited permissionsShare
Collect the replies (comments) under a Threads post, with each reply's author, engagement, media and place in the conversation.
What does Threads Replies Scraper API do?
Give it the links to up to 50 posts and your Threads Session ID (how to get one), and it returns a row for every reply it collects, ready to open in a spreadsheet or feed into your own tools.
What can you use it for?
- Read what people actually said under a post, instead of only how many replied
- Follow how a discussion developed, level by level, using each row's place in the conversation
- Put the replies to several posts side by side in one table
- Keep a copy of a conversation as it stood, before it changes
Features
- Up to 50 posts per run. Paste post links one per line; share links and short links work too. A link that is not a post is skipped, and the log gives its place in your list. A post listed twice is collected once.
- Nested replies, level by level. Turn on Include Nested Replies to also collect replies to replies. Every row says how deep it sits, and nested rows name the reply they answer where Threads identifies it.
- Top or Recent order. Collect replies in the order Threads ranks them, or newest first. On a busy post, Threads' ranking can end before the last replies, which follow it.
- A limit, or everything Threads lists. Set Max Replies Per Post, or set it to 0 to collect as many replies as Threads lists, which can be fewer than the number a post shows.
- Results as they arrive. Rows are saved while the run works, so you can open the dataset before it finishes.
- A run summary you can automate on. Each run says how it ended, whether any post is unfinished, and what stopped it when it did not finish.
- Resurrect continues a stopped run. A run that stops early picks up from its last saved point instead of starting over, unless its last line gives a different step.
How to Use
- Get your Session ID: the steps are just below.
- Replace the example links in Post URLs with your own post links, one per line, and paste your Session ID into Session ID.
- If you like, change Max Replies Per Post, Sort Replies By and Include Nested Replies. If you turn on nested replies, set the limit to 0, or it can fill before they are reached.
- Click Start. Rows appear in the run's dataset as they are collected, and the last line of the log says how the run ended.
- Open the results from the run's Output tab, or export the dataset in the format you need.
How to get your Session ID
Use a secondary account, not your main one. Automated access may cause Threads to flag your account or temporarily restrict it. Sign in to that account first, then follow one of the options below.
Option 1: Browser Developer Tools
- Open threads.com in the browser you signed in with
- Open Developer Tools: press F12 on Windows or Cmd+Option+I on a Mac. In Safari, first turn on the web-developer features in its Advanced settings
- In Chrome or Edge go to Application → Cookies →
https://www.threads.com; in Firefox or Safari the same list is under Storage - Find the cookie named
sessionidand copy its value - Paste it into the Session ID field in the Actor input
Option 2: Cookie Editor Extension
You can also use a browser extension like Cookie-Editor to view and copy cookies. Install the extension, visit threads.com, and search for the sessionid cookie.
Disclaimer: Cookie-Editor is a third-party extension not affiliated with this Actor. As with any browser extension that accesses cookie data, please review its permissions and use at your own discretion.
What you can paste
Paste the value of the sessionid cookie. If your browser or extension copies more with it, the Actor picks out sessionid and ignores the rest of what you pasted. Everything you paste is saved with the run's input, so paste only the value if you can.
Important notes
- Session IDs have no guaranteed lifetime. Threads can end one at any time. If a run says Threads did not accept your Session ID, copy a fresh one.
- Scheduled runs keep the Session ID they were given. Once Threads stops accepting it, every scheduled run stops at sign-in until you paste a fresh one into the schedule's input.
Input example
{"postUrls": ["https://www.threads.com/@mosseri/post/DalA5HOFvaC"],"sessionId": "your-session-id-here","maxReplies": 50,"sortOrder": "top","includeChildReplies": false}
| Field | Type | Description |
|---|---|---|
postUrls | Array | Required. Threads post links to collect replies from, one link per entry; a run collects up to 50 posts, and a longer list stops the run as it starts. threads.net links work too, and so do share links (threads.com/share/…) and short links (threads.com/t/…): each counts as one of the 50 posts |
sessionId | String | Required. Your Threads sessionid cookie |
maxReplies | Integer | Max replies per post (0 = no limit, default: 0; the input form starts at 50). Every reply counts toward it, including nested replies that appear with includeChildReplies off; the row for the item you submitted does not count toward it |
sortOrder | String | Reply order: "top" (Threads' own ranking, default) or "recent" (newest first) |
includeChildReplies | Boolean | Also collect nested replies (replies to replies). Each nested reply carries a depth (2+), and names the reply it answers in parentReplyId wherever Threads identifies it. With it off, some nested replies can still appear: the answers Threads shows directly under a reply. Default: false |
What you get
One row for the post you submitted, then one row for each reply collected under it. Every row carries the same columns:
- Row type and IDs — whether the row is the post you submitted or a reply, the post it belongs to, and the post or reply ID
- Content — text, its link, shortcode, hashtags, mentions, the accounts Threads recognised in the text, the links in the text and behind a link card, the title of that card, and the language Threads read the text in
- Author — username, display name, profile bio, user ID, profile link, profile picture, verified badge, and whether the account is private
- Engagement — likes, replies, reposts, quotes, and shares where Threads reports them, and on the row for the post you submitted, its views
- Media — type, a GIF flag, a spoiler flag, the main media link, every media link, pixel size, an audio flag, and the image description Threads provides where there is one. Photo, video and profile picture links expire, so download anything you want to keep soon after the run; a GIF's link points to the service that hosts the GIF
- Timing — when it was posted (as a date and as Unix time), when it was collected, and whether the text has been edited
- Conversation — who it is replying to, how deep it sits, the reply it answers where Threads identifies it, whether the thread's original poster liked it, whether it is pinned to the post above, who the author allows to reply, the post it quotes, and its position in the results
Output example
Long values are shortened with ... in these examples; the dataset holds every value in full. The reply's author, text and identifiers are placeholders.
The post you submitted (item_type: "post"):
{"item_type": "post","sourceUrl": "https://www.threads.com/@mosseri/post/DalA5HOFvaC","postId": "3937557373968119426","replyId": null,"postCode": "DalA5HOFvaC","postUrl": "https://www.threads.com/@mosseri/post/DalA5HOFvaC","replyUrl": null,"text": "Excited about this launch. I've been really impressed with how quickly t...","hashtags": [],"mentions": [],"mentionedAccounts": [],"urls": [],"linkTitle": null,"language": "en","username": "mosseri","userId": "63482099442","profileUrl": "https://www.threads.com/@mosseri","profilePicUrl": "https://scontent.cdninstagram.com/...","isVerified": true,"authorIsPrivate": false,"displayName": "Adam Mosseri","authorBio": "Father of three boys, married to an amazing woman, head of Instagram and supporter of Threads.","timestamp": "2026-07-09T16:10:38.000Z","timestampUnix": 1783613438,"isEdited": false,"replyControl": "everyone","isQuotePost": true,"quotedPostUrl": "https://www.threads.com/@zuck/post/DakyAavlKLZ","likeCount": 238,"replyCount": 148,"repostCount": 32,"quoteCount": 0,"shareCount": 14,"viewCount": 33157,"isLikedByAuthor": false,"isPinnedByAuthor": false,"replyToUsername": null,"depth": 0,"parentReplyId": null,"mediaType": "text","isGif": false,"isSpoiler": false,"mediaUrl": null,"mediaUrls": [],"mediaWidth": null,"mediaHeight": null,"hasAudio": null,"accessibilityCaption": null,"index": null,"scrapedAt": "2026-11-05T04:27:05.875Z"}
A reply (item_type: "reply"):
{"item_type": "reply","sourceUrl": "https://www.threads.com/@mosseri/post/DalA5HOFvaC","postId": null,"replyId": "1234567890123456789","postCode": "REPLYCODE01","postUrl": null,"replyUrl": "https://www.threads.com/@example_user/post/REPLYCODE01","text": "@meta.ai 可以幫我把這段公告翻成中文嗎?","hashtags": [],"mentions": ["@meta.ai"],"mentionedAccounts": [{"username": "meta.ai","userId": "27463547647"}],"urls": [],"linkTitle": null,"language": "zh_TW","username": "example_user","userId": "1234567890","profileUrl": "https://www.threads.com/@example_user","profilePicUrl": "https://scontent.cdninstagram.com/...","isVerified": true,"authorIsPrivate": false,"displayName": "Example User","authorBio": null,"timestamp": "2026-07-10T08:15:49.000Z","timestampUnix": 1783671349,"isEdited": false,"replyControl": "everyone","isQuotePost": false,"quotedPostUrl": null,"likeCount": 0,"replyCount": 1,"repostCount": 0,"quoteCount": 0,"shareCount": null,"viewCount": null,"isLikedByAuthor": false,"isPinnedByAuthor": false,"replyToUsername": "mosseri","depth": 1,"parentReplyId": null,"mediaType": "text","isGif": false,"isSpoiler": false,"mediaUrl": null,"mediaUrls": [],"mediaWidth": null,"mediaHeight": null,"hasAudio": null,"accessibilityCaption": null,"index": 14,"scrapedAt": "2026-11-05T04:27:06.142Z"}
What the columns mean
item_type is post for the item you submitted and reply for everything else, so you can filter by type. If the submitted item cannot be read or saved, its row is missing and the log says so. postId and postUrl are filled on post rows, replyId and replyUrl on reply rows, and postCode is the shortcode of whatever that row itself is.
sourceUrl names the post you submitted, in the form https://www.threads.com/@handle/post/SHORTCODE, whichever link you pasted, share and short links included. Group rows by it. To match rows back to your own list, compare the shortcode at the end of sourceUrl rather than the text you pasted; for a share link, the log line Entry N leads to @handle/post/CODE names its post. The author columns describe whoever wrote the item, which can differ from the handle in your link; postUrl gives the post's own address.
Empty means null in JSON and a blank cell in a spreadsheet. It means Threads stated nothing for that column on that row, so do not read it as no or zero. Two columns are the exception: text is empty when a reply has no words of its own, such as a GIF, a photo or a quoted post on its own, and quotedPostUrl is empty when a row quotes nothing, and also when the quoted post is no longer available, in which case isQuotePost is still true.
language,hasAudio,authorIsPrivate,isPinnedByAuthor,isSpoiler,shareCountandviewCountare empty when Threads states nothing.isVerified,isEditedandisLikedByAuthorread false when Threads states nothing.mentionslists every@handlewritten in the text;mentionedAccountslists the ones Threads recognised, with their account IDs.- On Threads, a private profile's posts are seen by the followers it approves and by the people it replies to, so take care before sharing rows with
authorIsPrivatetrue.
After a run
- Check the last line of the log. It says how the run ended and, when there is a step to take, what it is. If any post could not be opened or was not read, or some of its replies could not be read or saved, the last line says so instead of reporting the job complete. A post whose list Threads ended before the number it shows counts as finished, and the last line says that too, as it does for a reply whose own replies Threads did not send, and for replies left out to stay within the maximum cost.
- Stopped early? Open that run and choose Resurrect to continue from its last saved point. A new run begins from the beginning and collects the replies already saved a second time. Some endings take a different step, and the last line names it: a Session ID Threads no longer accepts or Threads asking the account to confirm something (both in the FAQ below), and a run that reached the maximum cost set for it (start a new run with a higher maximum cost and the posts its log lists under "Posts for a new run"). If what is left of the maximum cost may not cover the rest, the last line says so beside the Resurrect. A run with no closing line continues from its last automatic save, so a reply saved after that save can appear twice;
sourceUrltogether withreplyIdidentifies it. - None of the posts available? When Threads answers for each post you listed that it is not available, the run finishes successfully with no replies, and its last line says so. If no post could be collected and at least one could not be opened for another reason, the run fails and its last line says what to do. Both read
failedin the run summary, since nothing was collected, and both can nameposts_not_available: the run's own status, succeeded or failed, tells them apart. - Finished, but a post could not be opened? The log names it and says what happened. Open its link in a browser signed in to that account: if it opens there, please let us know; if it does not, check the link. The post may have been deleted, or that account may not be able to see it.
- Finished, but a post could not be collected in full? Resurrect does not continue a run that finished with rows saved: it finds the job done and collects nothing more. To try for the rest of that post, start a new run with it later, as the last line says; the new run collects that post from the start, so the replies already saved for it are collected again.
Automating with the run summary
Each run saves a short summary you can open from the Run Summary link on the run's Output tab: how many posts you submitted (each post counted once, plus any entry that is not a post link), how many were collected, how many replies and rows were saved, and whether any post is unfinished. A post that stopped at your Max Replies Per Post, where Threads' own list ended, or where rows outside Threads' ranking were left out to stay within the maximum cost (see the FAQ), counts as finished, so complete does not mean every reply a post shows. To find such a post in an automation, compare replyCount on the post's own row with how many of its rows have depth 1. A finished run reads like this:
{"status":"complete","stoppedEarly":false,"postsSubmitted":1,"postsCollected":1,"postsIncomplete":0,"repliesCollected":20,"rowsSaved":21,"postsForANewRun":[],"postsSavedInPart":[],"finishedAt":"2026-11-07T01:06:29.181Z"}
postsForANewRun lists the unfinished posts worth giving a new run, as links in the form Post URLs takes, so an automation can pass them on as they are; it is empty when there are none. Posts Threads answered are not available are not on it, and neither are posts this run saved part of: postsSavedInPart names those, and a new run collects such a post from its start and saves its rows a second time, so add one only when you want the rest of it. A run refused before it read its links carries neither list. When the last line's step is a Resurrect, the posts the Resurrect collects are on neither list unless what is left of the maximum cost may not cover it: once the resurrected run ends, its own summary lists what is left. A run stopped just as Threads stopped accepting your Session ID lists them, since a Resurrect would present the same Session ID: its log says so, and its step is a new run with a fresh Session ID.
status is complete, partial (finished, but a post could not be opened, or some of its replies could not be read or saved), stopped_early or failed (no replies collected). A post that could not be opened counts as unfinished even when running it again gets the same answer. A partial summary names no reason unless it is threads_changed, so do not retry on postsIncomplete alone: the log says for each post what happened.
A run that did not finish normally also has a reason. One reason can cover more than one next step, and the log says which:
reason | What helps |
|---|---|
session_not_accepted | A fresh Session ID, in a new run |
threads_is_limiting_reads | Wait, then Resurrect when stoppedEarly is true; otherwise start it again |
threads_not_responding | Try again after a few minutes, by Resurrect when stoppedEarly is true |
threads_changed | Threads answered in a way this version cannot read. Try again later: by Resurrect with the latest build when stoppedEarly is true, otherwise in a new run |
posts_shown_in_feed | The links are fine; try again later |
posts_not_available | Check the links; if the log says a link could not be opened just now, try again later |
time_limit_reached | Resurrect, with a longer Timeout if you like |
read_enough_for_one_run | A run with no Timeout stops after a set amount of reading; Resurrect continues it |
spending_limit_reached | A new run with a higher maximum cost |
results_not_saved | Resurrect after a few minutes |
stopped_by_request | Resurrect, unless the log says Threads stopped accepting your Session ID as the run was stopped: then a new run with a fresh Session ID and the posts postsForANewRun lists |
run_failed | The log says what helps |
While a resurrected run is still going, its summary reads stopped_early with no reason and the counts of its last saved point, so check that the run has ended before acting on its summary: until then finishedAt only says when the summary was last updated. A run that sees its Timeout coming stops by itself, says so in its last line and reads time_limit_reached. An abort that is not graceful (the API's default) ends the run at once, as does a Timeout too short for the run to wrap up: there is no closing line and no new run summary, and its dataset and log still show what was saved. If the summary cannot be saved at the end of a run, the run's last line says so, and the dataset still holds every saved row.
Frequently Asked Questions
Do I need a Session ID?
Yes: this Actor reads replies as a signed-in viewer and will not start without one. If you would rather not use an account, Threads Replies Scraper needs no Session ID and collects the replies Threads shows to visitors who are not signed in. It has lower limits per run and no Recent order, and its columns are named differently.
Is it safe to enter my Session ID?
It is treated as a secret: stored encrypted as part of your run's private input, used only to read Threads as that account during your run, and never written to logs or shared with anyone else. It still grants access to whichever account it came from, which is why a secondary account is the safer one to use.
A run stopped with a message about my Session ID. What do I do?
The run's last line says which case it is and gives the step:
- "Threads did not accept your Session ID" — the run saved nothing. Copy a fresh Session ID by following How to get your Session ID and run the same posts again. If the run is on a schedule, put the fresh one in the schedule's input too.
- "Threads stopped accepting your Session ID" — replies already collected stay in that run's results. Copy a fresh Session ID the same way and start a new run with the posts that run's log lists under "Posts for a new run", ready to paste. Resurrect would present the same Session ID again.
- "Threads is asking this account to confirm something" — a fresh Session ID alone will not help. Open threads.com in a browser while signed in to that account, do what it asks, then copy a fresh Session ID. When the run had saved anything, its last line points to "Posts for a new run": start the new run with the posts its log lists there, so nothing already saved is collected a second time. Otherwise start the run again.
Why did I get fewer replies than the post shows?
First check Max Replies Per Post: the input form starts at 50, and a run stops at that number for each post. Set it to 0 to collect as many replies as Threads lists.
The number on a post counts direct replies only. Threads can list fewer replies than the number it shows, sometimes none at all, in Top order and in Recent order alike, and a run ends where Threads stops listing them. That post counts as finished and its own row is saved, and its last line in the log says how many direct replies Threads listed against that number. If you can see the missing replies on Threads with this account, please let us know.
Two runs of the same post can return different numbers of replies. A new run collects the post from the start, so the replies already saved are collected again, and it may add none.
A run can also save more rows than the number, when nested replies come along.
How does a maximum cost work across several posts?
Posts are read one after another, in the order you list them. With Max Replies Per Post at 0, each post is read in full before the next one, so an early post with many replies can use up the maximum cost set for the run before the later posts are read; the run then stops, and its last line says how to collect the rest. With a limit set, each post stops at that limit, which spreads the cost across the posts; if the maximum cost does not cover your limit for every post, the run still stops when it is used up, and its last line says how to collect the rest.
With a limit set, a post whose ranked replies end before your limit can stop short of it, so that the maximum cost still covers your limit on the posts after it; that post's line in the log says when this happened. Room is kept for each later post at your full limit, so when a later post holds fewer replies than your limit, because the limit is far above what your posts hold or because Threads lists fewer replies than the post shows, part of the maximum cost can be left unspent while an earlier post stopped short. With 0, as above, each post is read in full in turn instead.
What happens if Threads limits access?
Threads limits how much can be read in a short period. When it does while a post is being read, the run pauses and asks again, carrying on with that post from where it was, as long as its Timeout leaves time for that. If Threads keeps limiting it, the run stops and keeps its progress: give it a while, then choose Resurrect to continue.
What is the difference between "Top" and "Recent" sort?
"Top" lists replies in the order Threads ranks them, the view Threads shows by default. "Recent" lists the newest replies first.
In Top order, the last rows of a post may fall outside Threads' ranking. Nested replies may not follow date order, so for a strict date order, sort the saved rows by timestamp.
Can I paste the link to a reply instead of a post?
Yes. On Threads a reply has its own link in the same shape as a post link, and either one works here: you get the replies underneath whatever you paste, not the wider thread it belongs to.
The item_type: "post" row is always the item you asked for. When that item is itself a reply it still carries depth: 0, and replyToUsername tells you who it was answering.
Can I scrape replies from multiple posts at once?
Yes, up to 50 posts per run. Group rows by sourceUrl. If you submit both a post and one of its replies, a reply can be listed under each link, so use sourceUrl together with replyId as a row's key.
Can I also get replies to replies (nested threads)?
Yes. Turn on Include Nested Replies and set Max Replies Per Post to 0 to follow each conversation, around five levels below the item you submitted; some conversations come back deeper than that, and replies below those levels can be left out. With a limit set, the limit can fill before any conversation is opened, and the log says when that happens.
depth says where a row sits: 0 = the item you submitted, 1 = a direct reply, 2+ = nested. parentReplyId names the reply it answers where Threads identifies it, so select direct replies with depth = 1 rather than by an empty parent. Together they let you rebuild the conversation, except where Threads does not identify a parent.
The option makes more requests on your account, so leave it off when the direct replies are all you need.
Something looks wrong?
Open an issue on this Actor's Issues tab and include the link to the run.
Integrations
Connect Threads Replies Scraper API with other apps and services using Apify integrations. Export data to Google Sheets, Slack, Zapier, Make, and many more.
More scrapers
- Threads Replies Scraper — collects replies without a Session ID, from what Threads shows to visitors who are not signed in.
Explore more social media and web scrapers on our Apify profile.
Disclaimer
This Actor is intended for learning, research, and personal use, and it is not affiliated with, endorsed by or sponsored by Threads or Meta. Replies can contain personal data such as names, handles, profile bios and profile pictures. You are responsible for using it responsibly and ethically, and for ensuring your use complies with the laws and regulations that apply to you, including data-protection law.
Threads may update its platform at any time, which could temporarily affect this Actor's functionality.
Using a Session ID involves providing authentication credentials to the Actor. We strongly recommend using a secondary account, as automated access may result in account restrictions or temporary bans. You are solely responsible for how you use this tool and any consequences that may arise from its use.
Threads replies scraper, Threads comments scraper, Threads reply API, Threads reply extractor, Threads post replies, social media scraper, Apify actor, Claude Code, OpenClaw, Gemini, Antigravity, Codex, ChatGPT