# Threads Posts Scraper: A Profile's Whole Post History (`luzivanlt/threads-posts-scraper`) Actor

A Threads profile's whole post history, back to its very first post, newest first. $2 per 1,000 posts. Text, date, likes, replies, reposts, quotes, media. No account needed.

- **URL**: https://apify.com/luzivanlt/threads-posts-scraper.md
- **Developed by:** [Luzi](https://apify.com/luzivanlt) (community)
- **Categories:** Social media, Marketing, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 posts

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 Posts Scraper: A Profile's Whole Post History

Get every post a Threads profile has made, newest first, all the way back to
its first post: the text, the date, likes, replies, reposts, quotes, shares,
images, videos and links, with the profile's followers, bio and tags on every
row. Paste profile links or just usernames. No Threads or Instagram account
needed.

Tested daily. Latest checks: one profile's whole history, 192 posts back to
its first one; 723 posts from three profiles in under 4 minutes.

### What does this Actor do?

You give it Threads profiles. For each one it reads the profile's posts from
the newest back, about 4 threads at a time, and saves one row per post until
it reaches your limit, your date, or the profile's first post.

A thread on Threads can hold several posts: the first one and the author's
own follow-ups underneath it. Each of them is its own row, and rows of the
same thread share a `thread_id`.

Each post comes with:

- its text, link and date, and whether it was edited
- its likes, replies, reposts, quotes and shares
- whether it is text, an image, a video or a carousel, with the image and
  video links
- the link it shares, the links and accounts named in its text, the post it
  quotes, its topic tag and its song, when it has them
- who can reply to it, its AI label, and whether it is pinned, a spoiler or a
  ghost post
- where it sits in its thread
- the author's username, name, ids, picture and verified badge
- the profile's follower count, thread count, bio, tags and picture

### Why use it?

- **The whole history, not just the latest.** This Actor keeps going to a
  profile's very first post, or stops at your limit or your date.
- **Every follow-up in its place.** A thread's follow-ups are rows of their
  own, numbered in thread order, so long threads are not cut to their first
  post.
- **Track a brand, a creator or a competitor.** See what they post, how each
  post does, and how many followers they have.
- **Monitor new posts.** Run it daily with **Only posts newer than** set to
  `1 day`.
- **Use the data anywhere.** Download as JSON, CSV or Excel, or send it to
  your own tools through Apify's API and integrations.

### How to use it

1. Paste one or more profiles into **Profile links or usernames**:
   `https://www.threads.com/@nasa`, `threads.net/@nasa`, `@nasa` or `nasa` all
   work.
2. Optionally, set **Only posts newer than** and **Max posts per profile**.
3. Click **Start**. When the run ends, open the **Output** tab to view the
   posts or download them.

A link to a single post, a search or a tag page is not supported: paste the
profile's link or username instead. Put one profile on each line of the
list.

Run it with no input to see a sample: up to 20 posts from NASA's profile,
charged as usual.

### Input

| Field                                            | What it does                                                                                                  | Default |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | ------- |
| **Profile links or usernames** (`startUrls`)     | The profiles to read. Required.                                                                               | —       |
| **Only posts newer than** (`onlyPostsNewerThan`) | A date (`YYYY-MM-DD`, UTC) or a period (`7 days`, `2 weeks`, `3 months`, `1 year`). Empty = the whole history | empty   |
| **Max posts per profile** (`maxPostsPerProfile`) | Stop reading a profile after this many posts, from 1 to 10,000                                                | `100`   |
| **Only new posts** (`onlyNewItems`)              | Return only the posts an earlier run did not; see New items only below                                        | off     |

Example input:

```json
{
  "startUrls": ["https://www.threads.com/@nasa", "zuck"],
  "onlyPostsNewerThan": "30 days",
  "maxPostsPerProfile": 500
}
```

### New items only

Turn on **Only new posts** (`onlyNewItems`) for a scheduled run, or a re-run
of the same task. Each run then returns only the posts it has not returned
before: it reads each profile back to a day before the last run that read it,
and skips the posts an earlier run saved. Skipped posts are neither saved nor
charged; each new post is charged as usual.

- Runs with other settings, or from another task, keep their own list, so two
  schedules on one profile never skip each other's posts.
- If a profile stops at **Max posts per profile**, the posts past that point
  are not returned later. Set the maximum above what one profile gets between
  runs.
- The list lives in your Apify account, in a key-value store named
  `threads-posts-scraper-monitor`. Delete it to start afresh.

### Output

One row per post. An example, with made-up values:

```json
{
  "post_id": "3100000000000000001",
  "post_code": "DAbCdEfGhIj",
  "post_fbid": "17900000000000001",
  "url": "https://www.threads.com/@example.brand/post/DAbCdEfGhIj",
  "text": "Our new launch is live today. Read more: example.com/launch",
  "posted_at": "2026-10-13T18:28:06.000Z",
  "is_edited": false,
  "like_count": 4176,
  "reply_count": 17,
  "repost_count": 89,
  "quote_count": 11,
  "reshare_count": 51,
  "like_counts_hidden": false,
  "media_type": "carousel",
  "image_urls": ["https://…/1.jpg", "https://…/2.jpg"],
  "video_urls": [],
  "image_alt_texts": ["A product on a white table"],
  "media_width": 1080,
  "media_height": 1350,
  "has_audio": null,
  "link_url": "https://example.com/launch",
  "link_title": "Our launch",
  "link_image_url": "https://…/preview.jpg",
  "link_favicon_url": "https://…/favicon.png",
  "text_links": ["https://example.com/launch"],
  "mentioned_users": [
    { "username": "example.partner", "id": "70000000002", "profile_pic_url": "https://…/p.jpg" }
  ],
  "topic": "Product News",
  "topic_is_community": false,
  "music_title": null,
  "music_artist": null,
  "music_song_id": null,
  "music_audio_id": null,
  "reply_control": "everyone",
  "ai_detection_method": "NONE",
  "is_spoiler": false,
  "is_ghost_post": false,
  "reply_to_username": null,
  "reply_to_user_id": null,
  "author_username": "example.brand",
  "author_full_name": "Example Brand",
  "author_id": "70000000001",
  "author_fbid": "17800000000000001",
  "author_is_verified": true,
  "author_profile_pic_url": "https://…/avatar.jpg",
  "author_is_meta_ai_bot": false,
  "quoted_post_url": null,
  "quoted_post": null,
  "is_pinned": false,
  "is_pinned_in_thread": false,
  "thread_id": "3100000000000000001",
  "thread_position": 1,
  "profile_follower_count": 48210,
  "profile_thread_count": 312,
  "profile_biography": "Making things people like.",
  "profile_bio_links": [{ "url": "https://example.com", "title": null, "is_verified": false }],
  "profile_tags": ["Product News"],
  "profile_pic_hd_url": "https://…/avatar_640.jpg",
  "source_url": "https://www.threads.com/@example.brand"
}
```

| Field                         | What it holds                                                                                        |
| ----------------------------- | ---------------------------------------------------------------------------------------------------- |
| `post_id`                     | Threads' id for the post                                                                             |
| `post_code`                   | The short code in the post's link                                                                    |
| `post_fbid`                   | Meta's other id for the post                                                                         |
| `url`                         | The post's page                                                                                      |
| `text`                        | The post's text. `null` for a post with only media                                                   |
| `posted_at`                   | When it was posted (UTC, ISO 8601)                                                                   |
| `is_edited`                   | `true` when the author edited the text                                                               |
| `like_count`                  | Likes                                                                                                |
| `reply_count`                 | Direct replies                                                                                       |
| `repost_count`                | Reposts                                                                                              |
| `quote_count`                 | Quotes                                                                                               |
| `reshare_count`               | Shares (Threads leaves it out on some posts)                                                         |
| `like_counts_hidden`          | `true` when the author hid the post's like count                                                     |
| `media_type`                  | `text`, `image`, `video` or `carousel`                                                               |
| `image_urls`                  | The post's images (for a carousel, one per slide; a video's cover image too)                         |
| `video_urls`                  | The post's videos                                                                                    |
| `image_alt_texts`             | The image descriptions Threads gives the post's images, when it has them                             |
| `media_width`, `media_height` | The size of the post's image or video in pixels. `null` for a text post                              |
| `has_audio`                   | For a video, whether it has sound; `null` for a post with no video                                   |
| `link_url`                    | The web link the post shares, when it has one                                                        |
| `link_title`                  | The title of that link's preview card                                                                |
| `link_image_url`              | The image of that link's preview card                                                                |
| `link_favicon_url`            | The site icon on that link's preview card                                                            |
| `text_links`                  | Web links written in the post's text                                                                 |
| `mentioned_users`             | The accounts the text names: `username`, `id` and `profile_pic_url` for each                         |
| `topic`                       | The post's topic tag, when it has one                                                                |
| `topic_is_community`          | `true` when that topic is a Threads community                                                        |
| `music_title`, `music_artist` | The song on the post, when it has one                                                                |
| `music_song_id`               | Threads' id for that song                                                                            |
| `music_audio_id`              | Threads' id for that song's audio                                                                    |
| `reply_control`               | Who may reply, as Threads names it (for example `everyone`)                                          |
| `ai_detection_method`         | Threads' AI-content label for the post; `NONE` when it has none                                      |
| `is_spoiler`                  | `true` when the post's media is marked as a spoiler                                                  |
| `is_ghost_post`               | `true` for a ghost post (one set to disappear)                                                       |
| `reply_to_username`           | For a follow-up, the account it answers (usually the profile itself)                                 |
| `reply_to_user_id`            | That account's id                                                                                    |
| `author_username`             | The author's username                                                                                |
| `author_full_name`            | The author's display name                                                                            |
| `author_id`                   | Threads' id for the author                                                                           |
| `author_fbid`                 | Meta's other id for the author                                                                       |
| `author_is_verified`          | `true` when the author has the verified badge                                                        |
| `author_profile_pic_url`      | The author's profile picture                                                                         |
| `author_is_meta_ai_bot`       | `true` when the author is a Meta AI account                                                          |
| `quoted_post_url`             | The post it quotes, when it quotes one                                                               |
| `quoted_post`                 | That quoted post's own details (text, date, counts, media, author), in the same field names as a row |
| `is_pinned`                   | `true` when the author pinned it to their profile                                                    |
| `is_pinned_in_thread`         | `true` when the post is pinned under the post it answers                                             |
| `thread_id`                   | The thread it belongs to: the same for a post and its author's follow-ups                            |
| `thread_position`             | `1` for the thread's first post, `2`, `3`… for the author's follow-ups                               |
| `profile_follower_count`      | The profile's followers when it was read                                                             |
| `profile_thread_count`        | The thread count the profile shows (threads, not posts); `null` when Threads shows it rounded        |
| `profile_biography`           | The profile's bio                                                                                    |
| `profile_bio_links`           | The links on the profile: `url`, `title` and `is_verified` for each                                  |
| `profile_tags`                | The topic tags on the profile                                                                        |
| `profile_pic_hd_url`          | The profile picture at its largest size                                                              |
| `source_url`                  | The profile this post was read from                                                                  |

