# Threads Scraper — Posts, Replies & Profiles, No Login (`vnx0/threads-scraper-no-login`) Actor

Threads scraper without login: extract public posts, profiles, replies, search and hashtags with engagement data via API. Try free.

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

## Pricing

$9.00 / 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?

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

Scrape public Threads.com data without login, cookies, or API keys: profiles, user posts, replies tabs, single-post threads, keyword search, and hashtag feeds. This **Threads scraper** returns one flat row per post with real like, reply, repost, and **quote counts**, plus a profile row when you want it.

Threads only shows logged-out visitors a window of recent content (about 10 profile posts, about 29 items per post thread, one page per search or hashtag — checked 2026-09-10). This Actor keeps every visible row, tells you when the login wall cut a run short, and never bills you for rows date filters removed or for an all-empty run.

### What you can scrape

- **Profiles** — username, full name, bio, profile picture, verified flag, follower count, bio-link website, post URL. (`followingCount` stays null for guests — Threads does not serve it logged-out.)
- **User posts** (`mode: posts`) — recent posts per username, newest first.
- **Author replies** (`mode: replies`) — the profile Replies tab, not just top-level posts.
- **Post threads** — any `postUrls` entry returns the post plus its reply thread; `replySort: top` puts the best-liked replies first.
- **Keyword search** — `searchQueries` with `searchSortType: top | recent`.
- **Hashtag feeds** — `hashtags` with or without `#`.
- **Media and context** — photo/video/carousel URLs with dimensions, `mediaType`, `hasAudio` for video, hashtags, mentions, external `urls`, link-preview URL, repost and quote lineage (`repostedFrom`, `quotedPostAuthor`, `parentPostId`, `rootPostId`), `scrapedFromMode`, and `searchQuery` on search rows.

### Threads profile scraper

Pass handles, `@handles`, or profile URLs in `usernames`:

```json
{ "usernames": ["zuck", "@mosseri", "https://www.threads.com/@creators"], "mode": "posts", "includeProfile": true, "maxPostsPerProfile": 10 }
```

`mode` applies to `usernames`: `posts` (default), `replies`, or `profile` (metadata only). `includeProfile: true` adds one profile row per username alongside posts. `maxPostsPerProfile: 0` means no per-profile cap (global `maxItems` still applies).

### Scrape Threads posts

Each post row carries 41 fields (about 29 on a typical row — conditional repost, quote, and reply fields are omitted when they do not apply unless you set `compactOutput: false`):

| Group | Fields |
|---|---|
| Identity | `type, postId, code, url, username, userId, userFullName, userIsVerified` |
| Content | `text, publishedAt, takenAtTimestamp, isEdited, isReply, replyToAuthor, hashtags, mentions, urls` |
| Engagement | `likeCount, replyCount, repostCount, quoteCount, reshareCount` |
| Repost / quote | `isRepost, repostedFrom, repostedPostId, repostedPostUrl, isQuotePost, quotedPostId, quotedPostUrl, quotedPostAuthor` |
| Thread | `parentPostId, rootPostId` |
| Media | `mediaType, mediaCount, mediaUrls, media[{type,url,width,height}], hasAudio, linkPreviewUrl` |
| Source | `scrapedFromMode, searchQuery, scrapedAt` |

Profile rows carry `type, username, userId, fullName, biography, profilePicUrl, profileUrl, isVerified, followerCount, followingCount, website, isPrivate`.

### Post threads and top replies

```json
{ "postUrls": ["https://www.threads.com/@zuck/post/DdCYWl7GktV"], "includeReplies": true, "replySort": "top", "maxRepliesPerPost": 50 }
```

- `includeReplies: false` returns exactly one row for the post URL.
- `replySort: top` (default) keeps the root post first and ranks replies by likes; `recent` keeps page order.
- `maxRepliesPerPost` caps expansion per URL; `maxItems` caps the whole run.

### Threads search scraper

```json
{ "searchQueries": ["climate change", "ai agents"], "searchSortType": "top", "postedAfter": "2026-01-01", "maxItems": 100 }
```

Search returns the public results page (single page per query — Threads-side limit). `postedAfter` / `postedBefore` (`YYYY-MM-DD` or ISO) drop rows **before** billing, so filtered-out rows cost nothing.

### Threads hashtag scraper

```json
{ "hashtags": ["coffee", "#travel"], "maxItems": 100 }
```

Same single-page window as search. The `#` prefix is optional; output rows carry `searchQuery: "#coffee"` so mixed runs stay attributable.

### Output fields and export

