# Scrape Threads: 55 Posts for 3 Credits + Comments (https://www.socialcrawl.dev/blog/threads-scraper) > Scrape Threads with one API: 55 posts for 3 credits via multi-window search. Plus comments, carousel slides, and phrase expand that turned 0 hits into 44. You can scrape public Threads reads with one `x-api-key`. On 4 September 2026 UTC we spent **12 credits** and recorded the numbers below — not mocked JSON. One search window returned **19 posts for 1 credit**. The same query with `limit=40` returned **55 unique posts for 3 credits**. `the best coffee` went from **0 posts** (`expand=false`, billed 0) to **44 posts** (default expand, 3 credits). Comments came back as a **22-reply** window. A carousel post returned **3** `media_urls`. Search `limit` goes to 100 on the product; this harvest stopped at 40. Threads reached [500 million monthly active users](https://about.fb.com/news/2026/06/meta-launching-new-features-500-million-monthly-threads-users/) by Meta's June 2026 announcement. Meta's official keyword search still needs App Review before it returns public results and caps a user at [2,200 keyword queries per rolling 24 hours](https://developers.facebook.com/documentation/threads/keyword-search). The deep OAuth / App Review walkthrough lives at [/blog/threads-api](/blog/threads-api). This post is the read-path update: what one SocialCrawl call returns now under the unified Author / Post / Comment schemas on [`/v1/threads/*`](/platforms/threads). Three credit windows of glowing post tiles fan out from one token, showing how a threads search walks multiple windows to scrape Threads at higher yield ## How do you search Threads and collect up to 100 posts? One credit still buys one keyword search window of about 15–20 posts. On 4 Sep 2026, `GET /v1/threads/search?query=artificial%20intelligence` returned **19 unique posts**, billed **1 credit**, with `pagination.next_cursor` present (`has_more=true`). ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/threads/search?query=artificial%20intelligence" ``` ```json { "success": true, "platform": "threads", "endpoint": "/v1/threads/search", "credits_used": 1, "cached": false, "pagination": { "has_more": true, "page_size": 19 }, "data": { "items": [ { "post": { "id": "3978114690643853738", "url": "https://www.threads.com/@brandwithjoel/post/Dc1GjvzlwGq", "author": { "username": "brandwithjoel", "verified": true }, "engagement": { "likes": 70, "comments": 34, "shares": 5 }, "content": { "text": "If I need to explain why using AI for everything is a bad idea, we shouldn’t work together." } } }, { "post": { "id": "3832505233457128041", "url": "https://www.threads.com/@karpathy/post/DUvyzRQCaJp", "author": { "username": "karpathy" }, "engagement": { "likes": 788, "comments": 42, "shares": 255 } } } ] } } ``` Pass `limit` (1–100) when you want more unique posts in one call. The same query with `limit=40` returned **55 unique posts** for **3 credits** — three whole windows, not a truncated 40. The API does not chop the last window mid-page, so the result can overshoot your target. Overlap with the one-window set: **14** of those 19 IDs reappeared; **41** were new. A cursor was still present after the 55. Of the 19 one-window hits, **6** carried a topic tag (`AI team` × 2, `Author Threads` × 2, `ArtistsOnThreads`, `Stray Kids STAY`). Topic tags are sparse but real on search; they show up on `post.ext.topic_tag` / `topic_tag_id` when the post was filed under one. Credit math: each ~15–20 post window costs 1 credit. Asking for 40 unique posts walked three windows, so you paid 3. Cap `limit` at 100 for the deepest single-call pull this path supports. ## What happens when a longer Threads query returns nothing? Real listening queries are rarely one word. Exact multi-word phrases often miss. That used to mean an empty page. As of September 2026, search defaults to `expand=true`: if the exact phrase matches nothing, the query splits into narrower adjacent searches, merges the hits, and bills **1 credit per sub-query that returned posts**. An exact miss with `expand=false` billed **0** this run. Measured on `the best coffee`: | Call | Params | Posts | Credits | Cursor | | --- | --- | ---: | ---: | --- | | Exact phrase | `expand=false` | **0** | **0** | none | | Default expand | omit `expand` | **44** | **3** | none | ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/threads/search?query=the%20best%20coffee&expand=false" curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/threads/search?query=the%20best%20coffee" ``` The empty exact search billed **0** — no posts, no charge. The expanded response carried this `_warnings` string: > No Threads post matched "the best coffee" as a phrase, so the query was expanded into 3 narrower searches (best coffee, best, coffee) and 3 of them returned posts. Results are merged, de-duplicated and ordered by how many of your terms each post contains. You are billed 1 credit per search that returned posts, and an expanded response is a single page with no pagination cursor. Send expand=false to search the exact phrase only. First hit after expand: `@californiamaqui` on `Coffee Threads` (`topic_tag_id=18320322136110731`), 61 likes, 75 comments. Fifteen of the 44 expanded posts carried a topic tag. Expanded responses have **no pagination cursor** — one page, then done. Set `expand=false` only when you need the exact phrase and can accept an empty set. ## How do you pull Threads post comments? `GET /v1/threads/post/comments` returns one replies window for a public post URL. Official Meta reply endpoints sit behind OAuth and scopes aimed at managing **your** Threads surface, not "give me replies under any public URL." ([Meta replies docs](https://developers.facebook.com/documentation/threads/retrieve-and-manage-replies/replies-and-conversations)) ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/threads/post/comments?url=https://www.threads.com/@zuck/post/DZpPDXbCeTt" ``` Live result for that URL: **22 comments**, **1 credit**, `pagination.next_cursor=null` / `has_more=false`. Every reply had text and a constructed `comment.url`. All 22 had `post_id=null` and `parent_id=null`. ```json { "success": true, "endpoint": "/v1/threads/post/comments", "credits_used": 1, "pagination": { "has_more": false, "page_size": 22 }, "data": { "items": [ { "comment": { "id": "3920732800241693703", "url": "https://www.threads.com/@din_kerinchi/post/DZpPbV5oPQH", "text": "As soon as the bots and ads are in, we are out. Deal?", "author": { "username": "din_kerinchi" }, "engagement": { "likes": 2138, "replies": 33 }, "post_id": null, "parent_id": null } }, { "comment": { "id": "3921134303237475580", "url": "https://www.threads.com/@kelpee83/post/DZqqt-tEYz8", "text": "How many of those are bots?", "author": { "username": "kelpee83" }, "engagement": { "likes": 2 } } } ] } } ``` Honesty check: the parent post object reported **4,750** comments. This endpoint returned the bundled window (22), not the full thread. There is no cursor to walk deeper. Plan for a sample of top replies, not exhaustive reply export. ## What else comes back on Threads posts and profiles now? If carousel slides, video URLs, or the bio link come back empty, you end up fetching the post twice. Here is what this harvest actually returned. **Profile `bio_link`.** `GET /v1/threads/profile?handle=zuck` returned the field on the wire: `author.ext.bio_link` was **present and `null`** (this account has not set a website). Followers: **5,724,910**. Verified. Bio: "Mostly superintelligence and MMA takes". 1 credit. The field is on the wire; null means the account has no website set, not that the scrape failed. **User posts window.** `GET /v1/threads/user/posts?handle=zuck` returned **15 posts**, 1 credit, **no cursor**. Inside that window: **1** carousel (`DZ7eGA1G7wU`, 3 slides), **1** video CDN URL matching `/o1/v/t16/` plus a separate `thumbnail_url`, **0** topic tags, **0** quote posts. A second handle from search (`karpathy`) matched the same pattern: 15 posts, 1 credit, no cursor, zero quotes. We did not download and play the file; the claim is the URL shape on the wire. **Single-post detail.** Hitting the carousel permalink returned all **3** `content.media_urls`, plus engagement (3,803 likes / 1,395 comments / 411,634 views) and `computed.engagement_rate=0.013216`. 1 credit. Envelope `post.url` was null on this detail call — use the request URL as the permalink. CDN media URLs are signed and expire; store what you need promptly. **Topic tags.** Sparse but real on search (6/19 on the AI window; 15/44 on the coffee expand). Zero on the `zuck` user-posts window. Most posts are untagged. **Quote posts.** The schema carries `post.ext.quoted_post` for when a quote appears. This harvest observed **zero** populated quotes across search, user posts, and the detail call — so there is no live example JSON to paste. When a quote does appear, it lands at that field. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/threads/profile?handle=zuck" curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/threads/user/posts?handle=zuck" curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/threads/post?url=https://www.threads.com/@zuck/post/DZ7eGA1G7wU" ``` ## How much does each Threads read cost in credits? One credit ≈ one ~15–20 post window. Search can spend more windows in one call when you raise `limit` or when phrase expand fans out. Cache hits cost 0 (none in this run). Full harvest ledger from 4 Sep 2026: | Call | Result | Credits | | --- | --- | ---: | | Search one window (`artificial intelligence`) | 19 posts, cursor | 1 | | Search `limit=40` | 55 posts, cursor | 3 | | Exact phrase `expand=false` | 0 posts | 0 | | Phrase expand default | 44 posts, no cursor | 3 | | Profile `zuck` | bio_link present (null), 5,724,910 followers | 1 | | User posts `zuck` | 15 posts, no cursor | 1 | | User posts `karpathy` | 15 posts, no cursor | 1 | | Post detail (carousel) | 3 media_urls | 1 | | Comments `DZpPDXbCeTt` | 22 replies, no cursor | 1 | | **This harvest total** | | **12** | Rules that matter when you budget: - Windows are consumed whole. `limit=40` can return 55. - Expand bills per sub-query that returned posts (docs cap search at 1–11 credits per call). - User posts and comments have **no** pagination — one window each. - Expanded search has **no** cursor; one-window and `limit=` search do. - Repeat the same URL inside the cache TTL and you may see `credits_used=0`. ## How do you start scraping Threads with one API key? 1. Get an API key (free credits on signup) and set `SOCIALCRAWL_API_KEY`. 2. Reproduce the one-window search curl above. Confirm `credits_used` and `pagination` in the envelope. 3. Raise `limit`, flip `expand=false`, or swap the path to `/v1/threads/post/comments` once the baseline shape looks right. 4. Open the [Threads platform reference](/platforms/threads) for the full endpoint list, or hit the [/docs](/docs) / Explorer to see live responses before wiring a client. Search, comments, and media all share the same envelope. Live result counts will move day to day; the envelope shape, credit rules, and cursor behavior will not. If you also need the official Meta publish / App Review path, keep [/blog/threads-api](/blog/threads-api) bookmarked — different job, different auth model. ## Frequently asked questions ### How many credits does a Threads keyword search cost? One window of about 15–20 posts costs **1 credit**. This run's `artificial intelligence` query returned 19 posts for 1 credit. Multi-window pulls add 1 credit per window walked — `limit=40` cost 3 credits for 55 posts. ### What does the `limit` parameter do on Threads search (up to 100)? `limit` asks for 1–100 unique posts in one call. Windows are whole (~15–20 posts), so the response can overshoot: `limit=40` returned **55**. A cursor remains when more pages exist beyond that pull. ### When should I set `expand=false` on a Threads search? When you need the exact phrase only. Empty exact search billed **0** this run. Default expand recovered **44** posts for **3** credits on `the best coffee`, with no pagination cursor on the merged page. ### Does Threads comments support pagination? No. One window only — **22** replies this run, `next_cursor=null`. The parent post may report thousands of comments; this endpoint returns the bundled sample, not the full thread. ### Can I get every carousel slide and a video URL from a Threads post? On the samples we captured, yes. Post detail for `DZ7eGA1G7wU` returned **3** `media_urls`. The `zuck` user-posts window included one video CDN URL (`/o1/v/t16/`) plus a separate thumbnail. We did not play the file. ### Do quote posts return the quoted content now? The field exists on the schema at `post.ext.quoted_post`. This harvest (search + user posts + detail) observed **zero** populated quotes, so we are not claiming a live example here. ### Is user-posts pagination available on Threads? No. About **15** posts per call, **1** credit, no cursor — confirmed on both `zuck` and `karpathy` in this pull.