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

Extract posts, captions, engagement metrics, and media from Threads (by Meta) profiles and direct post URLs. No API key, no login, no browser.

- **URL**: https://apify.com/aurenic/threads-scraper.md
- **Developed by:** [Aurenic](https://apify.com/aurenic) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 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.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Threads Scraper

Extract posts, captions, engagement metrics, and media from Threads (by Meta) profiles and direct post URLs. No API key, no login, no browser.

### What does Threads Scraper do?

Scrape public Threads content in four modes:

- **Profile posts** — pass usernames, get their recent posts with caption, likes, replies, reposts, quotes, media, and timestamps.
- **Direct post URLs** — pass Threads post URLs, get the specific post's full record.
- **Keyword search** — pass keywords, get ~20–25 matching public posts per query. Batch many queries to scale.
- **Hashtag search** — pass hashtags, get ~20–25 matching public posts per hashtag.

Uses the server-rendered HTML that Threads serves to crawler and browser user agents, with residential proxy rotation to avoid per-IP throttling. No login, no API key, no browser. No GraphQL signing, no PoToken, no Cloudflare managed challenge.

### Output fields

| Field | Description |
|---|---|
| code | Threads post short code |
| url | Direct post URL |
| authorUsername | Author handle |
| authorFullName | Author display name |
| authorId | Author ID |
| authorVerified | Verified flag |
| caption | Post text (truncated to 5,000 chars) |
| likeCount | Likes |
| replyCount | Direct replies |
| repostCount | Reposts |
| quoteCount | Quotes |
| shareCount | Shares |
| takenAt | ISO 8601 timestamp |
| mediaUrls | Image and video URLs |
| mediaType | `image` / `video` / `text` |
| language | Post language |
| isReply | Reply flag |
| query | The keyword or hashtag that surfaced this post (search modes only) |
| sourceType | `keyword` or `hashtag` (search modes only) |

### Who is it for?

- **Social media managers** tracking competitor posting cadence and engagement
- **Content researchers** analyzing top-performing posts by topic or account
- **Brand monitoring teams** watching product mentions
- **Growth teams** building cross-platform creator databases
- **Data scientists** building Threads engagement datasets

### Pricing

**$1.60 per 1,000 results.** No subscription.

| Results | Cost |
|---|---|
| 100 | $0.16 |
| 1,000 | $1.60 |
| 10,000 | $16.00 |

### How to use it

1. Pick a **Mode**.
2. For profile mode: enter **Usernames**.
3. For search mode: enter **Search Queries**. For hashtag mode: enter **Hashtags**. Batch 10–50 queries to scale.
4. Set **Max Items** (default 100) and **Max Posts per Query** (default 50).
5. Click **Start**.

### Output example

```json
{
  "recordType": "threads-post",
  "postId": "3412345678901234567",
  "code": "C1a2B3c4D5e",
  "url": "https://www.threads.net/@zuck/post/C1a2B3c4D5e",
  "authorUsername": "zuck",
  "authorFullName": "Mark Zuckerberg",
  "authorId": "123456789",
  "authorVerified": true,
  "caption": "Great conversation on the future of AI...",
  "likeCount": 45200,
  "replyCount": 1200,
  "repostCount": 890,
  "quoteCount": 45,
  "shareCount": null,
  "takenAt": "2026-09-20T14:30:00.000Z",
  "mediaUrls": ["https://scontent.cdninstagram.com/..."],
  "mediaType": "image",
  "language": "en",
  "isReply": false,
  "context": "@zuck",
  "scrapedAt": "2026-09-22T12:00:00.000Z"
}
```

### Technical details

- **No API key, no login, no browser.** Uses Threads' public GraphQL endpoint (`graphql.threads.net`) — the same endpoint Meta serves to unauthenticated visitors.
- **Crawler-UA SSR path** — Threads serves full server-rendered HTML to `facebookexternalhit` and browser user agents. The actor parses JSON-LD, `data-sjs` blocks, and raw post codes from that HTML.
- **Residential proxy built-in.** Threads throttles datacenter IPs after a few requests. All fetches route through Apify's residential proxy automatically.
- **Session cookie harvesting** — the actor captures `sessionid`/`csrftoken` from the initial HTML response if present, for requests that benefit from a session.

### Known limits

- **Profile mode is capped at ~25–30 posts per profile** by Threads itself. Logged-out profile views return only the most recent posts. This is not an actor limitation — every Threads scraper on the market hits this same ceiling.
- **Search mode returns ~20–25 posts per query.** Threads does not paginate logged-out search results. To scale, batch 10–50 queries (or hashtags) in a single run.
- **Public content only.** Private profiles and protected posts are not accessible.
- **Caption truncated at 5,000 characters.**
- **Comment/reply scraping not supported** in this version.
- **Residential proxy is required.** Threads throttles datacenter IPs after a handful of requests. The actor routes all fetches through residential proxy automatically.

### FAQ

**Do I need a Threads account?** No. The actor scrapes public content without authentication.

**Do I need a proxy?** No. Datacenter IPs work for public Threads content.

**Why is search limited to ~20 posts per query?** Threads does not paginate logged-out search results. Each query returns a single batch. To scale, pass 10–50 queries in one run — the actor dedupes across all of them.

**How many posts can I get per profile?** Up to 50 by default (`maxPostsPerProfile`), configurable to 500.

**How do I export data?** After a run, go to Storage → Export as JSON, CSV, Excel.

### Support

Open an issue on the Actor's page for bugs or feature requests.

# Actor input Schema

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

What to scrape. Note: profile mode is capped at ~25-30 posts by Threads itself (logged-out SSR limit). Search and hashtag modes return more per run.

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

Threads usernames without the @ prefix (e.g. zuck, natgeo).

## `postUrls` (type: `array`):

Direct Threads post URLs (https://www.threads.net/@user/post/CODE).

## `searchType` (type: `string`):

Search mode qualifier.

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

Hard cap on posts per run.

## `maxPostsPerProfile` (type: `integer`):

Cap per profile. Threads caps logged-out profile views at ~25-30 posts regardless of this value.

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

Include replies in output. Currently all public posts are returned; reserved for future filtering.

## `includeMedia` (type: `boolean`):

Include image and video URLs in each post record.

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

Keywords to search. Each returns ~17-18 posts (Threads logged-out limit per query). Batch many queries to scale.

## `hashtags` (type: `array`):

Hashtags to search (with or without #). Each returns ~17-18 posts.

## `maxPostsPerQuery` (type: `integer`):

Cap per search query / hashtag. Threads logged-out returns ~17-18 per query, so values above that are capped by Threads.

## Actor input object example

```json
{
  "mode": "profile",
  "usernames": [
    "zuck"
  ],
  "postUrls": [],
  "searchType": "top",
  "maxItems": 100,
  "maxPostsPerProfile": 50,
  "includeReplies": false,
  "includeMedia": true,
  "searchQueries": [
    "artificial intelligence",
    "build in public"
  ],
  "hashtags": [
    "buildinpublic"
  ],
  "maxPostsPerQuery": 50
}
```

# Actor output Schema

## `results` (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 = {
    "usernames": [
        "zuck"
    ],
    "postUrls": [],
    "searchQueries": [
        "artificial intelligence",
        "build in public"
    ],
    "hashtags": [
        "buildinpublic"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("aurenic/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 = {
    "usernames": ["zuck"],
    "postUrls": [],
    "searchQueries": [
        "artificial intelligence",
        "build in public",
    ],
    "hashtags": ["buildinpublic"],
}

# Run the Actor and wait for it to finish
run = client.actor("aurenic/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 '{
  "usernames": [
    "zuck"
  ],
  "postUrls": [],
  "searchQueries": [
    "artificial intelligence",
    "build in public"
  ],
  "hashtags": [
    "buildinpublic"
  ]
}' |
apify call aurenic/threads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aurenic/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/eNEIDcTTNY3EI4z7g/builds/Hdu8Byk9ohxjVQwoH/openapi.json