Not included: the replies other people wrote, the profile's reposts of other
people's posts, view counts, polls, and the lyrics of a post's song.

### How much does it cost?

No surcharges and no paid options; an item that fails is not charged.

You pay for what you get:

- **$2 per 1,000 posts** ($0.002 a post). Each post is charged once per run.
- No start fee, and nothing per profile.

So 300 posts from each of 2 profiles cost $1.20. If you set a maximum cost for a run, the Actor stops when it reaches it and keeps every post saved so far.

### How long does a run take?

About 4 threads every couple of seconds. A profile with 200 posts takes about
a minute or two.

### Good to know

- **Pinned posts come first.** A profile's pinned posts open its list
  whatever their date. With **Only posts newer than** set, an older pinned
  post is left out.
- **A profile's post count is in threads, not posts.** The "N Threads" on a
  profile (`profile_thread_count`) counts threads; with follow-ups, you get
  more rows than that number. The very end of a long history can come up a
  few threads short of it.
- **Check your input first.** A link that is not a Threads profile stops the
  run before anything is read, and the message names it.
- **One profile that cannot be read does not stop the run.** A profile that
  does not exist or is private ends with a message, the others carry on, and
  the run's status lists the profiles that could not be read. The run fails
  only when no profile could be read. Such a profile is tried a few times
  before it is given up, which can add two or three minutes to the run.
