Threads Scraper: Profiles, Posts, Search, Replies avatar

Threads Scraper: Profiles, Posts, Search, Replies

Pricing

$2.00 / 1,000 results

Go to Apify Store
Threads Scraper: Profiles, Posts, Search, Replies

Threads Scraper: Profiles, Posts, Search, Replies

Scrape Meta Threads profiles, posts, keyword search results, and post replies in one actor. Paste a username, a profile URL, a post URL, or a keyword and the mode is detected for you. No login, no OAuth, no app review.

Pricing

$2.00 / 1,000 results

Rating

0.0

(0)

Developer

Sourabh Kumar

Sourabh Kumar

Maintained by Community

Actor stats

2

Bookmarked

332

Total users

136

Monthly active users

6 days ago

Last modified

Share

Meta Threads scraper: profiles, full post history, search and replies

Scrape Meta Threads profiles, posts, search results and replies in one actor, with one input field and no login. Paste a username, a post URL or a keyword, and the mode is detected for you.

$2 per 1,000 results. No per-run fee, no monthly minimum, no subscription.

Works for public accounts on threads.com worldwide, except the few that hide from search engines (see Limitations). Posts in any language come back unchanged: the actor doesn't translate or strip non-Latin scripts.

It goes deep. A profile page shows only the newest 15 to 33 posts, but posts mode keeps going back through the account's history until it reaches your limit or the account's first post. Replies work the same way: switch on Get all replies and the actor pages through thousands of them.

Why this scraper, vs. Meta's official API or other actors

Meta's Threads API is real and free. Its keyword search is capped at 2,200 queries per rolling 24 hours, needs OAuth plus app review for the keyword-search permission, and most analytics cover only the developer's own posts. That's enough for first-party publishing. It's not enough for monitoring competitors, scraping a competitor's profile, or backfilling historical posts.

Many Apify alternatives cover only one or two of these jobs, and most add a start fee on every run. Here it's one input box for all four.

ConcernMeta's official APIMost Apify Threads scrapersThis actor
App registration / OAuthRequiredNoneNone
Search query cap2,200 per 24 hoursNoneNone
Modes you getPublishing + own analyticsOften one or two per actorAll four: profile, posts, search, replies
Post historyYour own posts onlyVariesBack to the account's first post
Replies extractionOnly on your own postsOften missingYes, on any public post
Reply depthn/aWhatever the page embedsWhatever the page embeds, or every reply with one checkbox
Per-run start feen/aCommon ($0.005 to $0.02)None
Per 1,000 resultsFree, but cappedThe top-ranked ones: $2.50 to $20$2.00

What data can you extract?

๐Ÿ‘ค Username, full name, bioโœ… Verified flag, follower count๐Ÿ–ผ๏ธ Profile picture (HD)๐Ÿ”— Bio links
๐Ÿ“ Post text + post codeโค๏ธ Like, repost, quote, reply countโ†—๏ธ Share count๐Ÿ‘๏ธ View count (post URLs)
๐Ÿ“ท Image URLs (single + carousel)๐ŸŽฌ Video URLs (direct MP4)๐Ÿ“Œ Pinned statusโœ๏ธ Edited flag
๐Ÿท๏ธ Topic tag@๏ธโƒฃ Mentions array๐ŸŒ URLs array๐Ÿค Paid-partnership flag
๐Ÿ”— Link preview cardโ†ฉ๏ธ Reply linkage (who a post replies to)๐Ÿ†” Stable user ID๐Ÿ“ Media dimensions
๐Ÿ™‹ Author name, ID, verified flag, avatar on every post๐Ÿ’ฌ Quoted post๐Ÿ“Š Poll options and vote counts๐ŸŽต Song and artist
๐Ÿ“ Tagged location๐Ÿ”’ Who can reply๐ŸŽž๏ธ Inline Giphy stickers๐Ÿ”Ž Real match vs. context in search

The actor extracts everything Threads serves to a logged-out browser. It does not extract likers lists, follower lists, or per-post analytics. Those live behind login.

Profile mode

A single record per username, with the account's newest posts nested inside posts[] (15 to 33, depending on the account). Each nested post carries the full post field set. Profile mode doesn't page back through older posts. Use posts mode for that.

