# Meta Threads Public Scraper (`rainminer/threads-public-scraper`) Actor

Extract public Meta Threads profiles, posts, and keyword search results — stable post IDs, media URLs, engagement metrics, and explicit extraction completeness flags. No login or cookies required.

- **URL**: https://apify.com/rainminer/threads-public-scraper.md
- **Developed by:** [rainminer](https://apify.com/rainminer) (community)
- **Categories:** Social media
- **Stats:** 3 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.99 / 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/platform/actors/running/actors-in-store#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

### What does Meta Threads Public Scraper do?

**Meta Threads Public Scraper** collects public data from [Threads](https://www.threads.com/) without login. Point it at profile URLs, post URLs, or keyword search pages and export stable post IDs, usernames, text, engagement counts, and media URLs — with explicit extraction completeness flags so empty shells are not treated as successful rows.

Compatible with common inputs/outputs from popular Threads Store Actors (e.g. `mode`, `keywords`, `max_posts`, snake\_case field aliases) so you can switch with minimal pipeline changes — while keeping public-only scraping, stable IDs, absolute media URLs, and hollow-row skipping.

### Why scrape Threads?

- **Brand monitoring** — Track public mentions and keyword conversations.
- **Creator research** — Pull public profile bios, follower counts, and recent posts.
- **Content analysis** — Export post text, media URLs, and engagement for research workflows.
- **Competitive listening** — Compare public posting patterns across accounts and topics.

### What data can you extract?

| Field                                                          | Description                                                                                                             |
| -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| id / code / url                                                | Stable Threads post pk, shortcode, and public post URL                                                                  |
| userId / username / fullName                                   | Public author identifiers                                                                                               |
| text                                                           | Post caption text                                                                                                       |
| likeCount / replyCount / repostCount / quoteCount / shareCount | Public engagement metrics when present                                                                                  |
| imageUrl / imageUrls / videoUrls / mediaUrls / mediaUrl        | Media CDN URLs (primary image + gallery)                                                                                |
| followerCount / biography / isVerified                         | Profile fields on profile records and attached to posts when available                                                  |
| extractionComplete / extractionGaps                            | Honest completeness metadata (no silent hollow rows)                                                                    |
| recordType                                                     | `profile` or `post`                                                                                                     |
| Competitor aliases                                             | Same values under snake\_case keys (`post_code`, `text_content`, `like_count`, `created_at`, `user_id`, `media_urls`, …) |

### How to scrape public Threads data

1. Open the Actor in Apify Console.
2. Add start URLs such as `https://www.threads.com/@zuck`, a post URL, or `https://www.threads.com/search?q=apify`.
3. Optionally add usernames or search queries (or competitor-style `mode` + `keywords` + `max_posts`).
4. Set **Maximum items per input** (default 5).
5. Run the Actor and download JSON/CSV/Excel from the dataset.

### Input

- **Start URLs** — profile, post (`/@user/post/CODE` or `/t/CODE`), or search URLs on `threads.com` / `threads.net`.
- **URLs (alias)** — optional alias for Start URLs.
- **Usernames** — bare names, `@handle`, or full profile URLs.
- **Search queries** — public keyword/hashtag terms.
- **Keywords (alias)** — competitor-compatible; search terms or optional `keyword_match` tags in user mode.
- **Mode (optional)** — `user` / `search` / `profiles` for competitor-style workflows.
- **Maximum items per input** — per URL / username / query (profile and post rows both count). Aliases: `max_posts`, `resultsLimit`.
- **Search sort order** — `top` or `recent` (`search_filter`).
- **Start/end date** — optional search date window (`YYYY-MM-DD` or `7 days`).
- **Include thread reply posts** — keep author self-reply chain items when enabled. Alias: `includeReplies`.
- **Include profile records** — push one profile row before posts for profile inputs.
- **Proxy configuration** — optional; defaults to no Apify Proxy.

#### Competitor-compatible examples

User posts:

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

Search:

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

### Output example

```json
{
  "recordType": "post",
  "id": "3957216315664483403",
  "code": "Dbq20Xaj8RL",
  "url": "https://www.threads.com/@zuck/post/Dbq20Xaj8RL",
  "text": "Announcing Muse Code beta...",
  "username": "zuck",
  "userId": "63055343223",
  "likeCount": 2445,
  "replyCount": 252,
  "imageUrl": "https://scontent.../...",
  "imageUrls": ["https://scontent.../..."],
  "mediaUrls": ["https://scontent.../..."],
  "extractionComplete": true,
  "extractionGaps": [],
  "sourceType": "profile",
  "sourceValue": "zuck",
  "record_type": "post",
  "post_code": "Dbq20Xaj8RL",
  "post_url": "https://www.threads.com/@zuck/post/Dbq20Xaj8RL",
  "text_content": "Announcing Muse Code beta...",
  "user_id": "63055343223",
  "like_count": 2445,
  "reply_count": 252,
  "created_at_timestamp": 1785956967,
  "media_urls": ["https://scontent.../..."]
}
```

### FAQ

**Do I need a Threads login or cookies?**

No. The Actor only uses public pages. Private accounts and login-only feeds are out of scope.

**Why are results limited to the first page?**

Public crawlable HTML includes the first Relay batch of posts/search results. Logged-in pagination APIs are not used.

**What about hollow or incomplete rows?**

Rows without a stable id or without usable public fields are skipped. Partial rows keep `extractionComplete: false` and list gaps in `extractionGaps`.

**Which URLs are supported?**

`https://www.threads.com/@username`, `https://www.threads.com/@username/post/CODE`, `https://www.threads.com/t/CODE`, and `https://www.threads.com/search?q=...` (`.net` hosts are normalized).

### Image Credit

Image credit: [Threads](https://www.threads.com/)

# Actor input Schema

## `startUrls` (type: `array`):

Public Threads URLs: profile (https://www.threads.com/@username), post (https://www.threads.com/@username/post/CODE or /t/CODE), or search (https://www.threads.com/search?q=keyword).

## `urls` (type: `array`):

Optional alias for Start URLs. Accepts the same profile/post/search links (string or {url} objects).

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

Bare Threads usernames (zuck or @zuck) or full profile URLs. Each becomes a public profile URL. In competitor mode=user this is the primary input.

## `searchQueries` (type: `array`):

Keywords or hashtags for public Threads search (e.g. AI, #tech).

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

Competitor-compatible alias. In mode=search/profiles: search terms. In mode=user: optional tags that set keyword\_match without dropping posts. Without mode: treated like Search queries.

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

Competitor-compatible mode: user (usernames → profile posts), search (keywords → posts), profiles (keywords → discover public accounts). Leave empty to use Start URLs / Usernames / Search queries together.

## `maxItems` (type: `integer`):

Maximum dataset rows to return per start URL, username, or search query. Profile and post rows both count toward this limit.

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

Competitor-compatible alias for Maximum items per input.

## `resultsLimit` (type: `integer`):

Optional alias for Maximum items per input.

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

Competitor-compatible search sort: top (default / relevance) or recent. Applied to searchQueries/keywords search URLs.

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

Optional post date lower bound for search results (YYYY-MM-DD or relative like "7 days"). Search mode only when mode is set.

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

Optional post date upper bound for search results (YYYY-MM-DD or relative like "1 day"). Search mode only when mode is set.

## `includeThreadReplies` (type: `boolean`):

When true, push every post in a thread chain (author self-replies). When false, only the first post of each thread edge is kept.

## `includeReplies` (type: `boolean`):

Alias for Include thread reply posts.

## `includeProfileRecords` (type: `boolean`):

When scraping a profile URL, also push one profile metadata record (followers, bio, avatar) before posts.

## `proxyConfiguration` (type: `object`):

Optional proxy. Public crawler-facing Threads HTML usually works without a proxy.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.threads.com/@zuck"
    },
    {
      "url": "https://www.threads.com/search?q=apify&serp_type=default"
    }
  ],
  "usernames": [
    "instagram"
  ],
  "searchQueries": [],
  "maxItems": 5,
  "search_filter": "top",
  "includeThreadReplies": false,
  "includeProfileRecords": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://www.threads.com/@zuck"
        },
        {
            "url": "https://www.threads.com/search?q=apify&serp_type=default"
        }
    ],
    "usernames": [
        "instagram"
    ],
    "searchQueries": [],
    "maxItems": 5,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rainminer/threads-public-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 = {
    "startUrls": [
        { "url": "https://www.threads.com/@zuck" },
        { "url": "https://www.threads.com/search?q=apify&serp_type=default" },
    ],
    "usernames": ["instagram"],
    "searchQueries": [],
    "maxItems": 5,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("rainminer/threads-public-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 '{
  "startUrls": [
    {
      "url": "https://www.threads.com/@zuck"
    },
    {
      "url": "https://www.threads.com/search?q=apify&serp_type=default"
    }
  ],
  "usernames": [
    "instagram"
  ],
  "searchQueries": [],
  "maxItems": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call rainminer/threads-public-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rainminer/threads-public-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/2mPMzBlKhS9IVpe9i/builds/Fupe2mVkHe1k717C5/openapi.json