Every run writes flat rows to the default dataset (JSON, CSV, Excel, XML in the Console) and a `RUN_SUMMARY` object to the key-value store with per-target outcomes, date-excluded counts, and error reasons. An all-empty run **fails with the summary** instead of billing green — check `RUN_SUMMARY.targetsEmpty` before retrying.

```json
{
  "type": "post",
  "postId": "3981852126213720917",
  "code": "DdCYWl7GktV",
  "url": "https://www.threads.com/@zuck/post/DdCYWl7GktV",
  "username": "zuck",
  "text": "Post text here",
  "publishedAt": "2026-09-01T12:00:00.000Z",
  "likeCount": 4969,
  "replyCount": 1034,
  "repostCount": 372,
  "quoteCount": 277,
  "mediaType": "text",
  "hashtags": [],
  "mentions": [],
  "scrapedFromMode": "posts",
  "scrapedAt": "2026-09-10T00:00:00.000Z"
}
```

### Pricing

Pay-per-result: one billable event per dataset row (post or profile). Date-excluded rows are never pushed and never billed. Set `maxTotalChargeUsd` (0 = no cap) to stop cleanly at a budget. Start small: one username with `maxPostsPerProfile: 5` shows the full schema for a few cents, then raise `maxItems` for bulk runs. The final per-1K price is listed on the Pricing tab.

### How to scrape Threads

1. Click **Try for free** and open the **Input** tab.
2. Add `usernames`, `postUrls`, `searchQueries`, or `hashtags` (combine them in one run).
3. Pick `mode` for usernames and set `maxItems` as your spend control.
4. Click **Start**, then open the **Dataset** tab to preview rows.
5. Export as JSON, CSV, or Excel, or call the API for pipelines.
6. Add an Apify **Schedule** for daily creator or keyword checks.

### Threads scraper API

