Threads Scraper — Posts, Profiles, Search & Hashtags avatar

Threads Scraper — Posts, Profiles, Search & Hashtags

Pricing

Pay per usage

Go to Apify Store
Threads Scraper — Posts, Profiles, Search & Hashtags

Threads Scraper — Posts, Profiles, Search & Hashtags

Scrape Threads posts, profiles, hashtags and search results without login. Exact like/reply/repost counts, images, videos, batch mode, pay per result.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Parker

Parker

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

10 days ago

Last modified

Share

Languages: README.md | README.zh-TW.md

Scrape Threads without logging in: posts, profiles, hashtag feeds, search results and replies — with exact engagement counts, full-resolution media, and batch processing.

What you get

Every post is one dataset record:

{
"id": "DZaExc0ESvs",
"url": "https://www.threads.com/@zuck/post/DZaExc0ESvs",
"author": {
"username": "zuck",
"displayName": "Mark Zuckerberg",
"profileUrl": "https://www.threads.com/@zuck",
"avatarUrl": "https://...",
"isVerified": true
},
"content": "Interesting Biohub conversation with No Priors...",
"timestamp": "2026-06-06T21:41:30.000Z",
"stats": { "likes": 832, "replies": 302, "reposts": 57, "shares": 0, "quotes": 23 },
"images": ["https://..."],
"videos": [],
"links": ["https://open.spotify.com/..."],
"source": "profile_posts",
"profile": "zuck",
"scrapeMethod": "graphql"
}

Counts are exact. Most Threads scrapers read the numbers off the rendered page, where Threads writes 1.5K and 5.6M — so 1,543 arrives as 1500, and a profile with 5,687,751 followers is recorded as 5,600,000. This Actor reads Threads' own JSON payloads, so you get the real integers. It also means extraction does not break when Threads ships a UI change or serves a different interface language.

No login requiredAll four actions work anonymously. Cookies are optional.
Exact statslikes, replies, reposts, quotes as integers, never rounded.
Full-resolution mediaLargest image variant, carousel media, videos, GIFs, link previews.
Batch modeMany keywords / usernames / hashtags / post URLs in one run.
TransparentEvery record says which engine produced it (scrapeMethod).

Quick start

  1. Set Action to Search Posts.
  2. Type a keyword, e.g. openai.
  3. Set Max Items to 20.
  4. Click Start.

That's it — results land in the Output tab. To scrape a profile instead, switch Action to User Profile and enter a username without the @.

Proxy. Meta blocks datacenter IPs aggressively. Residential proxies succeed far more often, at a higher cost per GB. Datacenter proxies are usually fine for low-volume profile and post runs.

Pricing

This Actor uses pay per event — you pay for results, not for compute time.

$5.00 per 1,000 results — every stored record costs the same, whether it is a post, a reply, a search hit or a profile.

EventWhen it firesPrice
actor-startOnce per run$0.005
post-outputPer post, reply or search/hashtag result stored$0.005
profile-outputPer profile record stored$0.005

A profile run with includePosts charges one profile-output plus one post-output per post returned. A 500-post run costs $2.51: 500 × $0.005, plus half a cent to start.

Two guarantees worth knowing:

  • You are only charged for stored results. Charging happens after the record is written, never before.
  • maxItems is capped to your budget before scraping starts. If your run's charge limit only covers 30 posts, the Actor scrapes 30 and finishes as a success with a status message saying so — it never overruns the limit.

The Pricing tab on this Actor's page is the source of truth.

Input

Set action to one of search, hashtag, profile, post. Only the fields for the chosen action are used.

Common

FieldTypeDescriptionDefault
actionstringsearch, hashtag, profile or postprofile
maxItemsintegerMax posts to store (1–1000)50
proxyConfigurationobjectProxy settingsApify Proxy

Per action

