# Threads Scraper - Profile Posts, Search & Hashtags, No Login (`scrapewise/threads-scraper`) Actor

Scrape Meta Threads (threads.com, threads.net) without login: every public post of a profile, keyword and #hashtag search (top or recent), posts by link. Text, date, likes, replies, reposts, quotes, images, videos, mentions and author. Only new posts on schedules. US$ 5 per 1,000.

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

## Pricing

from $4.25 / 1,000 post delivereds

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?

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

Scrape **Meta Threads** (threads.com, formerly threads.net) without login or cookies. Get **every public post of
a profile**, page after page, search any **keyword or #hashtag** (top or recent), or open posts by link. Each post
comes as one row with its text, date, likes, replies, reposts, quotes, images, videos, hashtags, mentions, links
and the author's username, name and verified badge. Export as JSON, CSV or Excel, or read it from the Apify API.

### At a glance

| Your Apify plan | Price per 1,000 posts |
|---|---|
| Free | US$ 5.00 |
| Bronze | US$ 4.75 |
| Silver | US$ 4.50 |
| Gold and above | US$ 4.25 |

- **No monthly fee, no start fee.** Error rows and duplicates are free, and there is no Apify compute bill on top.
- **Profiles:** all public posts, newest first, paged (not only the first 10 or 20). Replies to other people are
  left out by default and can be turned on.
