Threads Posts Scraper 🧵 Public Profiles, No Login avatar

Threads Posts Scraper 🧵 Public Profiles, No Login

Pricing

from $1.43 / 1,000 post returneds

Go to Apify Store
Threads Posts Scraper 🧵 Public Profiles, No Login

Threads Posts Scraper 🧵 Public Profiles, No Login

Scrape posts from any public Threads profile. Pass profile handles or URLs; get post text, like, reply and repost counts, author handle, publish date and a direct post URL as JSON or CSV. No login required. Since date filter makes scheduled monitoring cheap.

Pricing

from $1.43 / 1,000 post returneds

Rating

0.0

(0)

Developer

Yaniv van der Stigchel

Yaniv van der Stigchel

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

3 hours ago

Last modified

Share

Threads Posts Scraper — monitor profiles, no login

Latest posts from any public Threads profile. Text, likes, replies, reposts, quotes and timestamps. No login, no app password, no API key.

What it does

  • Monitor Threads profiles for new posts
  • Export Threads posts to JSON or CSV
  • Track Threads engagement metrics
  • Watch competitor and creator accounts on Threads

Pass many profiles in one run. Every row is tagged with its source profile.

Scope — read this before running

Threads only exposes a recent window per profile, typically 5 to 15 posts. Deeper history is not available without an authenticated session, so this actor does not offer it and does not pretend to.

That makes it a monitoring tool, not an archive tool. It is built for running on a schedule across many profiles: set since to your last run and each run returns only what is new. If you need a profile's full back catalogue, this is not the right tool.

Why it works where simpler scrapers do not

Threads serves a stripped page to standard HTTP clients — 265 KB with no post data, versus 874 KB with it. This actor uses browser TLS fingerprinting to receive the full payload, which is why it returns posts when plain scrapers return nothing.

Honest failure reporting

Unavailable profiles and misspelled handles return a row with a reason and cost you nothing. You are only charged for posts actually delivered.

Input

FieldRequiredDescription
profilesyesHandles or threads.net URLs
maxPostsPerProfilenoDefault 25. Your cost ceiling.
sincenoISO date. Only newer posts — ideal for scheduled runs.
proxynoOptional, for spreading load across many profiles

Example input

{
"profiles": ["@zuck", "mosseri"],
"since": "2026-08-25"
}

Output

Every row has the same fields whether it succeeded or failed, so you can select columns without branching. Failed rows are never charged.

FieldTypeDescription
successbooleanTrue when this row carries data. Failed rows are never charged.
sourceProfilestringThe profile input this row came from.
postUrlstringPublic threads.net link to the post.
postIdstringThreads' numeric post identifier.
shortcodestringShort code used in the post URL.
authorHandlestringHandle of the profile that posted.
authorIdstringStable profile identifier.
textstringThe post body.
publishedAtstringISO 8601 timestamp of publication.
likeCountintegerLikes at the time of the run.
replyCountintegerReplies at the time of the run.
repostCountintegerReposts at the time of the run.
quoteCountintegerQuote posts at the time of the run.
hasMediabooleanTrue when the post includes an image or video.
errorCodestringMachine-readable failure reason. Null on success.
errorMessagestringHuman-readable explanation of the failure. Null on success.

Example — success

{
"success": true,
"sourceProfile": "@zuck",
"postUrl": "https://www.threads.net/@zuck/post/C1aBcDeFgHi",
"postId": "3141592653589793",
"shortcode": "C1aBcDeFgHi",
"authorHandle": "@zuck",
"authorId": "314159",
"text": "Testing a few new things in the app this week.",
"publishedAt": "2026-08-14T09:12:04.000Z",
"likeCount": 48210,
"replyCount": 3112,
"repostCount": 884,
"quoteCount": 127,
"hasMedia": true,
"errorCode": null,
"errorMessage": null
}

Example — failure

A failure carries the same fields, so nothing downstream has to branch.

{
"success": false,
"sourceProfile": "@private_example",
"postUrl": null,
"postId": null,
"shortcode": null,
"authorHandle": null,
"authorId": null,
"text": null,
"publishedAt": null,
"likeCount": null,
"replyCount": null,
"repostCount": null,
"quoteCount": null,
"hasMedia": null,
"errorCode": "profile-unavailable",
"errorMessage": "No public Threads profile exists for this handle, or it is private."
}

Error codes

  • profile-unavailable
  • unparseable-handle
  • no-posts-found
  • error

Use it for

  • Threads profile posts — a public profile's timeline
  • Meta Threads monitoring — scheduled runs with a since filter
  • Social listening, brand and competitor tracking
  • Research corpora and training datasets

Use it from an AI agent (MCP)

This Actor is callable as a tool through the Apify MCP server, so Claude, ChatGPT, Cursor and VS Code can run it directly.

Add the server to your MCP client:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com",
"headers": {
"Authorization": "Bearer <YOUR_APIFY_TOKEN>"
}
}
}
}

Then ask for what you want in plain language — for example “get the recent posts from this Threads profile” — and the agent calls cleanfeed/meta-threads-posts-scraper with the right input. Every output field is described in the dataset schema, so the agent knows what it is getting back before it runs anything.

Call it from code

Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("cleanfeed/meta-threads-posts-scraper").call(run_input={
"profiles": ["https://www.threads.net/@zuck"],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item["success"]:
print(item)

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('cleanfeed/meta-threads-posts-scraper').call({
profiles: ["https://www.threads.net/@zuck"],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => i.success));

cURL

curl -X POST "https://api.apify.com/v2/acts/cleanfeed~meta-threads-posts-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H 'Content-Type: application/json' \
-d '{"profiles": ["https://www.threads.net/@zuck"]}'
If you needUse
Posts from public Bluesky accountsBluesky Posts Scraper
Messages from public Telegram channelsTelegram Channel Scraper

Limitations

  • Public profiles only. Private profiles return errorCode: profile-unavailable.
  • Threads exposes only a recent window — typically 5 to 15 posts per profile. There is no full history to page through, so maxPostsPerProfile above that returns what exists rather than erroring.
  • Because the window is short, scheduled runs with since are the reliable way to build history over time.

FAQ

Do I need a Threads or Instagram login?

No login and no app password. Only public profiles are read.

Why do I only get 5 to 15 posts?

That is the window Threads exposes publicly. There is no deeper history to page through, so asking for more returns what exists rather than erroring.

How do I build a longer history then?

Run on a schedule with since. Each run adds what is new, and over time you accumulate the history the platform will not serve in one request.

What profile formats work?

An @handle or a threads.net profile URL.

Can I read private profiles?

No. Those return errorCode: profile-unavailable.

Notes

Only publicly visible posts are collected. No login, no private data.