ActionRequiredOptional
searchkeywordfilter (recent | top)
hashtagtag (with or without #)filter
profileusername (without @)includePosts (default true)
postpostUrlmaxReplies (falls back to maxItems)
{ "action": "search", "keyword": "artificial intelligence", "filter": "recent", "maxItems": 50 }
{ "action": "profile", "username": "zuck", "includePosts": true, "maxItems": 20 }
{ "action": "post", "postUrl": "https://www.threads.com/@zuck/post/ABC123xyz", "maxReplies": 50 }

Rate limiting

FieldTypeDescriptionDefault
requestDelayMsintegerDelay before each page load1000
maxRetriesintegerRetries when a page fails or is rate limited3

Retries use exponential backoff, and a login wall or rate limit rotates to a fresh session and proxy IP before retrying.

Authentication (optional)

Cookies unlock the location and joinedDate profile fields and help when Threads shows a login wall. Scraping while logged in carries a risk to that account — use a throwaway one.

FieldTypeDescriptionDefault
useCookiesbooleanEnable cookie/storage injectionfalse
storageStateobjectPlaywright storageState.json content

To export: log into Threads with Playwright, then await context.storageState({ path: 'storageState.json' }), and paste the JSON.

If useCookies is on but storageState is empty, the run falls back to no-auth mode with a warning. Only cookies and localStorage for Threads domains are injected; sessionStorage is not supported.

Output

Post record

FieldTypeDescription
idstringThreads short code, unique per post
urlstringDirect link to the post
author.usernamestringAuthor's handle
author.displayNamestringAuthor's display name
author.profileUrlstringLink to the author's profile
author.avatarUrlstringAvatar image URL
author.isVerifiedbooleanWhether the author is verified
contentstringPost text
timestampstringISO 8601 publish time
stats.likesintegerLikes
stats.repliesintegerReplies
stats.repostsintegerReposts
stats.sharesintegerReshares — Threads does not report this for every post
stats.quotesintegerQuote-posts (JSON tiers only)
imagesarrayFull-resolution image URLs, incl. carousels and link previews
videosarrayVideo URLs
linksarrayExternal links
quotedPostobjectMinimal quoted-post info, if present
sourcestringsearch, hashtag, post, reply, profile, profile_posts
parentIdstringFor replies: the post being replied to
profilestringFor profile_posts: the profile that was scraped
scrapeMethodstringembedded, graphql or dom — see below

Profile record

Marked with type: "profile".

FieldTypeDescription
usernamestringHandle, without @
displayNamestringDisplay name
profileUrlstringProfile URL
avatarUrlstringAvatar image URL
biostringBio text
isVerifiedbooleanVerified badge
followersCountintegerFollowers — exact unless scrapeMethod is dom
followingCountintegerUsually absent, see FAQ
postsCountintegerUsually absent, see FAQ
locationstring | nullRequires login cookies
joinedDatestring | nullRequires login cookies
partialbooleanTrue when optional fields are missing
missingFieldsarrayWhich fields were unavailable

Posts from the profile page are stored as separate records with source: "profile_posts".

scrapeMethod — knowing when data degrades

ValueMeaning
embeddedRead from the JSON shipped with the page. Exact counts.
graphqlRead from an intercepted GraphQL response. Exact counts.
domFallback: parsed from rendered HTML. Counts may be rounded, some fields absent.

A healthy run is almost entirely embedded/graphql. If you see mostly dom, Threads has changed its payload and the fallback is carrying the run — please open an issue.

Run summary

Each run writes a RUN_SUMMARY record to the key-value store, linked from the Output tab: items per source, the engine mix, charged events and the stop reason.

{
"totalItems": 13,
"posts": 12,
"profiles": 1,
"bySource": { "search": 3, "hashtag": 3, "profile": 1, "profile_posts": 3, "post": 1, "reply": 2 },
"engineMix": { "embedded": 13 },
"engineMixPercent": { "embedded": 100 },
"stopReason": null
}

Data quality

Posts missing content, author or a valid timestamp are dropped rather than stored. Profiles are kept even when incomplete, but flagged with partial: true and missingFields.

Batch mode

Process many targets in one run. Batch mode activates when at least one list is non-empty; the single-value fields are then ignored.

{
"action": "search",
"keywords": ["vibe coding", "machine learning"],
"usernames": ["zuck", "openai"],
"tags": ["AI", "tech"],
"postUrls": ["https://www.threads.com/@user/post/ABC123"],
"maxItems": 20,
"concurrency": 2
}
FieldTypeDescriptionDefault
keywordsarraySearch keywordsunset
usernamesarrayUsernames, without @unset
tagsarrayHashtags, without #unset
postUrlsarrayPost URLsunset
concurrencyintegerTargets processed in parallel (1–5)2

maxItems applies per target. Higher concurrency is faster but much more likely to trip rate limiting.

FAQ

Why do I get fewer results than maxItems? Threads caps what it serves anonymously — roughly 10 posts for a search and 20 for a profile, varying by account and query. The Actor delivers everything it can reach; supplying login cookies raises the ceiling.

Do I need to log in? No. All four actions work anonymously. Cookies only add location / joinedDate and help past login walls — and put the account you use at some risk.

Why are followingCount and postsCount empty? Threads does not send them to anonymous requests at all — the fields are absent from the payload, not merely hidden. Rather than invent numbers, the Actor lists them in missingFields.

What happens if Threads shows a login wall? The session and its proxy IP are retired and the request is retried on a fresh identity. If every retry is blocked, the run fails with a status message saying so rather than quietly returning an empty dataset.

How do I avoid rate limiting? Use residential proxies, raise requestDelayMs, lower concurrency, and leave a few minutes between runs.

Can I scrape private accounts? No. Only public data. Private accounts, deleted posts and region-restricted content are not accessible.

Why is some post text truncated? Threads truncates long posts in feeds. Scrape the post URL directly with the post action to get the full text.

Are usernames with dots supported? Yes — @user.name works.

Is this legal? The Actor collects only publicly visible data and does not bypass access controls. You are responsible for how you use the data, including compliance with Threads' Terms of Service, applicable copyright, and data-protection law such as GDPR when records concern identifiable people. Cookie authentication is opt-in and may breach Threads' terms for the account used. See the disclaimer below.

Is there an official API? Yes — the Threads API is the better choice for accessing your own account data: higher limits, full history, no blocking. This Actor covers the public data the API does not expose.

Limitations

Honest expectations, so nothing surprises you mid-run:

  • Volume is capped by Threads, not by this Actor. Infinite scroll stops serving after a while, so results may be fewer than requested.
  • No private, deleted or region-restricted content.
  • Rate limiting is real; frequent runs from the same IP will hit it.
  • Login walls appear intermittently and are retried on a new session, but a sustained wall will end the run.
  • followingCount / postsCount are unavailable anonymously.
  • Threads can change its payload at any time. scrapeMethod and the weekly smoke test exist so that gets caught quickly.

Development

npm install
npm run lint
npm run build
npm test # offline: fixtures + local servers
npm run smoke:live # live checks against threads.com

npm run smoke:auth runs the authenticated profile check; supply THREADS_STORAGE_STATE_PATH=/path/to/storageState.json or THREADS_STORAGE_STATE_JSON='{"cookies":[...]}'.

Fixtures under test/fixtures/ are generated by node scripts/capture-fixtures.mjs and must never be hand-edited — the mapper tests assert exact values from them.

Support

Report problems via the Issues tab on the Actor page. Including the run ID and the RUN_SUMMARY record makes diagnosis much faster.

Changelog

See CHANGELOG.md. Current version: 0.2.

License

Apache License 2.0 — see LICENSE.

Disclaimer

This tool collects publicly available data for research and analysis. You are responsible for using it in compliance with Threads' Terms of Service and applicable law. The authors accept no responsibility for misuse.


Keywords: Threads scraper, Threads API, Meta Threads, social media scraper, Instagram Threads, Threads posts, Threads data extraction, social media monitoring, Threads automation, influencer discovery, follower count scraper