JavaScript:

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('vnx0/threads-scraper-no-login').call({
  usernames: ['zuck'],
  mode: 'posts',
  includeProfile: true,
  maxPostsPerProfile: 10,
  maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Python:

```python
from apify_client import ApifyClient
client = ApifyClient(token="APIFY_TOKEN")
run = client.actor("vnx0/threads-scraper-no-login").call(
    run_input={"searchQueries": ["ai agents"], "maxItems": 50}
)
print(client.dataset(run["defaultDatasetId"]).list_items().items[:2])
```

Prefer no code: run from Console, schedule it, attach a webhook, or connect Make, Zapier, or n8n. AI agents can call it through the Apify MCP server.

### Use cases

- **Creator research** — compare recent posts, follower counts, and engagement across handles.
- **Brand and keyword monitoring** — schedule daily `searchQueries` runs and diff the dataset.
- **Hashtag tracking** — pull `#tag` feeds for campaigns or events.
- **Conversation analysis** — expand a post thread with top replies first for sentiment review.
- **Content research** — collect text, hashtags, mentions, and media URLs for analysis pipelines.
- **Competitor checks** — watch public posting cadence and repost/quote pickup.

This Actor does not do lead enrichment, email extraction, follower-list pulls, or new-post delta detection — schedule full runs and diff on `postId` instead.

### Limitations

| Limit | What happens |
|---|---|
| Logged-out window (~10 profile posts, ~29 thread items, 1 page search/hashtag) | Run keeps visible rows and notes truncation in logs |
| Private or login-gated accounts | Target reported empty in `RUN_SUMMARY`, skipped |
| View counts, follower/following lists, full history | Not served to guests — never promised, never null-filled silently |
| Media binaries | URLs only; CDN links expire — download promptly |
| Threads layout changes | Embedded-data extractor with DOM fallback; failures logged per target |

### FAQ

**Do I need a Threads or Instagram login, cookies, or API key?**
No. Only what Threads serves to logged-out visitors, over Apify Proxy by default.

**Is there an official Threads API? How is this different?**
Meta's official API covers your own content, publishing, and insights behind app review. This Actor reads public profiles, posts, search, and hashtags and returns them as rows you can export or call via API — no app review.

**Can I scrape private accounts?**
No. Public data only.

**Why did I get fewer rows than my max?**
The max is a ceiling, not a guarantee. Inactive profiles, niche queries, and the logged-out window return fewer rows. The run still succeeds if any target returned data.

**Do view counts come back?**
No. Threads does not expose them to guests.

**Do date filters save money?**
Yes. `postedAfter` / `postedBefore` exclusions happen before the dataset push, so excluded rows cost nothing.

**What if every target returns nothing?**
The run fails with a `RUN_SUMMARY` explaining which targets were empty and why, instead of a green billed run.

**threads.com or threads.net?**
Both URL forms are accepted as input; output URLs use the canonical `threads.com` form.

**How do I export to CSV or Excel?**
Run in Console, open Storage, download — or fetch `GET /v2/datasets/{id}/items?format=csv` with your token.

**Can AI agents use it?**
Yes — via the Apify API or MCP server with the same JSON input.

### Troubleshooting

- `No valid targets` — provide at least one of `usernames`, `postUrls`, `searchQueries`, `hashtags`.
- All-empty failure — read `RUN_SUMMARY.targetsEmpty` for per-target reasons (`not-found-404`, `no-rows-returned`); check handle spelling and try one known-public profile.
- Thin search results — split multi-word phrases into separate queries; try `recent` sort.
- Private account — expected empty; remove it from the list.
- Cost worries — set `maxPostsPerProfile: 5` + `maxTotalChargeUsd: 1` for a sample run first.
- Proxy errors — leave `proxy` on automatic routing unless you have a reason to change it.

### Legal and support

Reads public pages only; respects the logged-out window; no credential handling. Found a bug or Threads changed layout? Open an issue on the Actor page — reports with a failing input and `RUN_SUMMARY` get fixed first.

# Actor input Schema

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

Threads handles, @handles or profile URLs. Scraped per mode (posts / replies / profile). Leave empty if using post URLs, search or hashtags.

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

What to pull for each username: posts (recent posts), replies (profile Replies tab), or profile (metadata only).

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

Threads post URLs. Returns the post plus its visible reply thread unless includeReplies is false. Use replySort to rank replies by likes.

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

Keywords/phrases to search Threads public posts for. Single page of results per query (Threads-side limit). Try separate queries instead of one long phrase.

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

Hashtag feeds to pull, with or without the leading #. Single page per tag. Output rows carry searchQuery with # prefix.

## `searchSortType` (type: `string`):

Ranking for keyword searches: top (most relevant) or recent (newest first).

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

Keep only posts on or after this date (YYYY-MM-DD or ISO). Excluded rows are dropped before billing — they cost nothing.

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

Keep only posts on or before this date (YYYY-MM-DD or ISO). Excluded rows are dropped before billing — they cost nothing.

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

For post URLs: return the post plus every visible reply in its conversation. Turn off for exactly one row per post URL.

## `includeProfile` (type: `boolean`):

For username targets in posts/replies mode: also return one profile row (followers, bio, verified). Turn off for posts only.

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

Cap posts per username target (newest first). 0 = no per-profile cap (global maxItems still applies). Start with 5 to check output cheaply.

## `replySort` (type: `string`):

For post URLs: rank replies by likes (top, best comments first) or keep page order (recent).

## `compactOutput` (type: `boolean`):

Omit conditional fields (repost/quote/reply lineage, website, audio flag) when they don't apply, instead of returning nulls. Set false for the fixed full schema.

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

Max total rows across all targets (posts + profiles). Your spend control — raise for bulk runs.

## `maxRepliesPerPost` (type: `integer`):

Cap on replies expanded per post URL. Lower it to cut cost on big threads.

## `maxTotalChargeUsd` (type: `number`):

Stop cleanly once estimated charges reach this cap. 0 = no cap. Use with maxItems for budget safety.

## `proxy` (type: `object`):

Apify Proxy configuration. Leave on automatic routing unless you have a reason to change it.

## Actor input object example

```json
{
  "usernames": [],
  "mode": "posts",
  "postUrls": [],
  "searchQueries": [],
  "hashtags": [],
  "searchSortType": "top",
  "postedAfter": "",
  "postedBefore": "",
  "includeReplies": true,
  "includeProfile": true,
  "maxPostsPerProfile": 0,
  "replySort": "top",
  "compactOutput": true,
  "maxItems": 100,
  "maxRepliesPerPost": 100,
  "maxTotalChargeUsd": 0,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One flat row per Threads post or profile: text, engagement counts, media, hashtags, timestamps. Export as JSON, CSV, Excel or XML.

## `runSummary` (type: `string`):

Per-target outcomes, date-excluded counts and error reasons. Status is FAILED when every target came back empty.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("vnx0/threads-scraper-no-login").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("vnx0/threads-scraper-no-login").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 '{}' |
apify call vnx0/threads-scraper-no-login --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vnx0/threads-scraper-no-login"
        }
    }
}
```

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/UeBkNhSr56L5R14bB/builds/srRlyFauKwm1Q8omt/openapi.json
