Threads Scraper — Posts, Profiles, Replies & Hashtags
Pricing
from $2.50 / 1,000 post scrapeds
Threads Scraper — Posts, Profiles, Replies & Hashtags
Scrape Threads posts, profiles, reply threads, search results and hashtags. Browserless, no login, and you only pay for rows actually delivered.
Pricing
from $2.50 / 1,000 post scrapeds
Rating
0.0
(0)
Developer
Ace
Maintained by CommunityActor stats
0
Bookmarked
5
Total users
4
Monthly active users
19 days ago
Last modified
Categories
Share
Scrape Threads (threads.com) without a browser and without logging in.
Give it a keyword, a #hashtag, an @username, or any Threads URL. Get back flat rows
ready for a spreadsheet, a dashboard, or an LLM pipeline.
Why this one
Threads scrapers break in two boring ways: they don't recognise the URL you gave them, and they die the moment Meta reshuffles the page. This one is built against both.
| This actor | Typical Threads scraper | |
|---|---|---|
| How it finds data | Walks the page's own JSON for any thread_items node | Hard-coded path into a Relay wrapper Meta reshuffles at will |
| URL shapes understood | profile, /replies, /media, /reposts, /@user/post/CODE, /t/CODE, threads.net, ?si= tracking links | Often just the plain profile URL |
| Stable numeric author ID | ✅ authorId on every row | Usually username only — which breaks when someone renames |
| One bad target | Skipped, with the reason; the rest still run | Whole run fails |
| What you pay for | Rows actually delivered, plus a $0.005 start fee | Start fee plus rows |
Filtered, duplicate and failed rows are never billed. Each run carries a $0.005 start fee ($0.02 on the Apify free plan; charged per GB of memory, the default is 1 GB).
What you get
Real, unedited rows from this input:
{ "queries": ["@zuck", "#buildinpublic"], "profileTabs": ["posts", "replies", "media"], "maxItems": 25 }
→ 25 rows in one run: 1 profile + 24 unique posts, zero duplicates across the three tabs.
A post
{"recordType": "post","code": "DVrwsE5EdSz","url": "https://www.threads.com/@zuck/post/DVrwsE5EdSz","text": "Meanwhile at Meta HQ","authorUsername": "zuck","authorId": "63055343223","authorFullName": "Mark Zuckerberg","authorIsVerified": true,"publishedAt": "2026-03-10T00:26:46.000Z","likeCount": 7581,"replyCount": 1192,"repostCount": 232,"quoteCount": 56,"isReply": false,"mediaType": "image","mediaCount": 1,"media": [{ "type": "image", "url": "https://instagram.fcdg4-1.fna.fbcdn.net/v/t51.82787-15/...", "width": 1080, "height": 1350 }],"hashtags": [],"sourceType": "profile","sourceUrl": "https://www.threads.com/@zuck"}
authorId is the account's stable numeric ID. Usernames get changed; this doesn't.
Use it as your join key.
A profile row
{"recordType": "profile","authorUsername": "zuck","authorId": "63055343223","authorFullName": "Mark Zuckerberg","authorIsVerified": true,"followerCount": 5721349,"biography": "Mostly superintelligence and MMA takes","bioLinks": [],"url": "https://www.threads.com/@zuck"}
Input
| Field | Type | Notes |
|---|---|---|
queries | array | Required. Keywords, #hashtags, @usernames, or Threads URLs — mixed freely. |
profileTabs | array | Which profile tabs to pull: posts, replies, media, reposts. More tabs = more posts. |
expandThreads | boolean | Also open every post that has replies and scrape the conversation. Highest yield, highest cost. |
maxItems | integer | Hard cap on delivered rows — your spend ceiling. 0 = no limit. |
minLikes / minReplies | integer | Drop low-engagement posts. Filtered posts are not billed. |
onlyVerified | boolean | Verified authors only. |
excludeReplies | boolean | Top-level posts only. |
mustHaveMedia | boolean | Only posts carrying an image or video. |
postedAfter / postedBefore | string | YYYY-MM-DD date window. |
includeProfileInfo | boolean | Emit the extra profile row shown above. |
proxyConfiguration | object | Residential strongly recommended. |
Every URL shape works
@zuck https://www.threads.net/@zuckhttps://www.threads.com/@zuck https://www.threads.com/@zuck/replieshttps://www.threads.com/@zuck/media https://www.threads.com/@zuck/post/CODEhttps://www.threads.com/t/CODE https://www.threads.com/@zuck/post/CODE?si=xyz#buildinpublic ai agents
How much data you actually get — read this
Threads shows a limited number of posts to logged-out visitors, and this actor does not log in. Measured yield per page fetch:
| Input | Posts per fetch |
|---|---|
| A post URL (post + its reply thread) | ~31 |
| Keyword search | ~20 |
| Hashtag | ~18 |
Profile /replies tab | ~8 |
Profile /media tab | ~6 |
| Profile main tab | ~4 |
So a profile returns its most recent posts, not its full history. Scraping all three
profile tabs is the way to widen that — measured ~18 unique posts for @zuck across
three tabs versus 4 from the main tab alone — and expandThreads multiplies it further
by pulling each post's replies.
If you need a complete profile archive going back months, this actor will not give you that, and no amount of retrying will change it. That is a Threads limit, not a bug, and it is stated here rather than discovered after you have paid.
Cost
You are billed $0.0025 per delivered row plus a $0.005 start fee per run ($0.02 on the Apify free plan; per GB of memory, the default 1 GB = one fee). Rows removed by your filters, duplicates, and failed pages are all free.
| Job (one run, paid plan) | Rows | Cost |
|---|---|---|
| One profile, all three tabs | ~18 | ~$0.05 |
| One keyword search | ~20 | ~$0.06 |
| One post + full reply thread | ~31 | ~$0.08 |
| 10 hashtags | ~180 | ~$0.46 |
Set maxItems to cap any run. It is a hard ceiling.
Honest limitations
- No full profile history. See the table above. Deeper paging sits behind Threads' internal API and is deliberately not attempted.
languageis almost always empty. Threads does not populatedetected_languagefor logged-out requests, so there is deliberately no language filter in the input — a filter that silently keeps everything is worse than no filter at all.- Private and non-existent accounts return nothing. You get an explicit
does not exist or has no public contentmessage, and no rows are billed. - Threads rate-limits. Each retry rotates to a fresh proxy session and re-establishes cookies, which is what actually clears a block — a fresh IP alone gets challenged again. If everything is blocked the run fails and bills no rows (only the start fee).
- A post with no replies yields one row.
expandThreadsonly helps where conversation exists.
Why did my run fail?
A failed run always carries a plain-English reason in its status message (top of the run
page, and the statusMessage field in the API) and never bills any rows — only the
start fee applies. The four causes:
| Status message starts with… | What it means | Fix |
|---|---|---|
None of the … input value(s) could be understood | Every input was a URL shape the actor does not know. Threads URLs must be a profile, a profile tab (/replies, /media, /reposts), a post (/@user/post/CODE) or a short link (/t/CODE). | Check the URL. Anything that is not a Threads URL is treated as a keyword search, so bare words always work. |
"postedAfter" must be a date like "2026-01-31" | A date filter was not an ISO date. | Use YYYY-MM-DD. |
None of the requested targets exist … (HTTP 404) | Threads returned 404 for every target. | Check the spelling. |
Threads rate-limited or refused every attempt | Threads blocked every fetch even after IP rotation — either an outright HTTP 429, or (under load) pages served empty right after one, which the actor retries and then reports as a block rather than as "no posts". Not caused by your input. | Wait a few minutes and retry. Avoid launching many runs at the same moment — bursts of parallel runs are what Threads rate-limits; put several targets in one run's queries instead, or space scheduled runs out. Raising maxRetries also helps. |
A run with at least one good target succeeds and delivers what it could; the bad ones are
listed in the run log and in the SUMMARY record of the key-value store.
Use it for
- Brand & competitor monitoring — watch a hashtag or keyword on a schedule.
- Creator research — recent posts, engagement counts, and verified status per account.
- Conversation mining — pull a viral post's full reply thread for sentiment or support signals.
- LLM pipelines — flat rows, no HTML, stable numeric IDs to join on.
Scheduling
Point the Apify Scheduler at this actor with a handful of keywords and postedAfter set to
yesterday to build your own Threads history over time. Because billing is per delivered
row plus a small start fee, and duplicates are removed within each run, a daily watch stays cheap.