One URL in. Clean JSON out.
Give /v1/threads/stats the URL of a public Threads post and it returns the post text, the engagement counters and the posting timestamp as JSON. One call, 3 credits, no Threads login involved. Read the availability note before you build on it: Threads does not publish a view count for most posts, so there is no views field in the response, and reply threads are not returned yet.
Shipped the thing. Six months of nobody using it, then one good week.
Availability: Threads does not publish view counts for most posts, so `views` is omitted from responses. Reply threads and post transcripts are planned for v2.
The difference
On the left, what a headless browser hands you. On the right, what the endpoint hands you.
<div class="x1a2b3c x9k2m1 xdt5ytf" data-pressable-container="true"><div class="x78zum5 xdt5ytf"><div class="x9f619 x1n2onr6"><span class="x1lliihq x1plvlek"><span dir="auto" class="x1lliihq xjkvuk6">Everyone building ai agents keeps rediscovering the same three problems.</span></span></div><div class="x6s0dn4 x78zum5 xl56j7k"><div role="button" tabindex="0" class="x1i10hfl x1qjc9v5"><svg aria-label="Like" role="img" viewBox="0 0 24 24"><path d="M16.792 3.904..."></path></svg><span class="x17qophe">88.4K</span></div><div role="button" tabindex="0" class="x1i10hfl"><svg aria-label="Reply"></svg><span>2,314</span></div></div><time datetime="2026-07-07T09:40:00.000Z" class="x1rg5ohu">2h</time></div><script>requireLazy(["ServerJS"],function(f){f().handle({"__bbox":{"complete":true,"require":[["ScheduledServerJS"... {"data": {"platform": "threads","entity_id": "C2isac0P7c7","url": "https://www.threads.com/@zuck/post/C2isac0P7c7","author": {"handle": "zuck","name": "Example Creator"},"posted_at": "2026-06-30T14:05:00Z","text": "Shipped the thing. Six months of nobody using it, then one good week.","metrics": {"likes": 88410,"replies": 2314,"reposts": 1290,"quotes": 214}},"request_id": "req_01JZX4M8Q2TE9W"}
The payload
One object for one post. You get the text body, who wrote it, the four counters Threads shows publicly (likes, replies, reposts, quotes), the publish time, and two booleans telling you whether the thing you fetched is itself a reply or a repost rather than an original post. That last pair matters more than it sounds: Threads permalinks to replies look identical to permalinks to top-level posts, so is_reply is often the first field your code should branch on.
There is no views field. Threads shows view counts to the post author inside the app and does not publish them on the public web for most posts, so we do not have a number to give you and we are not going to estimate one. If your dashboard has a views column for Threads, it will stay empty. Likewise, this endpoint returns the post you asked for and nothing beneath it — the replies under a post are a v2 item, not something you can pull today.
Counters are whatever the public page shows at call time. On a post an hour old they climb between calls; on a post from last year they will barely move. Responses sit in the fast cache class, so a repeat call for the same URL inside the window comes back in milliseconds with x-cache: hit.
The poster's handle as a plain string, without the leading @. Follower counts and bio are not here — they come from the Threads Profile API.
Pricing
One post is 3 credits — about 1.5¢ on the monthly plan, 1.3¢ on annual. $5 covers roughly 333 posts, cached repeats cost the same, and failed calls are never charged.
Estimate only, on a full-year basis. 3 credits per returned post. Monthly: $5 per 1,000 credits with $4/1,000 top-ups. Annual: $54 per 12,000 credits with $3/1,000 top-ups. We show whichever plan is cheaper for your annual volume, divided by 12. Failed calls are never charged; cache hits cost the same as fresh calls.
Entry price, side by side
Credits are not equivalent units across vendors — each meters differently. Price your own workload on both before deciding on entry price alone. At high volume, several of these are cheaper per credit than we are.
Engineering notes
We document exactly how every endpoint behaves — nulls, caching, billing — so what you ship on day one is still running in month six. No surprises, no support tickets.
Threads surfaces view counts to the author in the app's own insights view. They are not on the public post page, so a logged-out reader cannot see them and neither can this endpoint. There is no views key in the response object at all.
If you need Threads view data, the only route is the account owner reading it in the app or through Meta's own business tooling with an authenticated session. We read public pages logged out, on purpose, and that boundary is what keeps this endpoint predictable.
The replies field tells you how many replies a post has. It does not give you their text, authors or timestamps. Fetching a reply thread is on the v2 list and is not shipped.
You can work around it partially: if you already have the permalink of a specific reply, pass that URL here and you will get that reply as a post object with is_reply set to true. What you cannot do today is enumerate a post's replies from the parent URL.
Sample on a fixed cadence if you are charting growth. A newly published post generally accumulates engagement faster than an old one, so sampling more often in the first day and less often after that is a reasonable default — but we do not measure a decay curve for you, and the right cadence depends on the account. Pick one, keep the intervals even, and let your own data tell you where it flattens.
Do not diff two calls taken a minute apart and treat the difference as a trend. Between rounding upstream and cache hits inside the window, small deltas are noise.
A post from a private account, or one that has been deleted, returns an error rather than a partial object, and the call is not charged. Threads accounts can be flipped to private at any time, so a URL that worked last week can start failing without anything changing on your side.
If a post has been edited, text is whatever the public page shows when we read it — the current version, not what was originally published. There is no edit flag and no edit history in the response, so a call today and a call last week can legitimately return different text for the same shortcode. Keep your own copy of each fetch if that difference matters to you.
This endpoint is in the fast cache class. A repeat call for the same URL inside the window returns from cache in milliseconds and sets x-cache: hit. Cache hits are charged the same 3 credits as fresh calls. Add fresh=true when you need to bypass the cache — for the first sample in a monitoring pass, for example — and skip it otherwise.
Questions
No. Threads only shows view counts to the post's author inside the app, and does not publish them on the public post page. Since we read public pages with no logged-in session, there is nothing to read, and the response has no views field. Anyone offering you public Threads view counts is either authenticated as the account or estimating. Likes, replies, reposts and quotes are all returned.
Send a GET to /v1/threads/stats with the post URL and your API key. There is no app review, no OAuth flow, and no requirement to own the account. Meta's own Threads API is scoped to content the authenticating user posted, which rules it out for competitor tracking or agency reporting — the usual reason people end up here.
3 credits per post. Credits are $0.005 each on monthly billing and $0.0045 on annual, so a call is about 1.5 cents and $5 covers roughly 333 posts. Cached responses are charged the same as fresh ones. Calls that fail — private account, deleted post, bad URL — are not charged at all.
Not yet. The replies field gives you the count, but the reply text is not returned. Reply threads are planned for v2. If you have the direct permalink of an individual reply you can pass that URL to this endpoint and get it back as a post object with is_reply set to true, but you cannot enumerate replies starting from the parent post.
A repost shares the original post as-is to the reposter's feed. A quote wraps it in new commentary. Both are returned as separate counters here because they mean different things: reposts usually signal agreement, while a quote count that dwarfs the repost count often means people are arguing with the post rather than endorsing it.
Yes, as long as it points at a public post. Threads share links resolve to the standard threads.com permalink, and the endpoint reads that. What matters is the account's privacy setting, not the link format — a post from a private account returns an error whatever URL shape you send.
Threads renders relative timestamps for recent posts, and for some posts the absolute time is not present in the public page markup. When we cannot resolve an exact time we return null rather than guessing. If you need reliable ordering, the shortcode and your own fetch time are usually enough, and posted_at is populated for the large majority of posts.
Next
100 trial credits on signup — no card, key on screen immediately.