Posts mode

One flat record per post. It starts with the posts on the profile page, then goes back through the account's older posts until it reaches Max Results, your per-input limit, or the account's first post. In testing, one account's entire history (404 posts, back to July 2023) came back in about 2 minutes.

Search mode

One record per post, with the same full field set as posts mode. A keyword returns roughly 40 to 60 posts. When the matching post is a reply, Threads also sends the post it replies to, so the reply makes sense. Those rows carry isSearchMatch: false. Filter on isSearchMatch: true to keep only real matches.

Replies mode

One record for the parent post (the only place viewCount is populated) plus one record per reply, each carrying the full post field set.

A post page carries only a slice of its replies, sometimes none at all. Turn on Get all replies to page through the rest: on one busy post that meant 4,954 rows instead of the 10 on its page. Every reply is a charged result, so set a limit first.

How to scrape Threads: step by step

  1. Create a free Apify account. Takes 30 seconds, no card needed.
  2. Open Threads Scraper in the Apify Console.
  3. Paste any combination of @usernames, profile URLs, post URLs, or search keywords into the URLs field.
  4. Set Max Results (total), and Max results per input if you want a fixed number from each account or keyword.
  5. Click Start. A single profile or keyword usually finishes in 5 to 30 seconds. Going back through hundreds of older posts or thousands of replies takes a few minutes.
  6. Export as JSON, CSV, or Excel, or fetch via the Apify API.

How much does Threads Scraper cost?

