# Threads Scraper (`crawlerbros/threads-scraper`) Actor

Scrape public Threads (threads.com) profiles, posts, replies, media, reposts, keyword search, and hashtag search - real engagement counts, captions, media, and profile bios. No login or API key required.

- **URL**: https://apify.com/crawlerbros/threads-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Social media, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

## Threads Scraper

Extract public posts, replies, media, and profile info from [Threads](https://www.threads.com) — Meta's text-based social platform. No login, cookies, or API key required.

### What you can scrape

- **Profile posts, replies, media, and reposts** — for any public Threads username
- **Keyword search** — top or recent posts matching a search term
- **Hashtag / topic search** — posts tagged with a topic
- **A single post and its visible replies**
- **Profile metadata** — display name, bio, follower count, verification badge, linked Instagram

### Modes

| Mode | Description |
|------|-------------|
| `profile` | Recent posts on a user's profile (`username`, **required**) |
| `profileReplies` | Recent replies posted by a user (`username`, **required**) |
| `profileMedia` | Recent posts with photos/videos by a user (`username`, **required**) |
| `profileReposts` | Recent reposts by a user (`username`, **required**) |
| `search` | Keyword search across Threads (`searchQuery`, **required**) |
| `tag` | Hashtag / topic search (`tag`, **required**) |
| `postReplies` | A specific post plus its visible replies (`postUrl`, **required**) |

### Input

| Field | Type | Description |
|-------|------|-------------|
| `mode` | string | One of the 7 modes above |
| `username` | string | Threads username without `@` (profile modes) |
| `searchQuery` | string | Keyword/phrase to search (mode=search) |
| `tag` | string | Hashtag/topic without `#` (mode=tag) |
| `postUrl` | string | Full Threads post URL (mode=postReplies) |
| `sortBy` | string | `default` (top/relevance) or `recent` (mode=search) |
| `includeProfileInfo` | boolean | Also emit one profile-metadata record for profile modes (default `true`) |
| `maxItems` | integer | Maximum post/reply records to return (1–100, default 25) |
| `proxyConfiguration` | object | Apify proxy config. Defaults to the free `AUTO` datacenter group — no residential proxy or paid add-on needed. |

### Output

Post/reply record:

```json
{
  "recordType": "post",
  "mode": "profile",
  "postUrl": "https://www.threads.com/@zuck/post/DZpPDXbCeTt",
  "shortcode": "DZpPDXbCeTt",
  "authorUsername": "zuck",
  "postText": "500M monthly actives on Threads in less than 3 years. Thanks for making this platform what it is. 🙏",
  "publishedAt": "2026-06-16T10:59:56.000Z",
  "likeCount": 18000,
  "commentCount": 4700,
  "repostCount": 838,
  "shareCount": 491,
  "hasImage": false,
  "hasVideo": false,
  "scrapedAt": "2026-08-03T12:00:00.000000+00:00"
}
```

Profile-info record (emitted once per run when `includeProfileInfo=true` and mode is a profile mode):

```json
{
  "recordType": "profile",
  "mode": "profile",
  "username": "zuck",
  "profileUrl": "https://www.threads.com/@zuck",
  "displayName": "Mark Zuckerberg",
  "bio": "Mostly superintelligence and MMA takes",
  "followersCount": 5700000,
  "threadsCount": 152,
  "isVerified": true,
  "instagramUrl": "https://www.instagram.com/zuck/",
  "scrapedAt": "2026-08-03T12:00:00.000000+00:00"
}
```

Fields such as `postText`, `imageUrl`, `externalLinkUrl`, `externalLinkDomain`, and `externalLinkTitle` are only included when the post actually has that content — no null or empty values are emitted.

### Usage examples

#### A user's recent posts

```json
{ "mode": "profile", "username": "zuck", "maxItems": 25 }
```

#### A user's recent media posts

```json
{ "mode": "profileMedia", "username": "natgeo", "maxItems": 20 }
```

#### Keyword search, most recent first

```json
{ "mode": "search", "searchQuery": "openai", "sortBy": "recent", "maxItems": 25 }
```

#### Hashtag search

```json
{ "mode": "tag", "tag": "ai", "maxItems": 25 }
```

#### A post and its replies

```json
{ "mode": "postReplies", "postUrl": "https://www.threads.com/@zuck/post/DZpPDXbCeTt", "maxItems": 25 }
```

### Use cases

- **Social listening** — track what people are saying about your brand, product, or topic via keyword/hashtag search
- **Competitor monitoring** — follow a competitor's Threads profile for new posts and engagement trends
- **Influencer research** — check an account's follower count, bio, and recent post performance before a partnership
- **Content curation** — pull recent posts on a topic or hashtag to feature in a newsletter or roundup
- **Community analysis** — measure reply/repost activity on a specific post or thread

### FAQ

**Do I need a Threads or Instagram account?**
No. Everything this actor returns is visible to anyone browsing Threads while logged out.

**Do I need a proxy?**
No, but it's enabled by default at no extra cost. `proxyConfiguration` defaults to Apify's free `AUTO` (datacenter) proxy group; the actor works the same with it turned off.

**Why do I only get a handful of results?**
Threads intentionally caps how much it shows to logged-out visitors — after a bounded window of recent posts, it displays a "Log in to see more" wall. This actor extracts exactly that visible window and does not (and cannot, without login) go past it. Typical windows are roughly 4–25 items depending on the page. This is a platform limitation, not a bug.

**Why is `postText` missing on some records?**
Some posts are image/video-only with no caption. Only fields that are actually populated are included in the output — never a placeholder like `"N/A"`.

**What does `likeCount: 0` mean — is that a placeholder?**
No, it's real. Threads hides the numeric badge on an engagement button entirely when its count is zero; this actor reads each button individually and reports the true count, including zero.

**Are engagement counts exact?**
They reflect what Threads displays on the page (e.g. `"1.2K"` is parsed to `1200`), which is Threads' own abbreviated public count, not a raw exact number for large counts.

**Can I scrape private accounts?**
No. Only public profiles and posts are accessible without login.

# Actor input Schema

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

What to fetch from Threads.

## `username` (type: `string`):

Threads username without the @ sign, e.g. 'zuck'. Required for mode=profile / profileReplies / profileMedia / profileReposts.

## `searchQuery` (type: `string`):

Keyword or phrase to search for on Threads.

## `tag` (type: `string`):

Hashtag or topic name to search, without the # sign, e.g. 'ai' or 'mma'.

## `postUrl` (type: `string`):

Full URL of a Threads post to fetch along with its visible replies, e.g. 'https://www.threads.com/@zuck/post/DZpPDXbCeTt'.

## `sortBy` (type: `string`):

Sort order for keyword search results.

## `includeProfileInfo` (type: `boolean`):

For profile modes, also push one extra record with the profile's display name, bio, follower count, verification status, and Instagram link.

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

Maximum number of post/reply records to return. Note: Threads caps anonymous (logged-out) viewing to a small window of recent content per page (typically 4-25 items depending on the page), so raising this above what a given page actually contains has no further effect.

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

Route requests through Apify proxy. The free AUTO (datacenter) group is enabled by default — no residential proxy or paid add-on is needed for this actor. You can disable it if you prefer direct requests.

## Actor input object example

```json
{
  "mode": "profile",
  "username": "zuck",
  "searchQuery": "openai",
  "tag": "ai",
  "postUrl": "https://www.threads.com/@zuck/post/DZpPDXbCeTt",
  "sortBy": "default",
  "includeProfileInfo": true,
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `items` (type: `string`):

Dataset containing all scraped Threads posts/replies and (optionally) profile metadata.

# 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": "profile",
    "username": "zuck",
    "searchQuery": "openai",
    "tag": "ai",
    "postUrl": "https://www.threads.com/@zuck/post/DZpPDXbCeTt",
    "sortBy": "default",
    "includeProfileInfo": true,
    "maxItems": 25,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/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": "profile",
    "username": "zuck",
    "searchQuery": "openai",
    "tag": "ai",
    "postUrl": "https://www.threads.com/@zuck/post/DZpPDXbCeTt",
    "sortBy": "default",
    "includeProfileInfo": True,
    "maxItems": 25,
    "proxyConfiguration": { "useApifyProxy": True },
}

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

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": "profile",
  "username": "zuck",
  "searchQuery": "openai",
  "tag": "ai",
  "postUrl": "https://www.threads.com/@zuck/post/DZpPDXbCeTt",
  "sortBy": "default",
  "includeProfileInfo": true,
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call crawlerbros/threads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=crawlerbros/threads-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/sMcLCMHFmYJrrzw5e/builds/1xHFlAm3FTd67o45X/openapi.json
