Threads Search Post Scraper With Engagement Analytics
Pricing
from $3.99 / 1,000 results
Threads Search Post Scraper With Engagement Analytics
๐งต Threads Search Post Scraper finds and extracts Threads posts & replies by keywords, hashtags, or profiles. ๐ Captures text, author, timestamps, likes, reposts, media & links. ๐ Export CSV/JSON. ๐ Perfect for social listening, brand monitoring & competitor analysis.
Pricing
from $3.99 / 1,000 results
Rating
0.0
(0)
Developer
Scrapio
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
11 days ago
Last modified
Categories
Share
Threads Search Scraper โ Extract Posts, Analytics and User Profiles
Threads Search Post Scraper With Engagement Analytics searches Threads for a keyword, hashtag, or phrase and returns every matching post as typed JSON โ not just the first result โ complete with author profiles, flattened like/reply/repost/quote/reshare counts, and derived engagementRate, engagementVelocity, and percentileRank scores computed locally with no extra requests. It also accepts a direct post URL or numeric post ID for a single-thread lookup. Unlike scraping frameworks that return raw HTML, it returns typed JSON โ ready for your model, your database, or your pipeline without any parsing. This guide covers every input and output field, plus three concrete ways teams deploy it: enrichment pipelines, scheduled monitoring, and bulk dataset builds.
๐งญ What Does Threads Search Post Scraper With Engagement Analytics Do?
This Actor runs real, paginated Threads searches โ a search phrase returns every matching post found across the search's result pages, up to your cap, instead of stopping at the first match. It also accepts a full post URL (threads.com or threads.net) or a numeric post ID for a direct single-thread fetch, mixed freely with search phrases in the same run. No Threads account, login, or API key is required โ everything is read from Threads' public pages.
- Real multi-result keyword/hashtag search, paginated automatically
- Direct post lookup by URL or numeric post ID
- Author profile data embedded on every post (
userobject) - Flattened engagement counts: likes, replies, reposts, quotes, reshares, and a summed
totalEngagement - Derived
engagementRate,engagementVelocity, andpercentileRankโ computed locally, zero extra requests - Mentions, hashtags, and links parsed out of caption text into flat arrays
- Quote-post and repost detection with resolved source-post URLs
- Client-side filtering by author, date range, minimum engagement, and excluded keywords
โก Features & Capabilities
Capabilities split into three areas: what gets scraped, how results are filtered and enriched, and how this Actor stacks up against other Threads scrapers.
Core features
- Real multi-result search โ a search-phrase target paginates the actual Threads search connection instead of returning a single post
- Direct post/ID lookup โ
post_url-shaped targets or a 10+ digit numeric ID fetch that thread's SSR page directly - Engagement analytics โ
engagementRate(totalEngagementรทlike_count),engagementVelocity(totalEngagementper hour sincetaken_at), andpercentileRank(0โ100 rank within that target's own result batch) - Entity extraction โ
mentions,hashtags,urlsarrays parsed from each post's text fragments (with a regex hashtag fallback) - Quote/repost resolution โ
is_quote_post/quoted_post_urlandis_repost/reposted_post_url - Search-result filters โ
fromUsername,afterDate/beforeDate,minEngagement,excludeKeywords, applied client-side to already-fetched results - Tiered proxy escalation โ direct โ SHADER (datacenter) โ RESIDENTIAL, with automatic retry on blocks
How Threads Search Post Scraper With Engagement Analytics compares to other Threads scrapers
Checked on the Apify Store, 2026-08-04:
| Feature | This Actor | burbn/threads-search-scraper | logical_scrapers/threads-post-scraper |
|---|---|---|---|
| Multi-result keyword search | โ paginated | โ paginated | โ URL-only input, no search |
| Direct post URL/ID lookup | โ | not documented | โ
startUrls only |
| Derived engagement analytics (rate/velocity/percentile) | โ | not documented | not documented |
| Minimum-engagement / exclude-keyword filters | โ | not documented (from/date filters only) | not documented |
| Mentions/hashtags/links parsed to flat arrays | โ | not documented | not documented |
| Tiered proxy escalation described | โ | not documented | default Apify Proxy input only |
If your use case is feeding structured data to an LLM, the output format row is the decision-maker โ HTML parsing inside an agent loop is a reliability failure mode, not a feature. Every field above is already a typed JSON primitive or array, so none of these three require a post-processing pass before the data is model-ready.
When another tool might suit you better
If you need a full nested reply/comment tree for a thread rather than the root post itself, a dedicated Threads replies scraper is a better fit โ this Actor's direct-lookup mode fetches a single thread's SSR page, not a recursive comment crawl. If your workload is exclusively single-post lookups by URL at very high volume with no search step at all, logical_scrapers/threads-post-scraper's narrower URL-only input may be a simpler fit for that one job.
Threads Search Post Scraper With Engagement Analytics within the Scrapio data stack
This is currently Scrapio's only Threads Actor โ it covers keyword search, direct post lookup, and engagement analytics in one run rather than splitting them across separate Actors. For the same post-plus-engagement-analytics pattern on another platform, pair it with ../LinkedIn-Profile-Post-Scraper or ../Facebook-Group-Posts-And-Details-Scraper elsewhere in the Scrapio catalog.
Why do developers and data teams scrape Threads?
๐ข Brand and social media teams
Feed searchQueries with your brand name, product names, or campaign hashtags, add minEngagement to cut noise, and get back post_url, user.username, captionText, totalEngagement, and percentileRank for every mention. Sort the batch by percentileRank to surface the handful of posts actually worth a reply or a repost, instead of scrolling a live search page by hand.
๐ AI training data and RAG indexing
captionText is the high-information text field for RAG indexing โ it's already flattened out of Threads' nested caption object, so it drops straight into an embedding pipeline with no parsing step. For training data, like_count, direct_reply_count, repost_count, quote_count, reshare_count, and the derived engagementRate/engagementVelocity/percentileRank are consistently typed numeric fields across every row, useful as engagement-conditioning signals for a model rather than raw counts alone.
๐ฑ Competitive and market intelligence
Track a competitor's own posts (via fromUsername) or a market-wide keyword/hashtag alongside it, and watch totalEngagement and engagementVelocity per post to see not just how much engagement a post got but how fast it accumulated โ a launch post with a high velocity in its first hour reads differently than one that crept up over a week.
๐ฌ Research and academic use
Public-data-only Threads datasets for social or discourse research: hashtags and mentions arrays make network- and topic-mapping straightforward without re-parsing raw text, and taken_at timestamps support time-series analysis of a search topic. Scope is limited to what Threads exposes on its public pages.
๐ฅ Product and SaaS development
Build a Threads monitoring dashboard, sentiment tool, or engagement-benchmarking product on top of scheduled runs โ percentileRank alone gives you a ready-made "top performing post" signal without building your own ranking logic.
๐ Input Parameters
All parameters are optional โ there is no required field in the schema. Read directly from .actor/actor.json:
| Parameter | Required | Type | Constraints | Description |
|---|---|---|---|---|
searchQueries | No | array | stringList editor | One per line: a search phrase (recommended โ runs a real multi-result Threads search), a full post URL (threads.com or threads.net), or a numeric post ID (10+ digits). |
urls | No | array | stringList editor | Legacy alias for searchQueries, kept so inputs built for the base Threads Search Post Scraper keep working unchanged. If both fields are filled, entries from both are combined and de-duplicated. |
maxItems | No | integer | minimum 0, prefill 20 | Cap on how many rows to save across the whole run. Leave empty or 0 for no limit. |
sortOrder | No | string | enum top / recent, default top | Only affects search-phrase targets. top is Threads' default relevance ranking; recent returns the newest matching posts first. |
fromUsername | No | string | text field | Only keep search results posted by this exact username (without @). Leave blank to include every author. |
afterDate | No | string | date picker, absolute or relative | Only keep search results posted after this date/time. |
beforeDate | No | string | date picker, absolute or relative | Only keep search results posted before this date/time. |
minEngagement | No | integer | minimum 0, prefill 0 | Drop search results whose likes + replies + reposts + quotes + reshares add up to less than this number. 0 = no minimum. |
excludeKeywords | No | array | stringList editor | Drop any search result whose caption contains one of these words/phrases (case-insensitive). One per line. |
includeAnalytics | No | boolean | default true | When on, every row also gets engagementRate, engagementVelocity, and percentileRank. Turn off for the leaner base-compatible field set only. |
proxyConfiguration | No | object | proxy editor, prefill {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} | Routes requests through Apify Proxy. โ ๏ธ Threads serves an empty page to direct, un-proxied traffic from most cloud environments, so a proxy is strongly recommended for reliable results. |
Note the naming collision: the input field urls (legacy search targets) and the output field urls (links parsed out of a post's caption) are unrelated โ same name, different meaning, on opposite sides of the run.
Sample input:
{"searchQueries": ["AI startups", "https://www.threads.com/@zuck/post/AbCdEfGhIjK"],"sortOrder": "recent","minEngagement": 25,"excludeKeywords": ["giveaway"],"maxItems": 30,"includeAnalytics": true,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Supported URL types and input formats
Each line in searchQueries (or the legacy urls) is classified automatically:
- Search phrase โ anything that isn't a URL or a bare number, e.g.
AI startups. Recommended: this is the only mode that runs a real multi-result search. - Post URL โ must resolve to a
threads.comorthreads.nethost, e.g.https://www.threads.com/@zuck/post/AbCdEfGhIjK. Any other host raises a validation error. - Numeric post ID โ a string of 10 or more digits, e.g.
3487216590412789, matched with a\d{10,}pattern and converted internally to the post's short code.
๐ฆ Output Format
Every matched or fetched post is pushed to the dataset as one JSON row, in the order it was found. There is no separate output type for analytics or author data โ both are fields on the same post row.
Output for posts
Full row shape (values illustrative):
{"post_url": "https://www.threads.com/@zuck/post/AbCdEfGhIjK","pk": 3487216590412789,"id": "3487216590412789_7841022","code": "AbCdEfGhIjK","user": {"id": "7841022","pk": 7841022,"username": "zuck","full_name": "Mark Zuckerberg","profile_pic_url": "https://scontent.cdninstagram.com/...","is_verified": true,"friendship_status": { "muting": false, "following": false, "followed_by": false, "outgoing_request": null, "blocking": null },"text_app_last_visited_time": 0,"transparency_label": null,"transparency_product": null,"transparency_product_enabled": false,"text_post_app_is_private": false,"has_onboarded_to_text_post_app": true},"caption": { "text": "Excited to share our latest AI research... #ai" },"captionText": "Excited to share our latest AI research... #ai","caption_is_edited": false,"caption_add_on": null,"media_type": 1,"image_versions2": { "candidates": [{ "url": "https://scontent.cdninstagram.com/..." }] },"video_versions": null,"carousel_media": null,"has_audio": false,"audio": null,"accessibility_caption": null,"usertags": null,"original_height": 1080,"original_width": 1080,"transcription_data": null,"media_overlay_info": null,"like_count": 1520,"direct_reply_count": 87,"repost_count": 42,"quote_count": 12,"reshare_count": 5,"totalEngagement": 1666,"engagementRate": 1.0961,"engagementVelocity": 138.8,"percentileRank": 92.5,"mentions": [],"hashtags": ["ai"],"urls": [],"is_quote_post": false,"quoted_post_url": null,"is_repost": false,"reposted_post_url": null,"taken_at": 1769875200,"scrapedAt": "2026-08-04T09:15:22.104Z","is_paid_partnership": false,"has_liked": false,"like_and_view_counts_disabled": false,"canonical_url": null,"giphy_media_info": null,"metaPlace": null,"meta_place": null,"gen_ai_detection_method": { "detection_method": "NONE" },"sharing_friction_info": { "should_have_sharing_friction": false, "sharing_friction_payload": null },"organic_tracking_token": null,"logging_info_token": null,"__token": null,"text_post_app_info": { "id": "...", "direct_reply_count": 87, "repost_count": 42, "quote_count": 12, "reshare_count": 5, "share_info": { "reposted_post": null, "quoted_post": null }, "text_fragments": { "fragments": [] } }}
Every key above is written by the row-building code (src/extract_posts.py + src/enrich.py). Grouped reference:
| Group | Fields |
|---|---|
| Identity | post_url, pk, id, code |
| Author | user (nested object โ see below) |
| Content | caption, captionText, caption_is_edited, caption_add_on |
| Media | media_type, image_versions2, video_versions, carousel_media, has_audio, audio, accessibility_caption, usertags, original_height, original_width, transcription_data, media_overlay_info |
| Engagement counts | like_count, direct_reply_count, repost_count, quote_count, reshare_count, totalEngagement |
Engagement analytics (this Actor's own feature, gated by includeAnalytics) | engagementRate, engagementVelocity, percentileRank |
| Extracted entities | mentions, hashtags, urls |
| Quote/repost | is_quote_post, quoted_post_url, is_repost, reposted_post_url |
| Timestamps | taken_at, scrapedAt |
| Raw Threads metadata, preserved unmodified | text_post_app_info, is_paid_partnership, has_liked, like_and_view_counts_disabled, canonical_url, giphy_media_info, metaPlace, meta_place, gen_ai_detection_method, sharing_friction_info, organic_tracking_token, logging_info_token, __token |
The default dataset view surfaces a 22-column subset of the above (post_url, pk, user, captionText, like_count, direct_reply_count, repost_count, quote_count, reshare_count, totalEngagement, engagementRate, engagementVelocity, percentileRank, hashtags, mentions, urls, is_quote_post, quoted_post_url, is_repost, reposted_post_url, taken_at, scrapedAt) for readability โ every field in the table above is still present in the raw dataset item.
Output for engagement analytics
The same row's analytics fields, computed by src/enrich.py, in isolation:
{"totalEngagement": 1666,"engagementRate": 1.0961,"engagementVelocity": 138.8,"percentileRank": 92.5}
totalEngagementโlike_count + direct_reply_count + repost_count + quote_count + reshare_count.engagementRateโtotalEngagement รท like_count.nullwhenlike_countis0(undefined ratio, never reported as a fake0).engagementVelocityโtotalEngagementper hour sincetaken_at, floored at a 1-minute divisor so a just-posted item doesn't return an inflated number.nullwhentaken_atis missing.percentileRankโ 0โ100 rank of this post'stotalEngagementwithin its own target's result batch (average-rank method for ties). Only present whenincludeAnalyticsistrue; not comparable across different search queries or targets in the same run, since each target's batch is ranked independently.
Output for author profiles
The user object embedded on every row:
{"id": "7841022","pk": 7841022,"username": "zuck","full_name": "Mark Zuckerberg","profile_pic_url": "https://scontent.cdninstagram.com/...","is_verified": true,"friendship_status": { "muting": false, "following": false, "followed_by": false, "outgoing_request": null, "blocking": null },"text_app_last_visited_time": 0,"transparency_label": null,"transparency_product": null,"transparency_product_enabled": false,"text_post_app_is_private": false,"has_onboarded_to_text_post_app": true}
Schema stability and export options
Field names stay stable across runs โ src/extract_posts.py walks Threads' SSR JSON with a fixed field order and preserves any unrecognized keys rather than dropping them, so a front-end rename upstream adds a field instead of breaking one your pipeline already depends on. Datasets export from the Apify Console or API to JSON, CSV, Excel, XML, RSS, or HTML table โ standard Apify dataset export formats, not a feature specific to this Actor.
๐ก Threads Search Post Scraper With Engagement Analytics Strategy Guide
๐ฏ Strategy 1: Real-time enrichment pipeline
Trigger a run whenever a new lead, mention, or campaign hashtag needs checking: pass it as a searchQueries entry, run the Actor, then read totalEngagement, engagementRate, engagementVelocity, and percentileRank off each returned row keyed by post_url. Append those fields to the matching record in your CRM, spreadsheet, or database โ the row is already typed JSON, so no parsing step sits between the Actor and your destination table.
๐ฏ Strategy 2: Scheduled monitoring and alerting
Use an Apify Schedule to re-run the same searchQueries (brand name, hashtag, or competitor handle) every few hours. Diff each run's dataset against the previous one on post_url to find new posts, and alert on the ones where percentileRank or engagementVelocity crosses a threshold you set โ an Apify webhook on the run-succeeded event can push that alert to Slack or an HTTP endpoint without polling.
๐ฏ Strategy 3: Bulk dataset build
For a research or training corpus, list your search phrases or hashtags one per line in searchQueries and set maxItems per run. Targets inside one run are processed one at a time, not in parallel โ for a large batch, split queries across several concurrent Actor runs (launched via the Apify API) rather than listing hundreds of queries in a single run. Aggregate each run's dataset export to CSV or a database.
Strategy comparison at a glance
| Strategy | Best for | Run pattern | Output format |
|---|---|---|---|
| Real-time enrichment | Lead/mention enrichment | Triggered run, small target list | JSON row appended to an external system |
| Scheduled monitoring | Ongoing brand/competitor tracking | Apify Schedule, recurring run + webhook | Dataset diffed run-over-run |
| Bulk dataset build | Research/training corpora | Multiple concurrent runs, smaller lists each | Dataset export to CSV/JSON |
๐ด Related Threads Scrapers & Tools
| Scraper | What it extracts |
|---|---|
| LinkedIn Profile Posts Scraper With Engagement Analytics | LinkedIn profile posts with the same engagement-analytics pattern, on LinkedIn |
| Facebook Group Posts & Details Scraper | Facebook group posts and group metadata |
| X (Twitter) Tweets & Profiles Scraper | Tweets and profile data, for cross-platform post monitoring |
| TikTok Data Scraper: Comments, Replies & AI Sentiment | TikTok comments and replies with sentiment scoring |
| Reddit Subreddit Members Scraper With User Profiles | Subreddit member lists and user profile cards, for adjacent community research |
This is currently the only Threads Actor in the Scrapio catalog โ it covers keyword search, direct post lookup, and engagement analytics together rather than splitting them across separate listings.
How to integrate Threads Search Post Scraper With Engagement Analytics with your stack
Threads Search Post Scraper With Engagement Analytics works with any language or tool that can make an HTTP request โ it runs on Apify, so the Apify API and the official apify-client libraries are the fastest path in.
Python
from apify_client import ApifyClientimport csvclient = ApifyClient("<YOUR_APIFY_TOKEN>")run_input = {"searchQueries": ["AI startups", "SaaS launch"],"sortOrder": "recent","minEngagement": 10,"maxItems": 50,"includeAnalytics": True,"proxyConfiguration": {"useApifyProxy": True},}run = client.actor("<YOUR_USERNAME>/threads-search-post-scraper-with-engagement-analytics").call(run_input=run_input)rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())fields = ["post_url", "captionText", "totalEngagement", "engagementRate", "percentileRank"]with open("threads_posts.csv", "w", newline="", encoding="utf-8") as f:writer = csv.DictWriter(f, fieldnames=fields)writer.writeheader()for row in rows:writer.writerow({k: row.get(k) for k in fields})
Node.js
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const input = {searchQueries: ['AI startups', 'SaaS launch'],sortOrder: 'recent',minEngagement: 10,maxItems: 50,includeAnalytics: true,};const run = await client.actor('<YOUR_USERNAME>/threads-search-post-scraper-with-engagement-analytics').call(input);const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const post of items) {console.log(post.post_url, post.totalEngagement, post.engagementRate);}
Async and scheduled pipelines
For fire-and-forget large jobs, start the run via the API and let it finish asynchronously rather than blocking on .call(); attach an Apify webhook on the run-succeeded event to push a notification or trigger a downstream job once the dataset is ready. For recurring jobs, an Apify Schedule re-runs the same input on a cron-style interval without any code on your side.
๐ฏ Who Needs Threads Search Post Scraper With Engagement Analytics? (Use Cases & Industries)
๐ข Brand and social media managers
Search your brand name or campaign hashtag, sort the results by percentileRank, and reply to or amplify the posts already outperforming the rest of the batch โ instead of manually scrolling Threads' own search results.
๐ AI/ML and data teams
Pull captionText, hashtags, and the engagement fields as consistently typed inputs for RAG indexing or as engagement-conditioning signals in a training set, with no HTML parsing step.
๐ฑ Competitive intelligence analysts
Track a competitor's fromUsername alongside a market keyword, and compare engagementVelocity across both to see whose posts are gaining traction faster, not just which has more raw likes.
๐ฌ Researchers
Build a public-data-only dataset of a search topic on Threads for social or discourse research, using hashtags/mentions for network mapping and taken_at for time-series analysis.
๐ฅ Product and SaaS builders
Build a Threads engagement dashboard, sentiment tool, or benchmarking product on scheduled runs, using percentileRank as a ready-made "top performer" signal instead of writing your own ranking logic.
Is it legal to scrape Threads?
Yes โ scraping publicly accessible data is generally lawful in the US; the Ninth Circuit held in hiQ Labs v. LinkedIn (9th Cir. 2019) that accessing public web data does not violate the Computer Fraud and Abuse Act. That precedent covers accessing public data, not every downstream use of it. Scraping may still violate Threads' own Terms of Service, which is a civil contract matter between you and Meta, not a criminal one โ running this Actor does not create legal risk by itself, but commercial reuse of the data might, depending on your jurisdiction and use case.
Because Threads posts carry personal data โ usernames, full names, profile pictures, and verification status of identifiable individuals โ GDPR (EU/UK) and CCPA (California) considerations attach to storing and using that data, separately from the scraping-legality question above. Threads Search Post Scraper With Engagement Analytics returns only publicly accessible data. What you do with that data is your responsibility โ consult legal counsel for commercial applications involving personal data.
โ Frequently asked questions
Does Threads Search Post Scraper With Engagement Analytics work without a Threads account?
Yes. No Threads login, session cookie, or API key is required โ every field is read from Threads' public pages and public search/GraphQL endpoints.
How does it handle Threads' anti-scraping measures?
It rotates a small pool of user agents, retries transient HTTP errors (429/502/503/504) with exponential backoff and jitter, and escalates through a tiered proxy path โ direct (or SHADER datacenter, if proxy is enabled) โ SHADER โ RESIDENTIAL โ sticking to the higher tier once escalated. โ ๏ธ Threads returns an empty page to un-proxied requests from most cloud environments, so leaving proxyConfiguration off is a common cause of empty runs.
Can I run it at scale without getting blocked?
There is no published uptime or success-rate figure. What is documented in the code: search-phrase pagination stops after 30 pages or two consecutive empty pages, whichever comes first; targets within a single run are processed one at a time, not in parallel; and residential-proxy retries give up after 3 consecutive failures. For large batches, run multiple targets across separate concurrent Actor runs rather than one very long list.
How fresh is the data it returns?
Live โ every run fetches directly from Threads at run time. Nothing is cached or served from a previous run.
Which fields work best for AI training and RAG indexing?
For RAG, captionText is the high-information text field โ already flattened out of the nested caption object. For training data, like_count, direct_reply_count, repost_count, quote_count, reshare_count, totalEngagement, engagementRate, engagementVelocity, and percentileRank are consistently typed numeric fields across every row. All fields return as typed JSON primitives or arrays, requiring no normalization before use.
Does scraping Threads posts raise data-protection concerns?
Yes, to the extent the data is personal โ author usernames, full names, and profile pictures are personal data under GDPR/CCPA. This Actor returns only publicly available data; the lawful basis for storing and using it sits with you as the operator, not with the Actor.
Does it work with Claude, ChatGPT, and other AI agent tools?
It is not reachable through an MCP server. It is callable as an Apify Actor run by any agent framework that can make an HTTP request through the Apify API โ every response is typed JSON, so no parsing is required before passing a row into an LLM context window.
How does it compare to other Threads scrapers?
As observed on the Apify Store, 2026-08-04: burbn/threads-search-scraper documents multi-result search with sort/from/date filters but does not document engagement analytics, minimum-engagement filtering, or excluded-keyword filtering. logical_scrapers/threads-post-scraper accepts only direct post URLs โ no keyword search at all โ but does document full reply-thread extraction. This Actor's own strength is combining real multi-result search with the derived analytics fields and client-side filters in one run; if a full nested reply tree per post is what you need, neither this Actor nor either of those two documents that as a feature.
โน๏ธ Disclaimer
Threads Search Post Scraper With Engagement Analytics extracts only publicly available data from Threads. This tool is intended for lawful use cases only. Users are responsible for complying with Threads' terms of service and applicable data protection laws in their jurisdiction.