Threads Scraper
Scrape public Threads profiles and recent posts with no login. Rows carry bios, followers, post text, likes, timestamps and media URLs. $0.40 per 1,000 rows.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
profiles,query,maxPostsPerProfile(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.0004 per Threads profile or post = $0.4 per 1,000
| You are charged for | When | Price |
|---|---|---|
| Threads profile or post | One genuine public Threads profile or post row. Samples and diagnostics are free. | $0.0004 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-08-04, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
profiles | Public Threads handles or profile URLs. Leave empty for an uncharged sample row. | array |
query | Optional case-insensitive text filter applied to posts from the supplied profiles. This is not a global Threads search. | string |
maxPostsPerProfile | Maximum genuine public posts saved for each supplied public profile. | integer |
includeProfile | Save one public profile row for every successfully resolved handle. | boolean |
fallbackToResidential | Direct HTTP is always attempted first. When enabled, one blocked or transient request is retried through the Apify proxy settings you supply. Residential and other metered groups are not used; a datacenter proxy is used in their place. | boolean |
What you get
A structured dataset — each result includes fields like:
recordTypeusernamedisplayNamefollowerCountisVerifiedprofileUrltextlikeCountpublishedAtpostUrlExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
1 ready-to-run use cases
Threads Profile Posts Scraper
Get recent Threads posts from any public profile: text, timestamp, link, replies and likes. No login needed.
Related tools in Social Media Scrapers
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
Facebook Pages Scraper
Scrape public Facebook Page names, handles, likes, talking-about counts and verified badges. Up to 10 Pages per run. No login needed from you.
LinkedIn Profile Posts Scraper
Scrape LinkedIn profile posts with no login: post text, author, image, publish time and URL. $0.90 per 1,000 posts, flat on every plan.
LinkedIn Company Posts Scraper
Scrape public posts from any LinkedIn company page: post text, reactions, comments and URLs. No login or cookies. $0.90 per 1,000 posts.
LinkedIn Post Comments Scraper
Scrape public LinkedIn post comments: text, author name, profile URL, reactions. No login or cookie. Up to 10 per post. $0.60 per 1,000 comments.
RedNote Scraper
Scrape public RedNote (Xiaohongshu) notes: description, author, likes, collects, comments, shares and images. No login. $0.90 per 1,000 notes.
RedNote (Xiaohongshu) Profile Scraper
Scrape RedNote (Xiaohongshu) profiles: nickname, RedNote ID, followers, likes, verified badge, IP location and recent notes. $2.90 per 1,000.
Where this tool sits
- Categories
- Social Media Scrapers
- Platforms
- Threads
Threads Scraper: public profiles and recent posts, no login
Give it Threads handles and get back a row for each profile plus their recent public posts. Bio, follower count, post text, likes, the exact publish time, image links, and flags for video and replies. Nothing to log into.
You have to know whose posts you want. There is no anonymous global search on Threads that holds up, so this reads the handles you list and nothing wider. The query field filters those posts, it does not search Threads.
| Input | Threads handles or profile URLs |
| Output | One row per profile, one row per post |
| Ceiling | 30 posts per profile |
| Account needed | None |
| Price | $0.40 per 1,000 rows, flat on every plan |
🔍 What Threads Scraper does
Threads lives on threads.com now. A threads.net link redirects across, so both forms work, and so does a bare handle like zuck. Duplicates in your list are collapsed before anything is fetched, whatever the capitalisation.
For each handle it reads the public profile, then the public feed of that account's recent posts. You get one profile row and up to 30 post rows per handle, and you can turn the profile rows off if all you want is the posts.
query is an optional case-insensitive text filter over the posts it collected, so you can run ten accounts and keep only the ones that said "pricing". It narrows what you already asked for. It does not reach any post from an account you did not list.
📥 What you give it
{
"profiles": ["zuck", "https://www.threads.com/@instagram"],
"maxPostsPerProfile": 10,
"includeProfile": true,
"query": "AI"
}
| Field | Default | What it is |
|---|---|---|
profiles | none | Handles or full profile URLs. zuck, @zuck and the full link all resolve the same. The box starts with zuck in it, which is a suggestion and not a default. |
maxPostsPerProfile | 10 | Recent public posts to keep per handle, 1 to 30. |
includeProfile | true | Keep one profile row per handle. Turn it off for a posts-only run. |
query | none | Case-insensitive text filter over the posts collected from your handles. Not a Threads search. |
fallbackToResidential | false | Off. When one handle's request is turned down, try that handle once more through the network settings below. It does nothing unless you fill those in. |
proxyConfiguration | {"useApifyProxy": false} | Optional and off. Your own servers are used exactly as given. |
Leave profiles empty and you get a single labelled sample row, so you can see the shape before committing a list.
📤 What you get back
Every row carries a recordType, so one pass over the dataset splits it. A real profile row and a real post row, with the avatar URL cut short:
{
"ok": true,
"recordType": "profile",
"id": "63055343223",
"username": "zuck",
"displayName": "Mark Zuckerberg",
"bio": "Mostly superintelligence and MMA takes. See the latest conversations with @zuck.",
"followerCount": 5700000,
"isVerified": null,
"profilePicUrl": "https://scontent-iad3-1.cdninstagram.com/v/t51.82787-19/550174606_...",
"profileUrl": "https://www.threads.com/@zuck",
"source": "threads_public_ssr"
}
{
"ok": true,
"recordType": "post",
"id": "3981852126213720917",
"postId": "3981852126213720917",
"username": "zuck",
"text": "Introducing @Muse, the personal agent that understands your goals and works 24/7 to get things done for you...",
"likeCount": 3007,
"publishedAt": "2026-09-08T18:56:24.000Z",
"postCode": "DdCYWl7GktV",
"postUrl": "https://www.threads.com/@zuck/post/DdCYWl7GktV",
"imageUrls": [],
"hasVideo": false,
"isReply": false,
"source": "threads_public_graphql"
}
| Field | What it is |
|---|---|
followerCount | A number, but only as precise as Threads prints it. It publishes 5.7M for large accounts, so you get 5700000 and not the exact figure. |
isVerified | Comes back null. Threads does not put the badge in the public profile data, and a guess would be worse than a blank. |
postId, postCode | postCode is the short code in the URL. Either one works as a dedupe key across runs. |
likeCount | null when Threads does not publish a count for that post. |
text | The post text. Long posts are kept whole, and the example above is cut short for this page only. |
imageUrls | Up to five public image links. Empty for a text post. |
hasVideo, isReply | Booleans. There is no video file, just the flag. |
🧾 Reading the output
| Row | How to spot it | Charged |
|---|---|---|
| A profile | recordType: "profile" | yes |
| A post | recordType: "post" | yes |
| The sample row | _sample: true | no |
| A diagnostic | _diagnostic: true and a code | no |
The sample row also carries recordType: "profile", so filter on _sample and _diagnostic being absent rather than on recordType alone.
A diagnostic row names the handle it belongs to and carries a code:
code | What it means |
|---|---|
NOT_FOUND | No public Threads profile for that handle. Check the spelling. |
NO_POSTS | The profile resolved but no posts came back, or none matched your query. |
NO_RESULTS | Nothing at all was saved for that handle. |
BLOCKED | Threads turned the request down. Try again later. |
RATE_LIMITED | Too many requests too quickly. Give it a few minutes. |
NETWORK | Threads was unreachable or answered badly. Re-run it. |
TARGET_ERROR | Threads answered with something the actor could not read, usually a page without the public profile data on it. |
▶️ How to run it
1. Open Threads Scraper and click Try for free. 2. Put your handles into Threads profiles, one per line. 3. Set Maximum recent posts per profile. Ten is plenty for a first look. 4. Click Start. 5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.
💰 How much does it cost?
$0.40 per 1,000 rows. Flat on every Apify plan, no volume tiers.
A profile row and a post row cost the same. Turning Include profile rows off is the cheapest way to run a posts-only monitor, because a skipped profile row is a row you are not billed for. The sample row is not charged, diagnostic rows are not charged, and a handle you listed twice only produces one set of rows.
💡 What people use it for
- Watching what a set of accounts posted this week, on a schedule, with
postCodeas the dedupe key. - Pulling the text of an account's recent posts into a summary or a newsletter without opening the
app.
- Tracking like counts on a competitor's posts over time, by running the same handles daily and
joining on postId.
- Filtering a list of industry accounts down to the posts that mention one word, using
query, so a
30-account sweep lands as a handful of rows.
- Collecting bios and follower counts for a list of creators before deciding who to approach.
🚧 What it does not do
- No global search. You cannot ask for every post mentioning a word. You give it handles.
- No hashtags, no follower lists, no following lists, no reply threads and no comments under a
post.
- A bad handle can end the run. One entry that is not a usable handle stops the batch before the
good handles are written, and you get a single TARGET_ERROR row instead of your data. Check the list before a long run.
isVerifiedis alwaysnull.followerCountis rounded whenever Threads abbreviates it.- 30 posts per profile is the hard ceiling, and recent posts only. There is no way back through
an account's history.
- Public accounts only. A profile that does not resolve publicly comes back as a diagnostic row.
- Image links are Meta CDN URLs. They work for a while and are not archival. Video is a flag, not
a file.
- Rows are a snapshot. Likes move and posts get deleted.
🧭 Which social scraper do you need?
| If you want | Use |
|---|---|
| Threads profiles and their recent posts | This one |
| Posts by keyword on X | Twitter (X) Search Scraper |
| Posts by keyword on LinkedIn | LinkedIn Post Search Scraper |
| An Instagram account's profile details | Instagram Profile Scraper |
| Posts and reels under an Instagram tag | Instagram Hashtag Scraper |
❓ Questions people ask
Do I need a Threads or Instagram login? No. Nothing to connect, no cookie, no token.
Can I search Threads for a keyword? Not from here. query filters the posts from the accounts you listed. A real global search is not something Threads exposes to a signed-out visitor.
Do threads.net links work? Yes. They redirect to threads.com and resolve to the same account.
Why is the follower count round? Because Threads publishes it round for big accounts. A 5.7M on the page becomes 5700000 here.
Can I monitor accounts daily? Yes. Schedule it, keep includeProfile off if you only want posts, and dedupe on postCode.
Is this legal? These are public profiles and public posts. They are also personal data, which GDPR and similar laws cover, so have a reason for collecting it. Apify's write-up on scraping and the law is a good starting point, and we are not lawyers.
🆘 If something breaks
Open the Issues tab on the actor page. Send the handle and the run ID. If you got a diagnostic row, its code and details usually name the problem on their own.