# Threads Scraper - Posts, Profiles & Search (`futurizerush/meta-threads-scraper`) Actor

Search Threads posts by keyword, or grab any profile's posts, replies and reposts. Export engagement, views when available, and media. No login.

- **URL**: https://apify.com/futurizerush/meta-threads-scraper.md
- **Developed by:** [Rush](https://apify.com/futurizerush) (community)
- **Categories:** Social media, AI, Agents
- **Stats:** 5,129 total users, 1,691 monthly users, 92.0% runs succeeded, 48 bookmarks
- **User rating**: 4.34 out of 5 stars

## Pricing

from $2.50 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Threads Scraper - Posts, Reposts, Replies, Profiles & Search

Search public Meta Threads posts by keyword, collect an account's public posts, reposts or replies up to your selected limit, or find profiles by keyword. No login required. Export posts, media, public engagement metrics, and public profile data.

> **Before you start**: Threads changes its public pages from time to time, and a change can briefly affect what any tool can collect until it is adjusted. Run a small sample first, check the output, then scale up. Results reflect what Threads shows publicly at the time of the run.

### What You Can Do With It

- **Brand & Mention Monitoring**: watch brands, product terms, topics and campaigns as fresh public posts appear
- **Competitor Analysis**: compare public engagement across competitor accounts and posts
- **Influencer Discovery**: find creators by keyword or niche, with public follower counts
- **Lead Generation**: build account and prospect lists from public profile information
- **Trend & Content Analysis**: collect posts on a topic, hashtag, or campaign for downstream analysis
- **Market Research**: gather public posts on a product or category to read the conversation
- **Date-bounded Research**: narrow a search to a specific date range for time-sensitive work

### Choose Your Workflow

| Goal | Use this mode | What you enter |
|---|---|---|
| Collect posts from one or more accounts | `user` | Threads usernames or profile URLs |
| See what an account boosted, and when | `user_reposts` | Threads usernames or profile URLs |
| Read the replies an account wrote | `user_replies` | Threads usernames or profile URLs |
| Search public posts by topic | `search` | Keywords or hashtags |
| Discover account matches by keyword | `profiles` | Keywords, niches, or local phrases |
| Monitor fresh public mentions | `search` + `recent` | Brand, topic, or competitor keywords |
| Research a specific date range | `search` + date filters | Keyword plus start/end date |

### Ready-Made Examples

Each one is a pre-configured run you can start and then edit. Browse them all on the [Examples tab](https://apify.com/futurizerush/meta-threads-scraper/examples?fpr=rush).

| Example | What you get |
|---|---|
| [See which of your Threads posts perform best](https://apify.com/futurizerush/meta-threads-scraper/examples/analyze-your-threads-performance?fpr=rush) | Your posts with likes, replies, timestamps, and views when public, ready to sort |
| [Find competitors' best-performing Threads posts](https://apify.com/futurizerush/meta-threads-scraper/examples/benchmark-competitor-threads-accounts?fpr=rush) | Several competitor accounts side by side in one export |
| [Turn a Threads account into an AI knowledge base](https://apify.com/futurizerush/meta-threads-scraper/examples/build-ai-training-corpus?fpr=rush) | Clean structured text with timestamps for a RAG pipeline |
| [Audit a brand's most relevant Threads mentions](https://apify.com/futurizerush/meta-threads-scraper/examples/monitor-brand-mentions?fpr=rush) | Brand mentions with public engagement fields and a keyword-relevance flag |
| [Find creators posting about your niche](https://apify.com/futurizerush/meta-threads-scraper/examples/find-creators-by-topic?fpr=rush) | Accounts with followers, bio and profile links |
| [See what people said about a product this week](https://apify.com/futurizerush/meta-threads-scraper/examples/research-product-opinions?fpr=rush) | The last 7 days of posts, newest first |
| [Look up Threads accounts matching a keyword](https://apify.com/futurizerush/meta-threads-scraper/examples/lookup-threads-accounts-by-keyword?fpr=rush) | An account shortlist with follower counts |

### How To Use

#### Input Configuration

| Parameter | Type | Description | Example |
|-----------|------|-------------|---------|
| `mode` | string | Scraping mode: `user`, `user_reposts`, `user_replies`, `search`, or `profiles` (the shorter `reposts` / `replies` also work) | `"user"` |
| `usernames` | array | Target usernames (for User Posts, Reposts and Replies modes, max 20). Accepts bare name, with `@`, or full Threads URL. | `["zuck", "@nike", "https://threads.com/@meta"]` |
| `keywords` | array | Keywords or hashtags (required in Search and Find Profiles, optional in the three user modes to tag matching rows, max 20) | `["AI", "tech"]` |
| `search_filter` | string | Search mode only. `top` shows Threads-ranked relevant results. `recent` prioritizes newest matching public posts. | `"top"` |
| `start_date` | string | Search mode only. Show posts from this date onward (YYYY-MM-DD or "7 days"). | `"7 days"` |
| `end_date` | string | Search mode only. Show posts up to this date (inclusive); relative values count back from today. | `"2026-08-25"` |
| `max_posts` | number | Results per user or search keyword (10-10000). In User Posts, high limits need enough public posts on that account. In Search, this is a cap and available public results may be lower. Find Profiles returns up to 10 account matches per keyword and this setting does not raise that cap. | `50` |

Note: Date options and sort order apply to **Search** mode only. Leaving one set while you run another mode is fine: it is ignored and the run proceeds normally.

#### Mode 1: Scrape User Posts (with Profile Data)

Extract posts and available public profile information from a specific user:

```json
{
  "mode": "user",
  "usernames": ["zuck"],
  "max_posts": 50
}
```

##### Optional: flag a user's posts by keyword

Add `keywords` in User Posts, User Reposts or User Replies mode to flag which returned rows are textually relevant to your terms. Nothing is **removed**; each row gets a `keyword_match` value you can filter later.

```json
{
  "mode": "user",
  "usernames": ["zuck"],
  "keywords": ["AI"],
  "max_posts": 100
}
```

##### Batch Scraping Multiple Users

Scrape posts from multiple users in one run (up to 20 usernames):

```json
{
  "mode": "user",
  "usernames": ["zuck", "instagram", "nike"],
  "max_posts": 50
}
```

This returns:

- Available public bio and follower count
- Contact information extracted from bio (emails, phones, links)
- Recent public posts with engagement metrics when publicly available (likes, replies, reposts, shares, views)
- Profile verification status
- Media attachments
- Mentions and hashtags: `mentions` lists usernames found in the text, while
  `mentioned_users` and `mentioned_accounts` list the accounts the platform itself
  resolved as tagged; the two can differ on a given post

#### Mode 2: Search Posts by Keyword or Hashtag

Find public posts about a keyword or hashtag. Result volume depends on what Threads shows publicly for that term at run time.

> **Tip**: Include or omit the `#`: both `AI` and `#AI` work. Very specific or cross-language phrases may return fewer public results.

##### Understanding Search Filters

| Filter | Best For | What You Get |
|--------|----------|--------------|
| **Top** (`top`) | Discovering notable content | The posts Threads surfaces as most relevant for that term. Row order is not a popularity ranking. |
| **Recent** (`recent`) | Monitoring new activity | Prioritizes newest matching public posts; sort `created_at` descending for one combined timeline |

##### Top Results

```json
{
  "mode": "search",
  "keywords": ["artificial intelligence", "#startup"],
  "search_filter": "top",
  "max_posts": 50
}
```

##### Recent Posts

```json
{
  "mode": "search",
  "keywords": ["AI"],
  "search_filter": "recent",
  "max_posts": 50
}
```

#### Mode 3: Find Profiles (Discover Account Matches by Keyword)

Discover public Threads **account matches** for a keyword. Each keyword can return up to 10 accounts with public profile fields such as follower count, bio when present, links, and extracted contacts. Some keywords may return fewer than 10. Use related keywords to discover more accounts: an account matched by two of your keywords is still delivered once.

```json
{
  "mode": "profiles",
  "keywords": ["coffee roaster", "specialty coffee"]
}
```

Output rows are **account profiles** (not posts), with key fields such as `username`, `display_name`, `bio`, `followers_count`, `is_verified`, `profile_url`, `external_links`, `emails`, `phones`, and `search_keyword`. Empty bio/contact fields can mean the account did not publish that information.

Every row includes `record_type`: `post` for User Posts, Reposts, Replies and Search rows, and `profile` for Find Profiles rows.

> **Local search tip**: For local account discovery, include the place name in the keyword (e.g. `Brooklyn coffee` rather than only `coffee`).

#### Mode 4: Scrape User Reposts

> **(beta)** Reposts and Replies are newer than the other three modes and carry that label in the input form. They return the same row shape as User Posts plus the extra columns described below, but an occasional run can come back short.

Collect the posts an account **boosted**, rather than the posts it wrote:

```json
{
  "mode": "user_reposts",
  "usernames": ["natgeo"],
  "max_posts": 50
}
```

Each row is the **original post**, with its own author and engagement fields, plus three
columns saying who boosted it and when: `reposted_by_username`, `reposted_by_user_id` and
`reposted_at`.

If two of the accounts you asked for boosted the same post, you get one row per account,
not one row in total.

#### Mode 5: Scrape User Replies

> **(beta)** The same beta note as Mode 4 applies: same row shape as User Posts plus the extra columns below, and an occasional run can come back short.

Collect the public replies an account **wrote**:

```json
{
  "mode": "user_replies",
  "usernames": ["mosseri"],
  "max_posts": 50
}
```

Each row is the account's own reply, with the same fields any other post row carries, plus
the post it answered: `replied_to_post_code`, `replied_to_post_url`,
`replied_to_author_username`, `replied_to_author_user_id`, `replied_to_text` and
`replied_to_created_at`. When the conversation does not name the answered post
unambiguously, those fields are left empty rather than guessed.

This mode collects the replies **an account wrote**, wherever it wrote them. If you
want the other direction, the comment thread **under one specific post**, that is a
different tool: [Threads Replies Scraper](https://apify.com/futurizerush/threads-replies-scraper?fpr=rush).

Rows from all three user modes carry `source_tab` (`posts`, `reposts` or `replies`);
Search rows leave it empty. So a
combined export stays sortable by where each row came from.

#### Periodic Topic Monitoring

If you want to monitor keywords on a schedule (for lead generation, brand-mention tracking, or competitor monitoring), pair `mode: "search"` with `search_filter: "recent"` and run the actor automatically:

```json
{
  "mode": "search",
  "keywords": ["YOUR_KEYWORD_1", "YOUR_KEYWORD_2"],
  "search_filter": "recent",
  "max_posts": 30
}
```

**Suggested workflow**

1. **Schedule the actor**: Use [Apify Schedules](https://docs.apify.com/platform/schedules) to trigger regular runs.
2. **Review each run's dataset**: every post includes a unique identifier and timestamp.
3. **Handle your own downstream workflow**:
   - Deduplicate against your existing records using each post's unique identifier
   - Optionally filter by post timestamp to keep entries within your time window
   - Trigger your own notifications or follow-up workflow
   - Append new entries to your workspace or spreadsheet

**Tips**

- Each run returns a finite batch of matching public posts. For high-volume keywords, review the returned timestamps and adjust your schedule to match your monitoring needs.
- The actor does **not** perform cross-run deduplication, which is intentional, so you keep full control over data retention and storage.

#### Date Filtering (Search Mode Only)

Narrow search results to a date range. The range can be a recent window (for example the last 7 or 30 days) or an earlier period. Both relative dates (`"7 days"`, counted back from today) and absolute dates (`YYYY-MM-DD`) are accepted.

```json
{
  "mode": "search",
  "keywords": ["AI"],
  "search_filter": "recent",
  "start_date": "7 days",
  "max_posts": 50
}
```

### Output Format

#### Viewing Your Data

Use the field-focused dataset views to inspect posts, profiles, engagement fields, or contact fields. Some views are most useful for specific modes. Switch to "All fields" when you need the complete record.

- 🧵 **Posts**: post content, dates, author, media flags, and search fields
- 📊 **Engagement**: likes, replies, reposts, shares, views, and analysis flags
- 👥 **Profiles**: accounts found in Find Profiles mode
- 🔗 **Contacts**: public profile links and contact fields

#### Complete Post Record Example

Each post is saved as a separate record. Below is an illustrative example of the fields from **user mode**. The account, URL, text, dates, and numbers are fictional placeholders.

```json
{
  "record_type": "post",
  "post_url": "https://www.threads.com/@example_creator/post/EXAMPLE01",
  "post_code": "EXAMPLE01",
  "text_content": "Launching a new research note today...",
  "created_at": "2026-01-12T18:00:30+00:00",
  "created_at_display": "2026-01-12 18:00 UTC",
  "created_at_timestamp": 1768240830,
  "like_count": 268,
  "reply_count": 81,
  "repost_count": 12,
  "quote_count": 4,
  "share_count": 22,
  "view_count": 41651,
  "view_count_status": "available",
  "has_media": false,
  "media_type": "text",
  "media_url": "",
  "media_urls": [],
  "media_width": null,
  "media_height": null,
  "has_audio": null,
  "music_artist": "",
  "music_title": "",
  "music_song_id": "",
  "poll_options": [],
  "poll_votes": [],
  "poll_total_votes": null,
  "poll_is_closed": null,
  "is_ai_generated": false,
  "is_gif": false,
  "is_sticker_post": false,
  "sticker_count": 0,
  "sticker_ids": [],
  "sticker_urls": [],
  "hashtags": [],
  "mentions": [],
  "urls": [],
  "is_pinned": false,
  "is_edited": false,
  "is_paid_partnership": false,
  "accessibility_caption": "",
  "is_reply": false,
  "reply_to_username": "",
  "reply_control": "everyone",
  "is_quote_post": false,
  "quoted_post_url": "",
  "is_repost": false,
  "reposted_post_url": "",
  "repost_code": "",
  "repost_url": "",
  "reposted_by_username": "",
  "reposted_by_user_id": "",
  "reposted_at": "",
  "replied_to_post_code": "",
  "replied_to_post_url": "",
  "replied_to_author_username": "",
  "replied_to_author_user_id": "",
  "replied_to_text": "",
  "replied_to_created_at": "",
  "replied_to_available": null,
  "replied_to_like_count": null,
  "replied_to_reply_count": null,
  "replied_to_repost_count": null,
  "replied_to_quote_count": null,
  "replied_to_share_count": null,
  "conversation_id": "",
  "source_tab": "posts",
  "is_spoiler": false,
  "language": "",
  "topic_tag": "",
  "location_name": "",
  "location_id": "",
  "link_title": "",
  "mentioned_users": ["example_partner"],
  "mentioned_accounts": [{ "username": "example_partner", "user_id": "10000000002" }],
  "scraped_at": "2026-04-25T10:00:00+00:00",
  "username": "example_creator",
  "requested_username": "example_creator",
  "user_id": "10000000001",
  "display_name": "Example Creator",
  "profile_url": "https://www.threads.com/@example_creator",
  "is_verified": true,
  "followers_count": 54000,
  "bio": "Research notes and product updates",
  "profile_pic_url": "https://.../",
  "profile_pic_hd_url": "https://.../",
  "fediverse_enabled": true,
  "external_links": ["https://example.com/"],
  "emails": [],
  "phones": [],
  "bio_links": [],
  "profile_tags": ["AI", "Tech"],
  "podcast_name": "",
  "podcast_url": "",
  "podcast_platform": "",
  "search_filter": null,
  "search_keyword": null,
  "search_keywords": [],
  "keyword_match": null
}
```

> In Search mode, `search_keyword` remains the first selected keyword for backward compatibility, while `search_keywords` lists every input keyword that independently selected that deduplicated row. `keyword_match` is true when the text matches at least one of those selected keywords. A keyword is listed only when it actually selected that row for delivery. In the three user modes, `search_keywords` is empty; `search_filter` stays `null`, and `search_keyword` plus `keyword_match` are `null` unless you supply `keywords` to tag matching rows.

If a later Search or Find Profiles keyword discovers that an append-only row also matches
it, Run Results includes `keyword_membership_updates`. Match the Dataset row using the
entry's `match_field` and `match_value`, then add its `added_keywords` to your analysis.
For a username match, compare without case. This preserves every keyword relationship
without creating a duplicate Dataset row.

The same rule applies when two User Posts, Reposts or Replies inputs resolve to the
same saved result, such as an old handle and its renamed handle. Run Results includes
`input_membership_updates`: match the Dataset row with all fields in `match_fields`,
then add `added_usernames` to your input-to-result mapping. The Dataset still contains
one physical row.

> User Posts, Reposts and Replies also include `requested_username`. It normally matches the requested account; if Threads redirects an old handle after an account rename, `requested_username` keeps your original input while `username` continues to identify the actual post author.

### What To Expect

**Result availability**

- Result volume depends on how much public content exists for your query, so different
  modes and queries return different amounts.
- If a run looks lighter than expected, check **Run Results** (the run summary on the
  run's Output tab in the Apify Console), then broaden the query
  or switch the sort order.
- In a batch run, one username or keyword can fail while others still save results.
- In Search batches, `mixed_item_results` simply means keywords finished differently
  in this run. See **How to read Search stopping reasons** below for how to read it.

**Working without a login**

This actor reads only what Threads shows publicly, so niche or uncommon keywords can
return very few results, or none, even when you can see those posts while logged in.
When `no_results` appears, it means the public search window checked in this run returned
no matching rows. It does not prove that no matching post exists anywhere on Threads.
If the search was interrupted, the run is reported as partial instead of pretending the
empty result was confirmed.

**How to read Search stopping reasons**

- `requested_limit_reached`: the run delivered the number you asked for. There may still
  be more matching posts.
- `search_window_limit_reached`: the planned search window returned fewer posts than you
  asked for. Another sort order or a related keyword may find more.
- `date_filter_unverifiable`: at least one candidate did not include a usable public
  timestamp, so the Actor could not safely decide whether it belonged inside your date
  range. The run stays partial instead of claiming the range was empty.
- `search_depth_limit_reached`: the run reached its collection limit for that keyword before your
  number. More posts may remain.
- `search_time_budget_reached`: the time allowed for that keyword ended before reaching your
  number. More matching posts may remain.
- `low_yield_stop`: the run stopped because it was no longer finding new posts for that
  keyword. More posts may still exist.
- `mixed_item_results`: keywords had different completion outcomes or stopped for
  different reasons. It does **not** mean Threads has no more matching posts. Check
  `search_items` in Run Results to see which keyword was short and why; this is not
  proof that the shorter keywords are exhausted.
- `budget_reached`: the run stopped at the limit you set for it. Everything saved
  before that point is kept, and a new run with a higher limit can continue past it.
- `time_limit_reached` / `run_stopped_early`: the run ended before finishing, for
  example at its time limit or after being stopped, and wrapped up with what it had.
- `temporarily_unavailable`: part of the collection could not be completed on this
  attempt. Running it again can pick up what is missing.

**Per-keyword codes in `search_items`**

Each keyword in `search_items` also reports its own `status` (`complete`, `partial`, or
`failed`) and its own `stop_reason`. Besides the reasons above, a keyword can report an
operational code about this run's attempt: `setup_unavailable` (search could not be set
up for this keyword this time), `request_timeout` or `request_unavailable` (a page
request ran out of time or could not be completed), `save_unavailable` or
`save_incomplete` (prepared rows could not be saved, or only partly saved),
`details_unavailable` or `details_incomplete` (public author details could not be fully
attached), or `unexpected_error`. These codes describe this run's attempt, not the
keyword itself; running again usually completes them.

`posts_saved` counts unique physical Dataset rows. `search_items[].results_saved` counts
confirmed keyword memberships, so one deduplicated post selected by two keywords counts
once in `posts_saved` and once for each keyword. This is expected and does not mean the
row was saved twice.

If you need content that is visible only inside your own logged-in account, this is not
the right tool.

### FAQ

**Q: What engagement metrics can I get?**
A: The scraper extracts likes, replies, reposts, quotes, shares, and views when publicly available. On some posts, `share_count` and `view_count` can be `null`. `view_count_status` tells you which of three things happened: `available` (a number was read, including 0), `not_public_yet` (the post is too recent for a view count to exist yet), or `not_checked` (the count was not read on this run; run it again to pick it up). In Run Results, `view_counts_missing` counts the post rows this run checked that had no view count, and `view_counts_not_public_yet` reports how many of those are simply too recent.

**Q: How does contact information extraction work?**
A: Contact fields depend on the public bio text and profile links. The actor does not read text inside images or on linked pages.

**Q: Is there an identifier I can join on besides the username?**

A: Yes. Every post author and every profile record carries `user_id` next to `username`. A username is the account's handle; `user_id` is a separate identifier assigned by the platform and is not derived from it. Across our runs the same account returns the same `user_id` in User Posts, Search and Find Profiles alike, so it is the field to join on when a handle alone would be ambiguous. When it could not be resolved for a record it is `null`, never an empty string, so it is always clear which case you are looking at.

**Q: How do I see the complete field set?**
A: In the Apify console, switch to "All fields". You will see the complete record fields, including fields that may be `null` for some records.

**Q: Does it support batch scraping of multiple users or keywords?**
A: Yes. You can enter up to 20 usernames or 20 keywords in one run. Results are combined into the same dataset.

**Q: Can I tell which posts are sponsored / paid partnerships?**
A: Every post includes an `is_paid_partnership` field. `true` means a paid-partnership or branded-content signal is publicly shown for that row. `false` means that signal was not present in the public data returned for that row.

**Q: Can I see quote posts and reposts, and the original they reference?**
A: Yes. Quotes are marked on the row itself with `is_quote_post` and `quoted_post_url`. Reposts come from 🔁 User Reposts mode, where each row is the original post and `reposted_by_username`, `reposted_by_user_id`, `reposted_at` and `source_tab` say who boosted it and when.

**Q: Can I distinguish top-level posts from replies?**
A: Yes, when reply context is present in the returned public data. `is_reply` marks replies, `reply_to_username` shows who is being replied to, and `reply_control` reflects the reply-audience setting when available.

**Q: What about image alt text and media size?**
A: When available, `accessibility_caption` contains an image description; otherwise it is an empty string (""). `media_width` and `media_height` contain the available media dimensions in pixels and are null when not available (for example text-only posts).

**Q: Can I tell whether a post has a public AI-content label or whether a video has sound?**
A: `is_ai_generated` is true when the post carries an AI-content label, false when the checked public post has no such label, and null when it cannot be determined. `has_audio` is true/false for checked video posts and null for non-video posts or unavailable detail.

**Q: Is there a Fediverse / ActivityPub signal?**
A: Yes. `fediverse_enabled` is true when a Fediverse sharing indicator is publicly shown on the profile; otherwise it is false or null, depending on whether profile details were available for that row.

**Q: Do I need to choose between hashtag and full-text search?**
A: No. Enter your keyword with or without `#`, then pick a `top` or `recent` sort order. Results depend on what Threads makes publicly available.

**Q: How does Find Profiles work, and how many accounts can it return?**
A: Find Profiles (`mode: "profiles"`) returns up to 10 public account matches per keyword with profile fields such as follower count, bio when present, links, and contacts. Some keywords may return fewer than 10. To reach more accounts, use several related keywords.

**Q: How can I find local accounts?**
A: Put the place name directly in the keyword (e.g. `austin coffee`) so the search phrase is what the matching is based on. Geo-targeting is not supported.

**Q: Why do search results seem unrelated to the keyword?**
A: Threads search ranking is not strict keyword-only matching. Results can include broadly related content and sometimes unrelated content. Use `keyword_match` as a text-relevance aid in downstream filtering; it is true when the row text matches at least one keyword in `search_keywords`, but it is not an exact-match guarantee.

**Q: Why do I get fewer results than my max\_posts limit?**
A: `max_posts` is a ceiling, not a promise. One run checks a bounded public search window, so it can return fewer rows even for an active keyword. Read `collection_stop_reason` in **Run Results**: it names why the run stopped (the full list is under **How to read Search stopping reasons** above). None of the short-result reasons means every matching post on Threads was checked. Threads also limits how much of a search a visitor who is not logged in can see, and that visible window changes over time; when it is what ended the run, the run is marked partial rather than complete. You can try a broader keyword, another sort order, a wider date range, or split the search into related keywords.

**Q: Why are bio or followers\_count sometimes empty in Search mode?**
A: Some accounts expose limited public profile fields in search results. When a field is not publicly available for that account at run time, it may be empty.

### Explore Threads Workflows

- [Threads Replies Scraper](https://apify.com/futurizerush/threads-replies-scraper?fpr=rush): collect public replies and comments for conversation analysis.
- [Threads 海巡 - 貼文、個人檔案與關鍵字搜尋](https://apify.com/futurizerush/meta-threads-scraper-zh-tw?fpr=rush): the Traditional Chinese edition of this Actor, with a zh-TW interface and output labels.

### Disclaimer

This Actor is provided for research and educational purposes. You are solely responsible for how you use it and for ensuring that your use of the Actor and any data it returns complies with all laws and regulations applicable to you. Data availability, completeness, and accuracy may vary over time and between runs. The developers accept no liability for how this tool or the data it returns is used.

***

**Keywords**: Threads scraper, Threads search scraper, Threads data scraper, Meta Threads scraper, Threads post extractor, Threads profile scraper, Threads hashtag search, Threads keyword search, Threads search without login, Threads data extraction, export Threads posts, download Threads data, Threads exporter, Threads posts, Threads engagement metrics, follower count scraper, Threads bio email extractor, Threads account finder, influencer discovery, Threads influencer research, social media scraper, social media monitoring, brand monitoring, competitor analysis, competitor intelligence, trend research, content research tool, social listening tool, market research, Instagram Threads, public Threads data, Threads automation, Threads search, OpenClaw, Claude Code, Gemini CLI, Antigravity, Codex, ChatGPT

# Actor input Schema

## `mode` (type: `string`):

Pick one, then fill the matching field below:
• 👤 User Posts → 👤 Usernames. Public posts from those accounts.
• 🔁 User Reposts → 👤 Usernames. What they boosted, and when.
• 💬 User Replies → 👤 Usernames. Replies they wrote, each with the post it answered.
• 🔎 Search → 🏷️ Keywords. Public posts matching your keywords or hashtags, with an optional date range.
• 👥 Find Profiles → 🏷️ Keywords. Public accounts matching your keywords, up to 10 per keyword.

## `usernames` (type: `array`):

Required in 👤 User Posts, 🔁 User Reposts and 💬 User Replies modes (ignored in other modes). One or more Threads usernames: bare name (zuck), @-prefixed (@zuck), or full URL (https://threads.com/@zuck or https://threads.net/@zuck).

## `keywords` (type: `array`):

Required in 🔎 Search and 👥 Find Profiles. Optional in 👤 User Posts, 🔁 User Reposts and 💬 User Replies, where matching rows are tagged and nothing is dropped. The # is optional: both 'AI' and '#AI' work. In Find Profiles, adding a place name (e.g. 'austin coffee') helps surface local accounts.

## `max_posts` (type: `integer`):

A cap per user or per keyword, not a total for the run. Every input lands in the same dataset.
• 👤 User Posts / 🔁 Reposts / 💬 Replies: how many you get depends on what that account has posted publicly.
• 🔎 Search: a cap. The public results available at run time may be fewer.
• 👥 Find Profiles: up to 10 accounts per keyword, which this setting cannot raise.

## `search_filter` (type: `string`):

Only used in 🔎 Search mode. 'Top' returns what Threads surfaces as most relevant for that term; row order is not a popularity ranking. 'Recent' prioritizes the newest matching public posts; sort exported created\_at values for one combined timeline.

## `start_date` (type: `string`):

Used in 🔎 Search mode to show posts from this date onward. Supports YYYY-MM-DD or relative values such as '7 days' and '1 month'. Other modes ignore it and collect posts as usual.

## `end_date` (type: `string`):

Used in 🔎 Search mode to show posts up to this date (inclusive). YYYY-MM-DD is recommended for clarity. Relative values such as '7 days' mean that long ago. Other modes ignore it and collect posts as usual.

## Actor input object example

```json
{
  "mode": "user",
  "usernames": [
    "zuck"
  ],
  "max_posts": 50,
  "search_filter": "top"
}
```

# Actor output Schema

## `results` (type: `string`):

Scraped results: posts (User Posts / Reposts / Replies / Search) or accounts (Find Profiles)

## `runSummary` (type: `string`):

Run status, saved-result counts, partial-result reasons, and data-quality details

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "user",
    "usernames": [
        "zuck"
    ],
    "max_posts": 50,
    "search_filter": "top"
};

// Run the Actor and wait for it to finish
const run = await client.actor("futurizerush/meta-threads-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "user",
    "usernames": ["zuck"],
    "max_posts": 50,
    "search_filter": "top",
}

# Run the Actor and wait for it to finish
run = client.actor("futurizerush/meta-threads-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "user",
  "usernames": [
    "zuck"
  ],
  "max_posts": 50,
  "search_filter": "top"
}' |
apify call futurizerush/meta-threads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,futurizerush/meta-threads-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/lct1dlYksEDIG9If9/builds/y7FMcKFevXhElRL8l/openapi.json
