# Threads Scraper: Posts, Replies, Profiles & Search (`deepmine/threads-scraper`) Actor

Meta Threads scraper and Threads API for public data: search posts by keyword or hashtag (often hundreds per term) or find accounts, and scrape profiles, posts, replies and reposts by username or post URL. Likes, views, shares, media, links, followers and Instagram counts. No login.

- **URL**: https://apify.com/deepmine/threads-scraper.md
- **Developed by:** [DeepMine](https://apify.com/deepmine) (community)
- **Categories:** Social media, Lead generation
- **Features:** Limited permissions
- **Stats:** 19 total users, 12 monthly users, 99.9% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.89 / 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?

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: Posts, Replies, Profiles & Search

Threads scraper for Meta Threads, no login: type a keyword, a username or a post link and get posts, replies, profiles and view counts as a table.

| User | Post | Likes | Replies | Views | Author followers | Posted |
|---|---|---|---|---|---|---|
| [mosseri](https://www.threads.com/@mosseri/post/De2ynmxDcS-) | I was so excited when Emily Bode agreed to design… | 549 | 99 | 29,044 | 1,052,343 | 2026-10-23 |
| [mosseri](https://www.threads.com/@mosseri/post/Dez_7aUkoDQ) | Every major platform has had to lean into recommen… | 272 | 364 | 42,126 | 1,052,343 | 2026-10-22 |
| [mosseri](https://www.threads.com/@mosseri/post/DeZvGAMmu4D) | Big day for the Muse team with the introduction of… | 1,115 | 1,054 | 617,444 | 1,052,343 | 2026-10-12 |

<sub>Collected 2026-10-26 with this Actor's prefilled run (@mosseri: his profile and 80 posts). $1.59 per 1,000 results on the Free plan, $1.29 on Starter, $1.09 on Scale and $0.89 on Business, with no start fee. The prefilled run (81 results) costs about $0.10 on Starter.</sub>

### What you can scrape

| Input | You get |
|---|---|
| **🔍 Search terms** (`coffee`, `#booktok`, a Threads search or tag URL) | Posts that mention the term, Top or Recent: often a few hundred per term (see [Search depth](#search-depth)). Or, with **Search for: Accounts**, up to 100 **accounts** per term with followers, bio and links |
| **👤 Usernames** (`mosseri`, `@mosseri`, a profile URL) | The profile, the account's posts (paged to the end), its replies to others (each with the post it answers) and its reposts |
| **🔗 Post URLs** (`threads.com/@user/post/...`, `threads.com/t/...`) | Its replies and the replies to those (3 levels), Top or Recent, each with its **view count**; then the post itself with its views and how many replies were collected |

Mix them in one run. A post or profile that several inputs find is in your dataset, and charged, once. Plain HTTPS
on Apify datacenter IPs, no browser: first rows in seconds, and a run needs only 256 MB.

Use it to track a brand or topic on Threads, collect posts for research or AI training, find creators and their
contacts for outreach, or monitor an account's posts and replies on a schedule.

### Search depth

Each search page Threads serves logged-out visitors holds 13-20 posts and offers no next page (checked 2026-10-03 and
again 2026-10-26). This Actor reads the term through every page Threads offers (its default and top lists, the
hashtag, the singular or plural form, and up to 8 related topic tags). When those run out before your **Max results per input**, **Search deeper** (on by default) reads the newest
posts of the authors it found and of the accounts Threads' account search ranks for the term, and keeps only posts
whose own text, topic or hashtags contain your words. Each row says where it came from (`searchSource`:
`default`, `tag:coffeelover`, `author:runcoachmike`, `account:unwind_ai`, ...).

| Search term | Threads' search and tag pages | With Search deeper |
|---|---|---|
| coffee | 155 | 363 |
| skincare | 124 | 506 |
| real estate | 99 | 391 |
| marathon training | 40 | 160-204 |
| ai agents | 28 | 136-149 |

<sub>Posts that mention the term, per term, measured 2026-10-03 (T-0560 probes and runs on Apify datacenter IPs).
Counts change with what people post.</sub>

Turn off **Only posts that mention the search term** to also keep the loosely related posts Threads' search shows,
or **Search deeper** to get Threads' search pages only. Account searches return up to 100 accounts per term.

More search options (🔍 Search options):

- **Only posts by these accounts**: usernames; the search then reads those accounts' own posts (newest first, up to
  500 each) and keeps the ones that mention your term (`searchSource` `author:<user>`).
- **Search pages**: All (the most posts), or only Threads' Top, Recent or Tags pages.
- **Preferred language**: asks Threads for results in that language first, as a visitor's browser would (a
  preference, not a filter). In a 2026-10-26 check, "coffee" in Japanese gave 11-14 Japanese posts of 20, in
  English none.
- **Include replies found by the search** (on): off keeps posts only.
- **⏭️ Skip posts already in this dataset** (🎛️ Filters): an earlier run's dataset ID. Its posts and profiles are
  skipped and not charged: continue where a run stopped, or schedule a search and get only new posts.

A profile's posts and replies page to the end of what Threads lists. A post's replies page through every reply
Threads lists for logged-out visitors, which is often only part of them (`isPublicSubset` on the post's own row).
Reposts: Threads' reposts tab answered at most the latest 25, with no next page, when tested (2026-10-03).

### Output

The Output tab has three tables:

- **📊 All results**: every post and profile, with Overview (posts: text, likes, replies, views, author followers),
  Stats and Profile rows views.
- **🧵 Posts and replies**: posts only, with Posts, Media, Replies and Views and authors views.
- **👤 Profiles**: profiles only, with Profiles and Contacts (accounts search) views.

The run summary (`OUTPUT`) lists every input with its status, result count and why it stopped. Every field has a
label and a description in the dataset schema; the full list:

**Posts and replies** (one flat row each):

- who: `profilePicUrl`, `username`, `fullName`, `isVerified`
- what: `text` (the whole post; long posts include their full body, also in `attachmentText`), `textSnippet`,
  `url`
- engagement: `likeCount`, `replyCount`, `repostCount`, `quoteCount`, `shareCount` (Threads hides many zero
  counts; those come back empty), `viewCount` and `viewCountStatus` (see below); `createdAt`
- media: `mediaType` (Text, Image, Video, Carousel, Link, GIF), `thumbnailUrl`, `mediaUrl`, `images`, `videos`,
  `mediaUrls` and `mediaUrlTypes` (every image and video in the post's order, with its type), `hasMedia`,
  `mediaCount`, `carouselCount`, `mediaWidth`, `mediaHeight`, `hasAudio`, `isGif`, `isSpoiler`,
  `accessibilityCaption`, inline stickers (`isStickerPost`, `stickerCount`, `stickerIds`, `stickerUrls`)
- `topicTag`, `hashtags`, `mentions`, `links` (real URLs, not Threads' redirect links), `emails`, link preview
  (`linkPreviewUrl`, `linkPreviewTitle`, `linkPreviewDescription`, `linkPreviewImageUrl`, `linkPreviewDisplayUrl`)
- replies: `isReply`, `replyToUsername`, `rootPostUsername`, `selfThreadCount`, `parentPostId`, `parentPostUrl`,
  `parentPostCode`, `parentPostText`, `parentPostUsername`, `parentPostUserId`, `parentPostLikeCount`,
  `parentPostReplyCount`, `parentPostRepostCount`, `parentPostQuoteCount`, `parentPostShareCount`,
  `parentPostCreatedAt`, `parentPostAvailable`, `rootPostId`, `replyDepth` (1 = a direct reply, 2 = a reply to a
  reply, ...)
- an account's own threads (posts tab): `threadPosition` (1 = the first post of the thread) and
  `threadFirstPostCode`
- quotes: `isQuotePost`, `quotedPostUrl`, `quotedPostText`, `quotedPostUsername`, `quotedPostCreatedAt`,
  `quotedPostUnavailable` (Threads marked the quoted post unavailable instead of sending it)
- reposts: `isRepost`, `repostedByUsername`, `repostedAt`, `repostedFromUsername`, `repostedPostUrl`, `repostCode`
  (a repost row is the original post, with who reposted it)
- `isPinned`, `isEdited`, `isPaidPartnership`, `isLikedByAuthor`, `isAiGenerated` (empty when the post carries no
  AI-detection data), `replyControl`, poll (`pollOptions`, `pollVoteCounts`, `pollTotalVotes`), `musicTitle`,
  `musicArtist`, `musicAssetId`, `podcastEpisode`, `podcastUrl`, `locationName`, `taggedUsers`, `language`
- author (on by default, one lookup per author per run): `authorFollowerCount`, `authorBio`,
  `authorProfilePicHdUrl`, `authorProfileTags`, `authorInstagramFollowerCount`, `authorBioLinks`, `authorEmails`
  and `authorPhones` (from the author's bio and links), `authorFediverseEnabled`, `authorProfileUrl`
- also: `imageCount`, `gifUrl`, `gifDescription`, `canReply`, `areCountsHidden`, `transparencyLabel`
- ids: `postId`, `code`, `timestamp`, `userId`, `isPrivateAuthor`, `mentionedUserIds`, `topicTagId`,
  `replyToUserId`, `quotedPostId`, `quotedPostCode`, `repostedByUserId`, `locationId`
- where it came from: `inputType`, `input`, `searchQuery`, `searchSource`, `keywordMatch`,
  `matchedSearchQueries` (every search term of the run the post mentions), `sourceTab`; `scrapedAt` last

**Profiles**: `profilePicUrl`, `username`, `fullName`, `bio`, `bioSnippet`, `url`, `followerCount`,
`instagramFollowerCount`, `instagramFollowingCount` (the linked Instagram account), `isVerified`, `isPrivate`,
`profileTags` (the topics the account shows), `bioLinks`, `emails` and `phones` found in the bio and links,
`profilePicHdUrl`, `hasThreadsBadge`, `isThreadsOnlyUser` (no linked Instagram), `transparencyLabel`,
`fediverseEnabled` (the account shares its posts to the fediverse), `latestPosts` (its 10 newest posts, each with
text, counts, date and link plus its media, links, hashtags, mentions, topic, flags, music and poll), `userId`,
`inputType`, `input`, `searchQuery`, `scrapedAt`.

Times are UTC, like `2026-10-03T14:05:09Z`. Picture and media links are signed by Threads and stop working after
a few days: download what you need to keep.

### View counts

Threads sends a post's view count with the post's own page. **👁️ View counts on every post** is on by default
(🧾 Output section): the Actor reads those pages in parallel and each row goes out as soon as it's ready, so the
first row isn't held back. Post URLs always ask for theirs, and so do their replies (**View counts on replies
too**, on by default). Threads doesn't show a count on every post: in the 2026-10-26 prefilled runs of this
family, 80 of 80, 10 of 10, 90 of 92 and 80 of 90 post rows had one. `viewCountStatus` says why one is empty:
the author hid the counts, the post's page showed none, the page didn't answer, or view counts were off.
**👤 Author details on every post** (on) adds the author's followers, bio, HD photo, topics, Instagram followers and
bio links, looked up once per author. Turn either off for faster big runs; the price stays the same.

**Recent** search sends each search page as it arrives, newest first (the first one at once), so the order is
newest first within each batch. **Recent, strict** waits for every page and sorts all of them, so its first row
comes later.

### Speed and reliability

Apify runs of this Actor, default 256 MB, all SUCCEEDED with results = charged results:

| Run | Results | First result | Whole run | Peak memory |
|---|---|---|---|---|
| Prefilled run (@mosseri's profile and 80 posts; 4 runs, 2026-10-26) | 81 | 1.6-1.9 s after the container started | 35-50 s | 107-111 MB |
| One profile's posts (@cnn, 1,000; 2026-10-03) | 1,001 | 4 s | 64 s | 64 MB |
| One post's replies and replies to replies (500; 2026-10-03) | 501 | 6 s | 44 s | 78 MB |
| 10 search terms, 15 posts each (2026-10-03) | 150 | 7 s | 52 s | 111 MB |

Bigger runs, same code through Apify datacenter IPs: 2,000 posts of @cnn in 128 s, 1,000 replies in 96 s, 10 search
terms × 100 posts in 161 s. Inputs are read one after another, so a run's time grows with the number of inputs.

A refused request is retried on a new IP. If Threads answers with a page that looks empty but isn't a real answer,
the run checks a known-good search or profile: if that comes back empty too, the input is reported as refused (and
nothing is charged) instead of "no results". If every input fails, the run fails with a clear message. A run that
Apify restarts never charges a result twice.

### Dates

**Posted after** and **Posted before** take a date (`2026-09-01`) or a period (`7 days`). Posts outside the window
are skipped and not charged. Threads' search pages ignored the date parameters we tried logged out (2026-10-26), so
the window applies to what the inputs return.

### Pricing

Pay per result: **$1.59 per 1,000 on Free, $1.29 on Starter, $1.09 on Scale and $0.89 on Business**. No start fee. Only
results in your dataset are charged; filtered posts and repeats are free. Set a maximum cost per run in the run
options and the run stops exactly there.

### FAQ

**Do I need a Threads or Instagram account?** No. Everything comes from what Threads shows logged-out visitors.

**Is there a Threads API?** Meta's official Threads API only reads your own account. This Actor works like a Threads
API for public data: call it from the Apify API, a schedule or an integration and get JSON, CSV or Excel.

**Private accounts?** When Threads marks an account private, you get its profile row and no posts; the run summary
says so.

**Followers or following lists?** Not offered: the follower and following pages and their API routes answered 404
or 401 to logged-out visitors when we checked (2026-10-26). You get the follower count, plus the linked
Instagram's follower and following counts.

**Which proxy?** Keep the default. Residential is used only as a fallback when Threads refuses datacenter IPs, at no
extra cost to you.

### Related Actors

- [Threads Search Scraper](https://apify.com/deepmine/threads-search-scraper): posts or accounts by keyword or hashtag.
- [Threads Profile Scraper](https://apify.com/deepmine/threads-profile-scraper): followers, bio, links and the linked Instagram's counts.
- [Threads Posts Scraper](https://apify.com/deepmine/threads-posts-scraper): every post of an account, or posts by URL with views.
- [Threads Replies Scraper](https://apify.com/deepmine/threads-replies-scraper): the public replies under a post, 3 levels deep.

### Feedback

Missing a field or an input type? Open an issue on the Actor's page; we answer quickly. If the data helped you, a
short review on the Store page helps others find it, and helps us a lot.

# Actor input Schema

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

Accounts, one per line: mosseri, @mosseri or threads.com/@mosseri. You get the profile and its posts; pick replies or reposts under 👤 Profile options. Empty = none.

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

Words or hashtags, one per line, e.g. coffee or #booktok. A Threads search or tag URL works too. Empty = no search.

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

Posts that mention the term, or accounts (up to 100 per term, each with followers, bio and links).

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

Post links, one per line (threads.com/@user/post/... or threads.com/t/...). You get the post with its view count, then its replies. Empty = none.

## `maxItemsPerInput` (type: `integer`):

Most results per search term, per profile tab and per post's replies. A search term gives up to a few hundred posts (see Search depth in the README).

## `sort` (type: `string`):

For search results and replies. Recent sends each batch newest first as it arrives (first rows in seconds); Recent, strict gathers more first and sorts everything.

## `onlyMatchingPosts` (type: `boolean`):

Threads also shows loosely related posts. On: keep only posts whose text, topic, hashtags or author name contain your words. Posts left out are not charged.

## `deepSearch` (type: `boolean`):

When Threads' search pages run out before your max, also read the newest posts of the authors found and of accounts matching the term, keeping posts that mention it. Off: Threads' search pages only.

## `searchFromUsernames` (type: `array`):

Optional. Usernames, one per line: the search then reads these accounts' own posts (newest first, up to 500 each) and keeps the ones that mention your term, instead of Threads' search pages. Empty = posts by anyone.

## `searchTab` (type: `string`):

All reads every Threads search page for the term (Top, Recent, #tag, related tags) and, with Search deeper, the authors' and matching accounts' posts. Top, Recent or Tags reads only that part (fewer posts, ~20 per page).

## `searchLanguage` (type: `string`):

Ask Threads for search results in this language first (the language a visitor's browser would ask for). A preference, not a filter: posts in other languages can still come. Threads' default favours English.

## `includeSearchReplies` (type: `boolean`):

Threads' search also shows replies to other posts (isReply = true). Off: posts only; replies left out are not charged.

## `profileContent` (type: `array`):

Any mix of the profile, its posts, its replies to others (each with the post it answers) and its reposts (Threads shows the latest 25).

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

Add each linked post's replies after the post, up to 📊 Max results per input.

## `includeNestedReplies` (type: `boolean`):

Under each reply, add the replies to it, up to 3 levels deep. Each row has replyDepth and parentPostId to rebuild the tree.

## `postedAfter` (type: `string`):

A date (2026-09-01) or a period (7 days, 12 hours). Empty = any time. Posts outside the window are not charged.

## `postedBefore` (type: `string`):

A date (2026-09-30) or a period. Empty = up to now.

## `resumeFromDatasetId` (type: `string`):

Optional. The dataset ID of an earlier run (its Storage tab): posts and profiles already there are skipped and not charged. Use it to continue where a run stopped, or on a schedule to get only new posts.

## `includeViewCounts` (type: `boolean`):

On: every search and profile post gets its view count (viewCount), read in parallel from the post's own page; rows still stream as they're ready. Post URLs always get theirs. Same price.

## `includeAuthorDetails` (type: `boolean`):

Add the author's followers, bio, HD photo, topics, Instagram followers and bio links to every post row (looked up once per author). Same price.

## `includeReplyViewCounts` (type: `boolean`):

Read each reply's view count (viewCount): one more page per reply, read alongside the rows so the first row doesn't wait. Turn off for the fastest big reply runs. Same price.

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

Leave as is. The Actor starts on Apify datacenter IPs, which Threads serves, and moves a request to residential only if Threads refuses. Same price either way.

## Actor input object example

```json
{
  "usernames": [
    "mosseri"
  ],
  "searchType": "posts",
  "maxItemsPerInput": 80,
  "sort": "top",
  "onlyMatchingPosts": true,
  "deepSearch": true,
  "searchTab": "all",
  "searchLanguage": "any",
  "includeSearchReplies": true,
  "profileContent": [
    "profile",
    "posts"
  ],
  "includeReplies": true,
  "includeNestedReplies": true,
  "includeViewCounts": true,
  "includeAuthorDetails": true,
  "includeReplyViewCounts": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `posts` (type: `string`):

No description

## `profiles` (type: `string`):

No description

## `summary` (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": [
        "mosseri"
    ],
    "maxItemsPerInput": 80
};

// Run the Actor and wait for it to finish
const run = await client.actor("deepmine/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": ["mosseri"],
    "maxItemsPerInput": 80,
}

# Run the Actor and wait for it to finish
run = client.actor("deepmine/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": [
    "mosseri"
  ],
  "maxItemsPerInput": 80
}' |
apify call deepmine/threads-scraper --silent --output-dataset

```

## MCP server setup

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