- **Search:** keywords and #hashtags, `top` or `recent`, and every row keeps the keyword that found it.
- **Post links:** any `threads.com/@user/post/CODE` (threads.net links work too).
- **Engagement as numbers:** likes, replies, reposts and quotes on every post.
- **30 fields per row**, listed in the [field reference](#field-reference).
- **`onlyNew` for schedules:** a daily run delivers, and charges, only the posts published since the last run.

### What you can do with it

- **Brand and competitor monitoring:** every post of the accounts you follow, on a schedule, with engagement.
- **Trend and topic research:** the newest posts for a keyword or hashtag with `searchSort: recent`.
- **Influencer analysis:** posting frequency, media mix and engagement per post for any public profile.
- **Content research:** which formats (text, image, video, carousel) get the most replies and reposts.
- **Datasets for AI and social listening:** clean text with hashtags, mentions and links, ready for sentiment
  analysis or an LLM prompt.

### Input

Two profiles, one hashtag sorted by recent, up to 200 posts each:

```json
{ "usernames": ["nasa", "meta"], "searchQueries": ["#worldcup"], "searchSort": "recent", "maxItems": 200 }
```

Two specific posts by link:

```json
{ "postUrls": ["https://www.threads.com/@zuck/post/Dd1MqfcG0aH", "https://www.threads.net/@zuck/post/DeZtp-TkQHh"] }
```

A profile's own posts plus its replies under other people's posts:

```json
{ "usernames": ["zuck"], "excludeReplies": false, "maxItems": 100 }
```

| Field | What it does |
|---|---|
| `usernames` | Usernames or profile links (`zuck`, `@nasa`, `https://www.threads.com/@meta`). Also `profiles`, `profileUrls` |
| `searchQueries` | Keywords or #hashtags. Also `keywords`, `queries` |
| `searchSort` | `top` (default) or `recent` |
| `postUrls` | Post links. Also `urls`, `startUrls` |
| `maxItems` | Max posts per profile or keyword (default 50). Also `maxPostsPerSource` |
| `excludeReplies` | Keep only the profile's own posts (default on) |
| `onlyNew` | Only posts not delivered in earlier runs (default off), for schedules |
| `proxyConfiguration` | Apify datacenter proxy by default, which Threads accepts |

An empty input runs an example profile, so you can see the output first.

### Output

One real row, profile `zuck`, collected on 2026-10-15 (image link shortened):

```json
{
  "type": "post",
  "id": "4006434140014576097",
  "code": "DeZtp-TkQHh",
  "url": "https://www.threads.com/@zuck/post/DeZtp-TkQHh",
  "text": "Introducing Muse Wonder, our new family of frontier models with state of the art performance for personal and professional agentic work.",
  "publishedAt": "2026-10-12T16:56:29Z",
  "likeCount": 1966,
  "replyCount": 329,
  "repostCount": 154,
  "quoteCount": 56,
  "isReply": false,
  "replyToUsername": null,
  "isRepost": false,
  "imageUrls": ["https://scontent-xxc1-1.cdninstagram.com/v/t51.82787-15/...webp"],
  "videoUrls": [],
  "mediaType": 1,
  "hashtags": [],
  "mentions": [],
  "links": [],
  "authorUsername": "zuck",
  "authorName": "Mark Zuckerberg",
  "authorIsVerified": true,
  "authorUrl": "https://www.threads.com/@zuck",
  "source": "profile:zuck",
  "scrapedAt": "2026-10-15T18:17:32Z",
  "errorCode": null
}
```

In a sample of 242 posts from our last 27 runs, 64% were text only, 14% images, 13% carousels and 9% videos;
26% had a link and 10% mentioned another account.

<a id="field-reference"></a>

### Field reference

| Field | What it is |
|---|---|
| `type` | `post`, or `error` for a free error row |
| `id`, `code`, `url` | Threads post id, short code and link |
| `text` | Full text of the post |
| `publishedAt` | Publication date and time, ISO 8601 in UTC |
| `likeCount`, `replyCount`, `repostCount`, `quoteCount` | Engagement numbers |
| `isReply`, `replyToUsername` | The post is a reply, and to whom |
| `isRepost` | The post is a repost of another post |
| `quotedPostCode` | Code of the quoted post, when Threads sends it |
| `imageUrls` | Up to 10 image links (every image of a carousel) |
| `videoUrls` | Up to 5 video links |
| `mediaType` | Threads media code: `19` text only, `1` image, `2` video, `8` carousel |
| `hashtags` | Hashtags in the text, without `#` |
| `mentions` | Usernames mentioned in the text |
| `links` | Links in the text |
| `language` | Language code, when Threads sends it (usually empty for logged-out pages) |
| `authorUsername`, `authorName`, `authorUrl` | Who posted it |
| `authorIsVerified` | Verified badge |
| `authorFollowers` | Follower count, when Threads sends it (usually empty for logged-out pages) |
| `source` | What produced the row: `profile:<user>`, `search:<keyword>` or the post link |
| `scrapedAt` | When the row was collected |
| `error`, `errorCode` | Empty on a post; filled on a free error row |

#### Error rows (never charged)

| errorCode | Meaning |
|---|---|
| `PROFILE_NOT_FOUND` | No public profile with this username |
| `POST_NOT_FOUND` | The post was deleted or is not public |
| `INVALID_URL` | Not a Threads post link |
| `NO_RESULTS` | Nothing public for this input |
| `BLOCKED` | Threads did not answer after retries; run again |
| `NOT_REACHED` | The run timeout arrived before this input |
| `UNEXPECTED` | Something unforeseen broke; only that input is lost |

### Schedule it daily: only new posts

Turn on `onlyNew`, save the input as a Task and attach a Schedule. The Actor remembers which posts of each profile
and keyword it already delivered, in a Key-Value Store named `threads-scraper-only-new` in your own Apify account,
so every run delivers, and charges, only the posts published since the last one. Profiles stop paging at the first
post you already have, so a quiet day is one request and costs nothing for results; the run ends green with the
status "No new posts since the last run". Delete the store to start over.

```json
{ "usernames": ["nasa"], "searchQueries": ["#worldcup"], "searchSort": "recent", "maxItems": 50, "onlyNew": true }
```

### Integrations, scheduling and AI agents

- **Schedule** the input as a Task in [Apify schedules](https://docs.apify.com/platform/schedules), with `onlyNew`
  on, and each run bills only new posts.
- **Export** as JSON, CSV, Excel, XML or HTML, or read the dataset from the [Apify API](https://docs.apify.com/api/v2).
- **Connect** it to Make, n8n, Zapier, Google Sheets, Slack or a webhook through
  [Apify integrations](https://docs.apify.com/platform/integrations), so new posts land where your team reads them.
- **AI agents:** the Actor works as a tool through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp)
  in Claude, ChatGPT, Cursor and other MCP clients, for example "get the last 50 posts of these three brands on
  Threads and compare their engagement".
- **API call:** `scrapewise/threads-scraper` with the Apify API or the Python and JavaScript clients.

### FAQ

**Do I need a Threads or Instagram account?**
No. The Actor reads public pages logged out, with no cookies.

**How many posts can I get from a profile?**
All public posts, newest first, up to `maxItems` per profile. Raise `maxItems` for a full history.

**How many posts does a keyword search return?**
What Threads shows logged-out visitors, about 25 to 35 posts per keyword. Use several keywords, or schedule a
`recent` search often with `onlyNew` and the dataset grows every run.

**How much does it cost?**
500 posts of a profile cost US$ 2.50 on the Free plan and US$ 2.13 on Gold. Error rows and duplicates are free.

**Can I download the images and videos?**
Yes, from `imageUrls` and `videoUrls`. The links are signed by Meta and expire, so download them within a few hours.

### Limitations

- Search returns what Threads shows logged-out visitors, about 25 to 35 posts per keyword.
- Follower counts and language are filled only when Threads sends them on public pages, which is rare.
- Media links are signed by Meta; download files within a few hours.
- This Actor reads public posts only. Independent tool, not affiliated with Meta.

### Changelog

- **16 Oct 2026:** price per plan (US$ 5.00 Free down to US$ 4.25 Gold and above), field reference with the media
  codes, more input examples and an integrations section on this page.
- **2026-10-04:** `onlyNew` option for scheduled runs: posts delivered in earlier runs are skipped, not charged and
  not counted in `maxItems`.
- **2026-09-30, 0.1:** first release. Profile posts with pagination, keyword and hashtag search (top or recent),
  post links, free error rows.

# Actor input Schema

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

Threads usernames or profile links, one per line (for example zuck, @nasa or https://www.threads.com/@meta). Returns the profile's public posts, newest first, page after page, with text, date, likes, replies, reposts, quotes and media. Leave every list empty to run the example profile. Also accepts 'profiles' or 'profileUrls'.

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

Keywords or #hashtags, one per line (for example ai agents or #photography). Each returns the posts Threads shows for it, about 25 to 35 per keyword, in the order chosen below. Every row keeps its keyword. Also accepts 'keywords' or 'queries'.

## `searchSort` (type: `string`):

Order of keyword search results: Top (default, the posts Threads ranks highest) or Recent (newest first, the right choice for monitoring a topic). Used only with Search keywords.

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

Specific Threads posts, one per line, as threads.com/@user/post/CODE links (threads.net links work too). Each link returns that single post. Also accepts 'urls' or 'startUrls'.

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

Upper limit of posts for each profile or keyword (default 50). With 3 profiles and 50 here a run delivers up to 150 posts. You pay per post delivered. Also accepts 'maxPostsPerSource'.

## `excludeReplies` (type: `boolean`):

On (default): keeps only the profile's own posts, not the replies it wrote under other people's posts. Turn off to also get its replies. Used only with Profiles.

## `onlyNew` (type: `boolean`):

For scheduled Tasks. Remembers which posts of each profile, keyword and post list were already delivered (in a named key-value store in your account, 'threads-scraper-only-new') and skips them on later runs: not delivered, not charged and not counted in Max posts. Profiles stop paging at the first post you already have. Delete that store to start over. Also accepts 'onlyNewPosts'.

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

Apify Proxy, on by default with the datacenter group, which Threads accepts. Keep the default unless you have your own proxy.

## Actor input object example

```json
{
  "usernames": [
    "zuck"
  ],
  "searchSort": "top",
  "maxItems": 50,
  "excludeReplies": true,
  "onlyNew": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `resultsCsv` (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"
    ],
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/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"],
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/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"
  ],
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapewise/threads-scraper --silent --output-dataset

```

## MCP server setup

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