Pay-per-result pricing.

  • Per 1,000 results: $2.00
  • Free-plan yield (Apify's $5/month credits): roughly 2,500 results.
  • Starter-plan yield ($29/month): about 14,500 results per month.
  • No per-run fee. No subscription lock-in.

Both limits are spending limits too: you're never charged for more rows than Max Results (total) allows. Bad input costs nothing. A typo'd handle or an unsupported link is skipped and reported, not billed.

Input

Paste anything. The actor figures out the mode.

{
"urls": [
"@zuck",
"https://www.threads.com/@nike",
"https://www.threads.com/@zuck/post/DeZtp-TkQHh",
"AI startups",
"#threads"
],
"maxResults": 0
}
FieldTypeDefaultNotes
urlsstring[]["https://www.threads.com/@zuck"]Mix of profile URLs, @usernames, post URLs, profile /replies and /media tabs, search keywords or search URLs. Mode is auto-detected per entry.
modeenum(auto)Override auto-detection. Values: profile, posts, search, replies.
maxResultsinteger50Most rows for the whole run, across every entry, and the most you can be charged for. 0 = no limit.
maxResultsPerInputinteger(none)Most rows from each entry: per account in posts mode, per keyword in search, per post in replies mode. Leave empty for no per-entry limit.
fetchAllRepliesbooleanfalseReplies mode only. Page past the handful of replies the post page carries. Ignored by the other modes.

The two limits work together, and the run stops at whichever is hit first. To get 200 posts from each of 3 accounts, set maxResultsPerInput to 200 and maxResults to 600 (or 0).

Auto-detection rules

  • https://threads.com/@zuck โ†’ profile
  • @zuck (leading @ required, ASCII handle โ‰ค30 chars) โ†’ profile
  • https://threads.com/@zuck/replies or /media โ†’ that tab's posts
  • https://threads.com/@zuck/post/<code> or a https://threads.com/t/<code> short link โ†’ replies
  • AI startups, #ai, or a phrase that starts with a handle, like @nike shoes โ†’ search
  • A search URL pasted from the browser โ†’ that search, including the Tags tab
  • Empty input โ†’ runs @zuck as a sample

Share-link tracking parameters (?ref=share, ?fbclid=..., ?utm_source=...) and URL fragments (#section) are stripped before parsing, so social-media share links work as-is. The same post or account pasted twice, as a short link, with share parameters, on threads.net or in different capitals, runs and bills once.

Recipes (ready-to-paste)

Get a Threads profile and its latest posts

{ "urls": ["@zuck"], "maxResults": 1 }

Returns one profile record with posts[] containing the account's newest posts.

Get an account's post history

{ "urls": ["@mosseri"], "mode": "posts", "maxResults": 500 }

Goes back through older posts until it has 500 or reaches the account's first post. Use "maxResults": 0 for everything.

Get the same number of posts from several accounts

{
"urls": ["@nike", "@adidas", "@puma"],
"mode": "posts",
"maxResultsPerInput": 200,
"maxResults": 0
}

Up to 200 posts from each account, 600 in total.

Pull engagement on a specific Threads post

{ "urls": ["https://www.threads.com/@zuck/post/DeZtp-TkQHh"] }

Returns the parent post with viewCount, likeCount, share/repost/quote counts, plus the replies the post page carries.

Get every reply on a post, not just the first few

{
"urls": ["https://www.threads.com/@zuck/post/DeZtp-TkQHh"],
"fetchAllReplies": true,
"maxResults": 500
}

Pages through the full reply list. Each reply is a charged result, so maxResults is what keeps the bill predictable.

Search Threads by hashtag or keyword

{ "urls": ["#ai", "AI startups", "Apify"], "maxResultsPerInput": 30, "maxResults": 90 }

Each entry runs as a separate search. Keep only isSearchMatch: true rows if you don't want the context posts.

Bulk-scrape multiple profiles in one run

{ "urls": ["@zuck", "@instagram", "@nike", "@apple"], "maxResults": 0 }

One profile record per account. maxResults: 0 removes the cap.

Output

Real records copied verbatim from live runs, with every field the mode returns. Long CDN URLs are shortened at the ? for readability, and the profile example keeps one of its nested posts. A null is genuinely null in that mode, never a field dropped to save space.

Profile record (auto-detected from @username or profile URL)

{
"type": "profile",
"username": "zuck",
"fullName": "Mark Zuckerberg",
"bio": "Mostly superintelligence and MMA takes",
"followerCount": 5744949,
"isVerified": true,
"profilePicUrl": "https://scontent-iad6-1.cdninstagram.com/v/t51.82787-19/825322135_17989325280103224_1252773933700107438_n.jpg?...",
"posts": [
{
"postCode": "DeZtp-TkQHh",
"text": "Introducing Muse Wonder, our new family of frontier models with state of the art performance for personal and professional agentic work.",
"likeCount": 1530,
"repostCount": 105,
"quoteCount": 49,
"replyCount": 225,
"shareCount": 116,
"viewCount": null,
"postedAt": "2026-10-12T16:56:29.000Z",
"imageUrls": [
"https://scontent-iad6-1.cdninstagram.com/v/t51.82787-15/844965867_17991705567103224_8296143909108287920_n.webp?..."
],
"postUrl": "https://www.threads.com/@zuck/post/DeZtp-TkQHh",
"hashtags": [],
"mentions": [],
"urls": [],
"isPaidPartnership": false,
"isEdited": false,
"isPinned": false,
"hasAudio": false,
"accessibilityCaption": null,
"videoUrls": [],
"linkPreview": null,
"isReply": false,
"replyToUsername": null,
"rootPostUsername": null,
"topicTag": null,
"mediaWidth": 2160,
"mediaHeight": 3260,
"authorId": "63055343223",
"authorFullName": "Mark Zuckerberg",
"authorIsVerified": true,
"authorProfilePicUrl": "https://scontent-iad6-1.cdninstagram.com/v/t51.82787-19/825322135_17989325280103224_1252773933700107438_n.jpg?...",
"stickerUrls": [],
"replyControl": "everyone",
"quotedPost": null,
"poll": null,
"music": null,
"location": null
}
],
"scrapedAt": "2026-10-13T12:24:12.947Z",
"url": "https://www.threads.com/@zuck",
"userId": "63055343223",
"isPrivate": false,
"bioLinks": [],
"profileTags": [
"AI Threads",
"UFC Threads",
"AI",
"MMA",
"memes"
]
}

Post record (mode: "posts")

Same fields as a single entry inside profile.posts[], plus type: "post", username and scrapedAt.

Search record (mode: "search" or auto-detected)

{
"type": "search",
"query": "sourdough",
"username": "cheffsonni",
"postCode": "DdpfPEBD2Re",
"text": "markisa sourdough bread\n๐Ÿค˜๐Ÿ”ฅ๐Ÿค˜",
"likeCount": 36,
"postUrl": "https://www.threads.com/@cheffsonni/post/DdpfPEBD2Re",
"scrapedAt": "2026-10-13T12:24:22.952Z",
"repostCount": 0,
"quoteCount": 0,
"replyCount": 8,
"shareCount": null,
"viewCount": null,
"postedAt": "2026-09-23T23:26:57.000Z",
"imageUrls": [
"https://scontent-iad3-1.cdninstagram.com/v/t51.71878-15/821708703_1059028133626792_1648431282156308925_n.jpg?..."
],
"hashtags": [],
"mentions": [],
"urls": [],
"isPaidPartnership": false,
"isEdited": false,
"isPinned": false,
"hasAudio": true,
"accessibilityCaption": null,
"videoUrls": [
"https://scontent-iad3-1.cdninstagram.com/o1/v/t2/f2/m86/AQOggWKdljZgDdcyG9RHMLqDIG03Cnym85JMhuGJaKuOmxVU3j2eRGmcTC3MWySXxTEPLWTY9R7NqM4ss1DriUnCZagLnw0inO6WfZg.mp4?..."
],
"linkPreview": null,
"isReply": false,
"replyToUsername": null,
"rootPostUsername": null,
"topicTag": null,
"mediaWidth": 720,
"mediaHeight": 1280,
"isSearchMatch": true,
"authorId": "42396593289",
"authorFullName": "Cheff Sonni Bakery",
"authorIsVerified": false,
"authorProfilePicUrl": "https://scontent-iad6-1.cdninstagram.com/v/t51.82787-19/764881017_18076655090409290_6330035882206804282_n.jpg?...",
"stickerUrls": [],
"replyControl": "everyone",
"quotedPost": null,
"poll": null,
"music": null,
"location": {
"id": "373605448268596",
"name": "Markisa"
}
}

Search records carry the same field set as posts mode, so there is no need to re-run a result to get its engagement. viewCount is the one exception: it is only available when you scrape a post URL directly.

Reply record (auto-detected from /post/<code> URL)

{
"type": "reply",
"parentPostCode": "DeZtp-TkQHh",
"parentUsername": "zuck",
"isParent": false,
"username": "_randomdev001",
"text": "Impressive stuff.\nDoes it beat OpenAIs Dots though?",
"likeCount": 0,
"viewCount": null,
"postedAt": "2026-10-12T16:59:36.000Z",
"postUrl": "https://www.threads.com/@_randomdev001/post/DeZuAywDEWf",
"scrapedAt": "2026-10-13T12:24:20.078Z",
"postCode": "DeZuAywDEWf",
"repostCount": 0,
"quoteCount": 0,
"replyCount": 0,
"shareCount": null,
"imageUrls": [],
"hashtags": [],
"mentions": [],
"urls": [],
"isPaidPartnership": false,
"isEdited": false,
"isPinned": false,
"hasAudio": false,
"accessibilityCaption": null,
"videoUrls": [],
"linkPreview": null,
"isReply": true,
"replyToUsername": "zuck",
"rootPostUsername": "zuck",
"topicTag": null,
"mediaWidth": null,
"mediaHeight": null,
"authorId": "63095976534",
"authorFullName": "Peter",
"authorIsVerified": false,
"authorProfilePicUrl": "https://scontent-iad3-1.cdninstagram.com/v/t51.82787-19/641717925_17951034903096535_856164541309490688_n.jpg?...",
"stickerUrls": [],
"replyControl": "everyone",
"quotedPost": null,
"poll": null,
"music": null,
"location": null
}

The parent record (isParent: true) is the only row that carries viewCount, on text and video posts alike. Reply rows have viewCount: null, because Threads publishes a view count on the post you requested and not on each reply beneath it.

Field availability by mode

Fieldprofilepostssearchreply (parent)reply (child)
type / username / scrapedAtโœ…โœ…โœ…โœ…โœ…
text / postCode / postUrl / postedAtnestedโœ…โœ…โœ…โœ…
likeCount / repostCount / quoteCount / replyCount / shareCountnestedโœ…โœ…โœ…โœ…
viewCount---โœ…-
hashtags / mentions / urls / linkPreview / topicTagnestedโœ…โœ…โœ…โœ…
isReply / replyToUsername / rootPostUsernamenestedโœ…โœ…โœ…โœ…
isPaidPartnership / isEdited / isPinned / hasAudio / accessibilityCaptionnestedโœ…โœ…โœ…โœ…
imageUrls / videoUrls / mediaWidth / mediaHeightnestedโœ…โœ…โœ…โœ…
authorId / authorFullName / authorIsVerified / authorProfilePicUrlnestedโœ…โœ…โœ…โœ…
stickerUrls / replyControl / quotedPost / poll / music / locationnestedโœ…โœ…โœ…โœ…
isSearchMatch / query--โœ…--
parentPostCode / parentUsername / isParent---โœ…โœ…
followerCount / bio / profilePicUrl / fullName / isVerified / urlโœ…----
userId / isPrivate / bioLinks / profileTagsโœ…----

"nested" means the field appears inside the profile record's posts[] array, not at the top level.

A few nulls are the truth about the post, not gaps:

  • mediaWidth and mediaHeight are null on text-only posts. There's no media to measure.
  • likeCount is null when the author hides like counts. Threads shows no number, so neither do we.
  • quotedPost, poll, music and location are null unless the post has one. Most don't.
  • shareCount is usually null on replies. Threads rarely reports reshares of a reply.
  • hashtags is usually empty. Threads has largely moved from inline #hashtags to a single topic tag per post, which is what topicTag gives you.

Limitations

  • Accounts hidden from search engines can't be scraped. Some accounts (we've seen it on a few news brands) turn off search-engine visibility, and Threads then shows them only to logged-in visitors. The run reports them as not available, at no charge.
  • Search returns roughly 40 to 60 posts per keyword. That's what Threads shows a logged-out visitor, and it's Threads' own Top ranking. A Recent sort and date filters aren't available.
  • viewCount exists only on a post you scrape by URL. Feeds, search results and individual replies don't carry it.
  • The /media and /replies profile tabs return their first page only. Use the profile URL in posts mode to go further back.
  • The Reposts tab isn't supported. A reposts URL is reported as unsupported and not billed.
  • Very deep runs can stop early. Threads limits how fast one server can page. When that happens you keep every row collected so far, and the run's status message says it stopped early and why.

FAQ

How much does Threads Scraper cost?

Threads Scraper uses pay-per-result pricing. You pay $2 for 1,000 results. The Apify Free plan gives you $5 in usage credits a month, enough for around 2,500 results. If you run regularly, the $29/month Starter plan covers about 14,500 results.

No subscription lock-in. Pause whenever.

How do I know whether a run got everything?

Read the run's status message. A complete run starts with "Delivered", for example "Delivered 50 results" or "Delivered 404 of 500 requested. That is everything Threads returned for these inputs". If something stopped it short (a hidden account, your charging limit, the run's timeout), the message starts with a short code and says how many inputs were affected and why. The run's key-value store also has a RUN_SUMMARY record with the outcome of every input you sent.

Scraping public data is generally allowed in the US and most of the EU, as long as you don't collect personal data covered by GDPR or CCPA without a lawful basis. This actor only touches publicly accessible pages: anything you'd see in a browser without logging in. How you use the output is on you.

Apify's full breakdown: Is web scraping legal?.

Can I integrate Threads Scraper with other tools?

Push results into Make, Zapier, Slack, Airbyte, GitHub, Google Sheets, Google Drive, and more. Apify treats every actor as a webhook source, so anything that consumes webhooks or pulls from an API works.

Full list: Apify integrations.

Can I use Threads Scraper with the Apify API?

Yes. Every run is available via the Apify REST API:

curl -X POST "https://api.apify.com/v2/acts/sourabhbgp~threads-scraper/runs?token=APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"urls": ["@zuck"], "maxResults": 1}'

Docs: Apify API reference.

Can I use Threads Scraper through an MCP Server?

Yes. Apify ships an MCP server that exposes every actor as a tool, so Claude Desktop, Cursor, and any other MCP-capable client can call Threads Scraper directly. Setup: Apify MCP docs.

Your feedback

Bug, missing field, or odd behavior? Drop a note in the Issues tab. Reports go to a human and fixes usually ship the same week.