- **Counts move.** Likes, replies and followers are the numbers at the moment
  the post was read.
- **Remove repeats by `post_id`.** A post whose counts change while a run
  pages past it can appear twice in one run, and a daily run reads recent
  posts again unless **Only new posts** is on.

### More Actors from us

- [AliExpress Product Scraper: Search Results & Prices](https://apify.com/luzivanlt/aliexpress-products-scraper): Every product of an AliExpress search to its last page, with exact sold counts and ratings.
- [Amazon Product Scraper: Search Results & Prices](https://apify.com/luzivanlt/amazon-products-scraper): Every product on Amazon's search pages to the last page, sponsored marked, with monthly sales.
- [App Store Reviews Scraper: All Reviews, Not 500](https://apify.com/luzivanlt/app-store-reviews-scraper): Every written App Store review of an app, not just the newest 500.
- [Woolworths Coles ALDI Scraper: AU Grocery Prices](https://apify.com/luzivanlt/au-supermarkets-scraper): Woolworths, Coles and ALDI products for any search in one run, every results page to the end.
- [Bilibili Video Scraper: Search & Channel Videos](https://apify.com/luzivanlt/bilibili-videos-scraper): Bilibili videos from searches or whole channels, each with its full detail page's data.
- [Career Site Jobs Scraper: Workday, Greenhouse, Lever](https://apify.com/luzivanlt/career-site-jobs-scraper): Every job on Greenhouse, Lever, Ashby, SmartRecruiters and Workday boards, checked against each board's count.

### Use it from an AI agent or the API

One call starts a run and returns its items (Apify waits up to 300 seconds; for a
longer run, start it with `POST /v2/acts/…/runs` and read its dataset):

```text
POST https://api.apify.com/v2/acts/luzivanlt~threads-posts-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>
```

With the sample input as its JSON body:

```json
{
  "startUrls": ["https://www.threads.com/@nasa"],
  "maxPostsPerProfile": 20
}
```

Its inputs, in the order of the input form:

| Input                                        | What it takes                                                                                                                                                                                         | Default |
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `startUrls` (Profile links or usernames)     | Threads profiles to read: links such as https://www.threads.com/@nasa (threads.net links work too), or just the username (nasa or @nasa).                                                             | —       |
| `onlyPostsNewerThan` (Only posts newer than) | Keep only posts from this date on: a date (YYYY-MM-DD, UTC) or a period such as "7 days", "2 weeks", "3 months" or "1 year".                                                                          | —       |
| `maxPostsPerProfile` (Max posts per profile) | Stop reading a profile after this many posts.                                                                                                                                                         | `100`   |
| `onlyNewItems` (Only new posts)              | Turn this on for a scheduled run, or a re-run of the same task: each run then returns only the posts it has not returned before, reading each profile back to a day before the last run that read it. | —       |

Apify's MCP server, `https://mcp.apify.com`, lists it as `luzivanlt/threads-posts-scraper`. To give an
AI agent this Actor as a tool, add the server to the agent's MCP config:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=luzivanlt/threads-posts-scraper"
    }
  }
}
```

The client signs in with OAuth, or add `"headers": { "Authorization": "Bearer <APIFY_TOKEN>" }`.

Charged per post delivered; the sample input above costs at most $0.04.

### FAQ

**Do I need a Threads or Instagram account?**
No. The Actor reads what anyone can see on a public Threads profile.

**Can it read private profiles?**
No, only public ones.

**Can I search Threads by keyword or hashtag?**
Not yet: this Actor reads profiles.

**Can I run it from my own code, on a schedule, or with other apps?**
Yes. Like any Apify Actor, you can start it through the Apify API, run it on a
schedule, and connect it to other apps with Apify's integrations and webhooks.

### Is it legal to scrape Threads?

This Actor reads only public posts that anyone can see. Posts and profiles
hold personal data, such as names, ids and pictures: check Meta's terms and
the laws that apply to you (such as the GDPR) before you use the data. If you
are unsure, ask a lawyer.

### Support

Found a problem or missing a feature? Open an issue on the **Issues** tab and
include the run's link.

***

This Actor is not affiliated with, endorsed by or sponsored by Threads, Meta
or Instagram.

# Changelog

This Actor's version history is a separate document: https://apify.com/luzivanlt/threads-posts-scraper/changelog.md

# Actor input Schema

## `startUrls` (type: `array`):

Threads profiles to read: links such as https://www.threads.com/@nasa (threads.net links work too), or just the username (nasa or @nasa). Each profile gives you its posts, newest first. A link to a single post, a search or a tag page is not supported. Example: https://www.threads.com/@nasa

## `onlyPostsNewerThan` (type: `string`):

Keep only posts from this date on: a date (YYYY-MM-DD, UTC) or a period such as "7 days", "2 weeks", "3 months" or "1 year". Leave empty for the whole history. A date in the future is refused, and an older pinned post is left out. Example: 30 days

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

Stop reading a profile after this many posts. From 1 to 10,000; 100 if left empty. You pay $0.002 a post saved, so this caps each profile's cost: 100 posts cost at most $0.20.

## `onlyNewItems` (type: `boolean`):

Turn this on for a scheduled run, or a re-run of the same task: each run then returns only the posts it has not returned before, reading each profile back to a day before the last run that read it. Skipped posts are neither saved nor charged; each new post is charged as usual. Runs with other settings, or from another task, keep their own list. Off by default.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.threads.com/@nasa"
  ],
  "maxPostsPerProfile": 20
}
```

# Actor output Schema

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

Every post the run saved, one row per post.

## `allFields` (type: `string`):

The same rows with every field.

# 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 = {
    "startUrls": [
        "https://www.threads.com/@nasa"
    ],
    "maxPostsPerProfile": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("luzivanlt/threads-posts-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 = {
    "startUrls": ["https://www.threads.com/@nasa"],
    "maxPostsPerProfile": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("luzivanlt/threads-posts-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 '{
  "startUrls": [
    "https://www.threads.com/@nasa"
  ],
  "maxPostsPerProfile": 20
}' |
apify call luzivanlt/threads-posts-scraper --silent --output-dataset

```

## MCP server setup

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