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

Scrape Threads without login: full post history of any public profile, profile data with follower count, replies under any post, keyword and topic search. Date filters, monitoring of new posts. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/nice_dev/threads-posts-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** Social media, Lead generation, MCP servers
- **Stats:** 18 total users, 10 monthly users, 92.9% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.09 / 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

### 🧵 What is Threads Scraper?

**Threads Scraper** extracts **posts, profiles, replies and search results from [Threads](https://www.threads.com)**, Meta's text network: the **full post history of any public account**, its **profile with follower count**, the **replies under any post**, and the posts a **keyword or topic search** shows — with **likes, replies, reposts, quotes, media, links, polls and mentions** on every post.

Type a few **usernames** (`nasa`), paste **post URLs** or a **keyword**, click **Start**, and download the results in JSON, CSV or Excel. No login, nothing to set up. About **1,000 posts in 3 minutes**.

### 📋 What data can you extract from Threads?

One item per post or profile, 114 fields:

| Category | What you get |
| --- | --- |
| 📝 **Post** | text, link, date to the second, language, edited or not — `Happy equinox, Earthlings! 🍂` |
| 📊 **Engagement** | likes, replies, reposts, quotes, shares — `2 234 likes, 44 replies`; **views** of a post read by its URL — `161,167 views`; a ready-made **engagement rate** (interactions per view, or per follower when a post has no views) |
| 🖼️ **Media** | every photo and video of the post (carousels included), alt text, **video length, available resolutions and audio file**, GIF, stickers, music and podcast shared — title, artist, episode, link |
| 🔗 **Links and mentions** | links of the text and of the link card (real target, no redirect), mentioned accounts, hashtags, topic |
| 🗳️ **Polls** | every option with its votes, total votes, closed or not, end date |
| 💬 **Conversations** | who the post answers, the text and link of that post, depth in the thread, **place of a post in its author's thread and the posts Threads recommends next to it** (post read by its URL), quoted post, reposts |
| 👤 **Author** | username, name, verified badge, picture, profile link, follower count, bio, **e-mails and phone numbers of the bio**, and on request those found on the **website the author cites in the bio** |
| 🪪 **Profile** | name, bio, links, **e-mails and phone numbers written in the bio**, followers, verified, private, topics |
| 📁 **Extras (optional)** | **your own copy of the photos and videos** of the posts, and the **contacts found on the websites of the authors** — `media-3905-1.jpg` · `hello@acme-shop.fr` |
| 🤖 **AI (optional)** | an **AI sentiment label** (positive, neutral or negative, with a score) and **your own AI labels** (the ones you wrote that apply to the post, with a score) — `negative, 0.91` · `pricing, 0.82` |

Every field, with an example, is listed in the **Output** section below.

### ✅ Why use Threads Scraper?

- 💸 **Cheap**: $0.17 per 1,000 results, down to $0.088 on paid Apify plans — proxy and platform usage included.
- ⚡ **Fast**: about 1,000 posts in 3 minutes and 4,000 in 10 minutes from one account, with the default settings.
- 📜 **The whole history of an account**: every post back to the account's first one — or stop at a date with **Posted after** (very long histories: see **Known limitations**).
- 💬 **Replies included**: the replies under any post, sorted as Threads shows them (Top) or newest first, with their depth in the conversation — in the same run as the posts.
- 🧩 **Everything in one run**: accounts, their replies and reposts, single posts, keywords and topics together; a post found by several of them is saved once.
- 🔔 **Monitoring built in**: tick **Only new posts**, schedule the Actor, and each run returns (and charges) only the posts it never delivered before.
- 🤖 **What they think**: tick **AI sentiment label** for a positive / neutral / negative label on each post, and write **AI labels** (`pricing`, `complaint: The author reports a problem`) to see which of your topics each post is about.
- 📁 **Photos and videos that do not expire**: the media links Threads gives are signed and stop working. Tick **Download photos and videos** and each file is kept in your run's key-value store, with a link on the row.
- 📊 **A summary of each search**: tick **Keyword statistics** and the key-value store gets a `KEYWORD_STATS` record: posts per day, average and median likes, top hashtags, authors and posts of each keyword and topic you searched.
- 🔌 API, scheduling, integrations (Make, Zapier, n8n, Google Sheets…) and JSON / CSV / Excel export via the Apify platform.

### 🚀 How to scrape Threads

1. Create a free Apify account.
2. Open **Threads Scraper** and type one or more **Usernames** (e.g. `nasa`).
3. Or paste **Post URLs** to get posts with their replies, or type a **Search keyword**, or paste any Threads profile, post or search URL into **Threads URLs**.
4. Set **Max results** (100 by default, 0 = no limit) — and **Max posts per source** when you scrape several accounts — then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

### 💰 How much does it cost to scrape Threads?

This Actor uses **pay per event** pricing: **$0.17 per 1,000 results** (posts, replies and profiles) without an Apify subscription — plus **$0.01 per run start** (one per GB of memory: one at the default 512 MB). Paid Apify plans pay less: $0.15 (Bronze), $0.11 (Silver) and $0.088 (Gold) per 1,000 results. **Author follower counts**, when you turn it on, adds **$0.28 per 1,000 authors** looked up ($0.27, $0.26 and $0.25 on Bronze, Silver and Gold). **E-mails from bios** and **Phone numbers from bios** (both unticked by default: tick the one you need) are two separate extras: each is charged once per account and per run whose bio holds at least one e-mail address (`bio-email`) at **$3.59 per 1,000 accounts** ($3.19, $2.89 and $2.49 on Bronze, Silver and Gold) or one phone number (`bio-phone`) at **$3.59 per 1,000 accounts** ($3.19, $2.89 and $2.49 on Bronze, Silver and Gold); an account without any of that kind costs nothing, and left unticked each leaves its fields empty. **AI sentiment label** (unticked by default) adds a positive, neutral or negative label and its score to each post and reply: one `post-sentiment` event per row labelled, at **$8.09 per 1,000 rows labelled** ($8.08, $8.07 and $8.06 on Bronze, Silver and Gold); a post without text costs nothing. **AI labels** (empty by default) judges the labels you write on each post and reply: one `ai-label` event per post and per label judged, whether the label applies or not; a post without text costs nothing. **Download photos and videos** (unticked by default) keeps your own copy of the files of the posts: one `media-file` event per file kept; a file that could not be kept costs nothing. **Contacts from the author's website** (unticked by default, needs **Author follower counts**) opens the website each author cites in its bio: one `website-contacts` event per author, once per run, for whom an e-mail address or a phone number is found there; a website that gives neither costs nothing. It is separate from **E-mails from bios** and **Phone numbers from bios**, which read the bio itself. **Keyword statistics** (unticked by default) adds a summary of each keyword and topic you search: one `keyword-stats` event per search given, only for a search with at least 5 posts in the run and at most 50 searches per run, the biggest first; a search under 5 posts costs nothing, and the posts of accounts and post URLs are not summarised. See the **Pricing** tab for the amounts of these four extras. The two AI options need 2 GB of memory (Run options → Memory): with less, they are skipped, the log says so and nothing is charged. The engagement rate is free. A run without the AI options keeps the default memory and pays nothing for them. Example, without a subscription: the whole history of 10 accounts of 500 posts each (5,000 posts) ≈ $0.86; a daily monitor of 300 new posts ≈ $0.06. The filters Threads does not apply itself (`postedAfter` / `postedBefore`, `minLikes`, `minReplies`, `minReposts`, `mediaOnly`, `verifiedOnly`, `languages`, `includeAuthors`, `excludeAuthors`, `minAuthorFollowers`, `includeKeywords`, `excludeKeywords`) are checked by the Actor on every post it reads, kept or not: each post checked is charged a filter check (`filter-check`): **$0.055 per 1,000 posts checked** ($0.050, $0.045 and $0.040 on Bronze, Silver and Gold). A post is checked once per run, however many searches or accounts show it again; with **Only new posts**, a post your filters dropped for good is not checked, nor charged, again by the next runs (see Monitoring). `minAuthorFollowers` needs **Author follower counts**: unticked, it is ignored (the log says so) and nothing is charged for it; ticked, the profile page of each author is read, and charged as an author profile, once per author, for every post the other filters keep — even when the post is then dropped for its author's followers. Platform usage (compute, proxy) is included in the price.

### ⚙️ Input

```json
{
    "usernames": ["nasa", "natgeo"],
    "maxItems": 500
}
```

Posts with their replies, recent replies first:

```json
{
    "postUrls": ["https://www.threads.com/@nasa/post/DdXJKzbkqPg"],
    "maxReplies": 200,
    "repliesSort": "recent"
}
```

Several accounts, a cap per account, only the last two weeks, only the posts not delivered before:

```json
{
    "usernames": ["nasa", "spacex", "esa"],
    "maxItemsPerQuery": 100,
    "postedAfter": "14 days",
    "onlyNew": true,
    "stateKey": "space-watch"
}
```

| Field | Notes |
| --- | --- |
| `usernames` | Threads usernames (`nasa`, `@nasa`) or profile URLs: every post of each account, newest first. |
| `includeProfile` | One profile row per account (default on, no extra request). |
| `includeReplies`, `includeReposts` | Also the replies the account wrote (about 20-30 shown without an account) and its reposts (the last 1-4). |
| `postUrls` | Post URLs: the post, then its replies. |
| `maxReplies` | Replies per post (`0` = the post only). |
| `repliesSort` | Order of the replies: `top` or `recent`. |
| `repliesForAllPosts` | Also the replies under every post found through the accounts and the searches. |
| `query`, `searchQueries` | Keyword searches. With `deepSearch` (on by default): hundreds of posts for a common word, a few dozen for a rare one, only the posts that contain the keyword; off: the one page Threads shows without an account (about 20-35 posts). |
| `hashtags` | Topic searches (`ai`, `#nfl`): about 20-30 posts each, more with `deepSearch`. |
| `deepSearch` | Deep search (on by default): after the first search page, Threads' Recent and topic views, the keyword as a hashtag, the phrases found around it ("nike dunk") and the site in other languages — keeping only the posts that contain the keyword (text, quoted post, link, image description or topic), as Threads pads its results with loosely related posts. |
| `maxSearchPagesPerQuery` | Upper bound on the search pages Deep search reads for one keyword (default 300); it also stops by itself after several pages in a row without a new matching post. |
| `startUrls` | Any Threads profile, post or search URL (`https://www.threads.com/search?q=apify`), or a text file of URLs (one per line, read once when the run starts: a resurrected or migrated run keeps its URLs). |
| `maxItems` | Stop after this many results for the whole run (`0` = unlimited). |
| `maxItemsPerQuery` | Cap for EACH source (`0` = none): an account's posts, its replies and its reposts are three sources; a post with its replies, a keyword, a topic one each. The profile row is not counted. |
| `includeAuthorProfiles` | Fill the author follower count and bio of every post (one extra lookup per author, charged apart). |
| `includeBioEmails` | E-mail addresses written in the bios, in their own fields: on profile rows, and on posts with **Author follower counts**. Off by default; charged once per account that has some. |
| `includeBioPhones` | Phone numbers written in the bios, in their own fields: on profile rows, and on posts with **Author follower counts**. Off by default; charged once per account that has some. |
| `includeSentiment` | An AI sentiment label (positive / neutral / negative) and its score on each post and reply, in two extra fields. Off by default; charged once per row labelled, nothing for a post without text. Requires 2 GB of memory (Run options → Memory); with less the option is skipped and nothing is charged. |
| `aiLabels` | AI labels: your own labels, one per entry — a name (`pricing`) or a name and a sentence that is true when the label applies (`competitor: The author compares tools`); up to 20. Each post and reply gets the labels that apply, with a score from 0 to 1, in `aiLabelMatches`. Empty (the default) = off. Charged per row and per label judged, whether it applies or not; nothing for a post without text. Requires 2 GB of memory (Run options → Memory); with less the option is skipped and nothing is charged. |
| `downloadMedia`, `maxMediaFileMb` | Keep the photos and videos of the posts, and the audio track of their video, in the key-value store and give their links in two extra columns of the row (off by default). Charged once per file kept; a file over `maxMediaFileMb` (50 MB by default, 1 to 100; at most 50 below 1 GB), gone or out of time is not kept and not charged. |
| `includeWebsiteContacts` | Open the website each author cites in its bio and add the e-mails, phone numbers and social links found there (off by default; needs `includeAuthorProfiles`, without it nothing happens). Charged once per author for whom at least one e-mail or phone number is found; a website that cannot be opened or gives none costs nothing. Not the bio contacts of `includeBioEmails` / `includeBioPhones`. |
| `includeKeywordStats` | A summary of each keyword and topic you search, in the KEYWORD_STATS record of the key-value store (never in the dataset); off by default. Charged once per search given: at least 5 posts in the run, at most 50 searches, the biggest first. Only the posts found by a keyword or topic search count: the posts of an account, of a post URL and the replies under a post are not summarised. |
| `postedAfter`, `postedBefore` | Publication date range: `2026-09-01` (a UTC day), or a period before now (`7 days`, `2 weeks`, `1 month`, `24 hours`). |
| `minLikes`, `minReplies`, `minReposts`, `mediaOnly` | Only the posts with at least that many likes / replies / reposts, or with a photo or a video (a post whose count is unknown, because the account hides it, is dropped). |
| `verifiedOnly` | Only the posts whose author has the verified badge (a post whose badge is unknown is dropped). |
| `languages` | Only the posts written in one of these languages, as ISO 639-1 codes (`en`, `fr`, `ja`): the language column, given by Threads or detected from the text. A post whose language is unknown (text too short to tell) is dropped while the filter is on. |
| `minAuthorFollowers` | Only the posts whose author has at least that many followers (`0` = no minimum). Needs `includeAuthorProfiles`: without it the filter is ignored, with a warning in the log. |
| `includeAuthors`, `excludeAuthors` | Keep only / drop the posts written by these accounts (usernames such as `nasa` or `@nasa`, case ignored). |
| `includeKeywords` | Keep only the posts that contain one of these words, in the text, image descriptions, link card, hashtags or topic (case and accents ignored; a word is also found inside a longer word): with a keyword search, the results Threads returns without the keyword are dropped. |
| `excludeKeywords` | Drop the posts whose text, image descriptions or link card contain one of these words (case and accents ignored; a word is also found inside a longer word). |
| `onlyNew`, `stateKey`, `resetState` | Monitoring: only the posts never delivered under this memory key; `resetState` forgets the memory. |
| Advanced | `proxyConfiguration` (Apify proxy by default, included in the price; the residential proxy is not available), `maxConcurrency`, `maxRequestsPerMinute`, `maxRequestRetries`, `debugLog`. |

### 📦 Output

A post as the run saved it (empty fields left out, links shortened):

```json
{
    "type": "post",
    "id": "3991969585838706926",
    "url": "https://www.threads.com/@nasa/post/DdmUzAeFFDu",
    "source": "profile-posts",
    "sourceInput": "nasa",
    "searchUrl": "https://www.threads.com/@nasa",
    "scrapedAt": "2026-09-24T00:03:59.949Z",
    "code": "DdmUzAeFFDu",
    "text": "Happy equinox, Earthlings! 🍂\n\nSept. 22 marks the the first day of fall in the Northern Hemisphere. From now until the beginning of spring, nighttime hours will last longer than daylight as the Sun travels a shorter arc across the sky each day.",
    "createdAt": "2026-09-22T17:57:59.000Z",
    "createdAtTimestamp": 1790099879,
    "isEdited": false,
    "likeCount": 2235,
    "replyCount": 44,
    "repostCount": 141,
    "quoteCount": 14,
    "shareCount": 18,
    "viewCount": null,
    "engagementRate": 0.0002,
    "engagementBase": "followers",
    "mediaType": "image",
    "hasMedia": true,
    "images": [
        {
            "url": "https://instagram.fnap7-2.fna.fbcdn.net/v/t51.82787-15/818654783_18120464002960389_7323725605055789618_n.jpg",
            "width": 4096,
            "height": 3264,
            "altText": "This natural-color image shows the hilly region around State College, Pennsylvania. It show lines and ridges varying in size and color from orange to green."
        }
    ],
    "videos": [],
    "mediaUrls": [
        "https://instagram.fnap7-2.fna.fbcdn.net/v/t51.82787-15/818654783_18120464002960389_7323725605055789618_n.jpg"
    ],
    "accessibilityCaption": "This natural-color image shows the hilly region around State College, Pennsylvania. It show lines and ridges varying in size and color from orange to green.",
    "mentions": [],
    "hashtags": [],
    "links": [],
    "isReply": false,
    "isQuotePost": false,
    "isRepost": false,
    "mediaCount": 1,
    "isGif": false,
    "stickerUrls": [],
    "pollOptions": [],
    "isGhostPost": false,
    "isLikedByAuthor": false,
    "likeCountsHidden": false,
    "isPinned": false,
    "replyControl": "everyone",
    "isSpoiler": false,
    "authorId": "28829152388",
    "authorUsername": "nasa",
    "authorFullName": "NASA",
    "authorIsVerified": true,
    "authorProfilePicUrl": "https://instagram.fnap7-2.fna.fbcdn.net/v/t51.82787-19/669747085_18089786557960389_922072622069351626_n.jpg",
    "authorUrl": "https://www.threads.com/@nasa",
    "authorFollowerCount": 12739850,
    "authorBio": "Making the seemingly impossible, possible. ✨",
    "authorEmails": [],
    "authorPhones": [],
    "authorWebsiteEmails": [],
    "authorWebsitePhones": [],
    "authorSocialLinks": [],
    "bioLinks": [],
    "emails": [],
    "phones": [],
    "profileTags": []
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### Media files

With **Download photos and videos**, every photo and video of the posts the run delivers is kept in the run's key-value store as `media-<post id>-<n>.<extension>`, with its real content type, and so is the audio track of the post's video (`audioUrl`, `media-<post id>-audio.<extension>`, one more file). The row says where, in `storedMediaUrls` (same order as `mediaUrls`; `null` for a file not kept) and `storedAudioUrl`. The links Threads gives in `mediaUrls` and `audioUrl` are signed by Meta and expire: your copy stays. A GIF (`gifUrl`), the author's picture and the picture of a link card are not copied.

A file is kept whole or not at all, and charged only when it is kept. Not kept, and not charged: a file larger than `maxMediaFileMb`, a file Threads no longer serves, a download that fails or runs out of time, and any file beyond what the run's maximum cost pays for. The log says how many files were kept and why the others were not.

#### Keyword statistics

With **Keyword statistics**, the run adds a `KEYWORD_STATS` record to its key-value store (never a row of the dataset) with one summary per keyword and per topic you searched, the biggest first: the number of posts and of replies, the first and last post date, posts per day, the average and the median of likes, replies, reposts, quotes and views (a count Threads hides is left out, never read as 0), the median engagement rate, the share of posts with media, the number of authors and the share of verified ones, the languages when Threads gives them, the 10 most used hashtags, the 10 most active authors, the 5 posts with the most likes, and — with **AI sentiment label** — the share of positive, neutral and negative posts. Each summary carries `keyword` (a topic with its `#`) and `source` (`search` or `hashtag`).

A summary is made of the posts the run delivered for that search: a post that two of your searches both show is counted under the first one, and a pasted Threads search URL is named by its keyword. The posts of an account, of a post URL and the replies under a post are not the result of a search and are not summarised. A search needs at least 5 posts in the run and at most 50 searches are given; the others are listed in `notDelivered` with the reason. One `keyword-stats` event is charged per search given, never twice for a run that was moved to another server, and never past the maximum cost of the run. With **Only new posts**, only the posts delivered in this run are counted. The link to the record is in the run log.

#### Contacts from the author's website

With **Contacts from the author's website** (and **Author follower counts**, where the links come from), the Actor opens the website each author cites in its bio: its home page and up to two pages of the same site that the home page links as contact, about or legal notice (a link-in-bio page such as Linktree is one page). The row gets `authorWebsite` (the site), `authorWebsiteEmails` and `authorWebsitePhones` (`+` and digits for an international number), and `authorSocialLinks` (Instagram, Facebook, LinkedIn, X, YouTube, TikTok, WhatsApp and Telegram profiles, from the bio and from the website). Each website is read once per run: every post of the author carries the same values. The profile row of an account has none of these columns.

An author is charged once per run, and only when at least one e-mail address or phone number is found on its website; the social links are free. This is not the bio: the e-mails and phone numbers written in the bio itself stay in `authorEmails` / `authorPhones` (**E-mails from bios**, **Phone numbers from bios**). Links to Instagram, Facebook, YouTube, TikTok, X, LinkedIn, WhatsApp, Telegram and Threads are never opened, and the Actor reads only the website the author itself cites. A website that cannot be opened, is protected or gives nothing costs nothing, and the log counts them.

#### All 114 fields

| Fields | What you get |
| --- | --- |
| `type`, `id`, `url`, `source`, `sourceInput`, `searchUrl`, `scrapedAt` | `post` or `profile`, Threads id, public link, what produced the row (`profile-posts`, `profile-replies`, `profile-reposts`, `profile`, `post`, `replies`, `search`, `hashtag`), the username / URL / keyword you gave, the threads.com page it was read from (the account's page or tab, the post, the search), ISO timestamp |
| `code`, `text`, `createdAt`, `createdAtTimestamp`, `isEdited`, `language` | **Post**: code of its URL, full text, publication date (what the date filters read), edited, language (ISO 639-1 code such as `en`, `ja`, `zh`; left empty when the text is too short to tell) |
| `sentiment`, `sentimentScore`, `aiLabelMatches` | **AI** (options): `positive`, `neutral` or `negative` for the text of the post or reply, and the confidence in it from `0` to `1` (`0.91`) (**AI sentiment label**); the labels you wrote that apply to the text, each as `{ "label", "score" }`, `[]` when none applies (**AI labels**). `null` when the option is off or skipped, or when the row has no text |
| `likeCount`, `replyCount`, `repostCount`, `quoteCount`, `shareCount`, `viewCount`, `likeCountsHidden` | **Engagement**: `2234`, `44`, `141`, `14`, `18`; views (`161167`) only for a post read by its URL (**Post URLs**) — Threads shows them nowhere else, so posts of profiles, searches and replies have `null`; `likeCountsHidden` = the author hides likes and views (Threads shows no number): `likeCount` and `viewCount` are then `null`, never a false 0 |
| `engagementRate`, `engagementBase` | **Engagement rate** (computed for you, free): likes + replies + reposts + quotes divided by the views (`views`, a post read by its URL), or by the author's follower count when the post has no views (`followers`: the posts of an account, or any post with **Author follower counts**), 4 decimals — `0.0249`. A count Threads does not give counts 0, unless it gives none of the four. `null` when the post has neither views nor followers |
| `mediaType`, `hasMedia`, `hasAudio`, `mediaCount`, `images`, `videos`, `mediaUrls`, `accessibilityCaption` | **Media**: `text`, `image`, `video`, `carousel` or `audio`; every photo (`url`, `width`, `height`, `altText`) and video (`url`, `width`, `height`, `thumbnailUrl`, `durationSeconds`) |
| `videoDurationSeconds`, `videoQualities`, `audioUrl` | **First video of the post** (the one of `videos[0]`, on every source, nothing extra to pay): its length in seconds (`11.935`), the resolutions Threads offers, smallest first (`["720p", "1080p"]`), and its audio track as a separate file; `null` for a post without video or when Threads gives no readable manifest for it. In a carousel with several videos, `durationSeconds` of each entry of `videos` gives the length of each one |
| `storedMediaUrls`, `storedAudioUrl` | **Your copy of the media** (**Download photos and videos**): where each file of `mediaUrls` is kept in the run's key-value store, in the same order, `null` for a file not kept; where the audio track of `audioUrl` is kept. `[]` and `null` when the option is off |
| `isGif`, `gifUrl`, `stickerUrls`, `musicTitle`, `musicArtist`, `musicSongId`, `podcastName`, `podcastEpisodeName`, `podcastPlatform`, `podcastUrl` | GIF, stickers, song attached, podcast episode shared (`SPOTIFY`, `APPLE_PODCASTS`…) |
| `mentions`, `hashtags`, `links`, `topicTag`, `linkUrl`, `linkTitle`, `linkDisplayUrl`, `linkImageUrl` | **Links and mentions**: usernames, hashtags, links of the text, topic (`NFL Threads`), link card — real targets, no redirect |
| `pollOptions`, `pollTotalVotes`, `pollIsClosed`, `pollExpiresAt` | **Polls**: `{text, votes}` per option |
| `isReply`, `replyToUsername`, `replyToUserId`, `replyToText`, `replyToPostId`, `replyToUrl`, `replyDepth`, `rootPostUsername`, `isLikedByAuthor`, `relatedTo` | **Conversations**: the post answered, depth under the post whose replies are read (`1` = direct reply), starter of the thread, liked by the author answered, the post URL the reply belongs to |
| `positionInThread`, `threadLength`, `relatedPostUrls` | **Thread of the author and recommendations**, only for a post read by its URL (**Post URLs**, or a post link in **Threads URLs**) — nothing extra to pay: the place of the post in the thread of its author (`2` of `9`: the author's own posts in a row, `1` and `1` for a post alone; a reply to another author starts its own count) and the URLs of the posts Threads recommends on that page (`[]` when it shows none). Posts of profiles, searches and replies have `null`: their page does not give the whole thread |
| `isQuotePost`, `quotedPostId`, `quotedPostUrl`, `quotedPostText`, `quotedPostUsername`, `isRepost`, `repostedByUsername` | Quoted post; reposts of **Reposts by each account** (the original post, and who reposted it) |
| `isPinned`, `replyControl`, `isPaidPartnership`, `isSpoiler`, `isAiGenerated`, `isGhostPost`, `locationId`, `locationName` | Pinned on the profile, who can reply, paid partnership, spoiler, AI label, 24-hour post, place tagged |
| `authorId`, `authorUsername`, `authorFullName`, `authorIsVerified`, `authorProfilePicUrl`, `authorUrl`, `authorFollowerCount`, `authorBio`, `authorEmails`, `authorPhones` | **Author**; followers and bio for the accounts of **Usernames**, and for every author with **Author follower counts** — with the e-mails (**E-mails from bios**) and phone numbers (**Phone numbers from bios**) written in that bio |
| `authorWebsite`, `authorWebsiteEmails`, `authorWebsitePhones`, `authorSocialLinks` | **Author's website** (**Contacts from the author's website**): the website cited in the bio, the e-mails and phone numbers found on it, the social profiles of the bio and of the website. `null` and `[]` when the option is off |
| `username`, `fullName`, `bio`, `bioLinks`, `emails`, `phones`, `followerCount`, `isVerified`, `isPrivate`, `profilePicUrl`, `profileTags`, `transparencyLabel` | **Profile** rows: `nasa`, `NASA`, bio, its links, e-mails and phone numbers written in it, `12739843` followers, badges, topics |

### 💡 Tips

#### How to get more results

Leave **Max results** at `0` and add usernames: an account gives its whole history. A keyword search with **Deep search** gives hundreds of posts for a common word, a few dozen for a rare one (Threads shows one page of about 20-35 to visitors without an account; Deep search reads its other views, related phrases and languages): add more keywords, or take the accounts that post about your topic.

#### How to reduce costs

The price is per result, so the levers are `maxItems`, `maxItemsPerQuery`, `maxReplies`, the filters (a filtered-out post is not charged as a result, only its filter check — a narrow filter on a long history checks many posts to keep few) and `onlyNew` for recurring runs (you never pay twice for the same post, and a post dropped by a date, language, author, keyword or media filter is not checked again). **Author follower counts** is charged per author: leave it off when you do not need the followers of every author. **E-mails from bios** and **Phone numbers from bios** are each charged per account that has some: leave off the one you do not need. The AI options are charged per post (and per label): leave them off, or keep the number of labels low, when you only need the text. **Download photos and videos** is charged per file kept and **Contacts from the author's website** per author for whom a contact is found: leave them off when the dataset is enough.

#### Several accounts, posts and searches in one run

Fill `usernames`, `postUrls`, `searchQueries` and `hashtags` together: each one is a source of its own. A post found by several sources is saved — and charged — once. Set `maxItemsPerQuery` to give every source its own cap: without it the first accounts can use up the whole `maxItems` budget.

#### Monitoring: only the new posts

Tick **Only new posts** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the posts already delivered: they are not saved and not charged. The memory lives in a named key-value store of your account (`threads-posts-scraper-seen`, up to 150,000 posts per key) and is only updated with posts that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey` (two schedules sharing a key would hide each other's posts), and tick `resetState` once to start over. An account's history stops once it meets 20 posts in a row you already have (pinned posts are not counted; fewer under a small `maxItems` or `maxItemsPerQuery`), so the older posts a cap left out of an earlier run are not fetched later. The posts your filters dropped for good are remembered too: `postedAfter` (older posts), `languages`, `includeAuthors`, `excludeAuthors`, `includeKeywords`, `excludeKeywords` and `mediaOnly`. The next run skips them without checking them, so it is not charged a filter check for them. This memory is kept as long as the rest of your input stays the same (the limits, the pace, the proxy and the memory key can change) and `resetState` forgets it. A post dropped by something that can change (`minLikes`, `minReplies`, `minReposts`, `verifiedOnly`, `minAuthorFollowers`, `postedBefore`) is checked again at every run, so it comes out the day it has enough likes or falls inside the dates. To get the older posts a cap left out, run once without `onlyNew`, with `postedBefore` set to the date of the oldest post you have (the newer ones are then filtered out, each one charged its filter check).

#### Filter by publication date

`postedAfter` and `postedBefore` take a date (`2026-09-01`, the whole day is included, UTC) or a period before now (`7 days`, `2 weeks`, `1 month`; via the API also `24 hours` or a full ISO date-time), counted from the start of the run — a resurrected or migrated run keeps the period of its first start; the log shows it as `Date range (UTC)`. The filter reads `createdAt`. Filtered-out posts are not saved and do not count in `maxItems`; each post the date filter checks is charged a filter check, kept or not (see Pricing). On an account, the history stops at the first page older than `postedAfter` (pinned posts excepted).

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per Threads post, reply or profile (column `type`). Actor id: `nice_dev/threads-posts-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/threads-posts-scraper`.

Smallest input, for a cheap first call:

```json
{
    "usernames": ["nasa"],
    "maxItems": 10
}
```

Key output fields: `type`, `url`, `text`, `createdAt`, `likeCount`, `replyCount`, `repostCount`, `engagementRate` and `authorUsername`.

Cost: $0.17 per 1,000 results plus $0.01 per run start ($0.088 per 1,000 on the Gold plan). Author follower counts, the e-mails and the phone numbers of the bios (each off by default: `includeBioEmails: true`, `includeBioPhones: true`), the AI sentiment label and your AI labels (off by default: `includeSentiment: true`, `aiLabels`), the copy of the media files (`downloadMedia: true`), the contacts of the authors' websites (`includeWebsiteContacts: true`), the summary of each search (`includeKeywordStats: true`) and the filters cost extra, see the pricing section above. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape Threads?

The Actor only reads what Threads shows publicly to any visitor without an account. It logs in to nothing and uses no account or cookie of yours. With **Contacts from the author's website** it also opens the public website an author itself cites in its bio, and nothing else. Results contain personal data (usernames, names, bios, posts, and the e-mails or phone numbers people wrote in their bio or published on their website), which is protected by GDPR: do not store it without a legitimate reason, and delete what an author has deleted. You are responsible for using the data in compliance with Threads' Terms of Use and applicable law. This Actor is not affiliated with Threads or Meta.

#### Does it need a Threads account or a proxy?

No account. The proxy is included in the price: leave the default setting (the residential proxy is not available). When Threads refuses a request, it is sent again at once on a new proxy session.

#### Is the data safe to open in Excel or to show on a web page?

Posts and bios are their authors' own words, copied as they are. A text can begin with `-`, `+`, `=` or `@` (a mention, `-20% today`): Excel and Google Sheets may read such a cell of a CSV file as a formula. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. Every URL field holds an http(s) URL or null. On a web page, escape every field like any text written by a stranger.

#### Known limitations

- Keyword and topic searches: Threads shows visitors without an account one page of about 20-35 posts per search, and ignores the dates and author of its search. **Deep search** widens it (views, related phrases, languages), up to a few hundred posts for a common word — not the whole history of a keyword, which needs an account. The date filters of this Actor are applied to what the pages show.
- Followers and following lists need a Threads account: not available.
- Replies under a post: Threads shows visitors about 80 % of the replies it counts (hidden, deleted and some nested replies are missing).
- An account's Replies tab shows about 20-30 replies, its Reposts tab the last 1-4, to visitors without an account.
- A private account gives its profile row only.
- Threads answers a limited number of requests per IP address (about 2,000 posts' worth), then refuses that address for more than half an hour. The Actor moves to another proxy address at each refusal; a run that reads very long histories (tens of thousands of posts) can run out of fresh addresses: its last requests then fail, are counted in the last line of the log and listed in `FAILED_REQUESTS`, and nothing is charged for them. Your own proxies (**Proxy configuration**) add addresses.
- `onlyNew` remembers post ids, not their content: a post whose likes changed is not returned again.
- Files kept with **Download photos and videos** weigh on the run's storage and memory: a photo is a fraction of a MB, a video can be tens. With less than 1 GB (the default is 512 MB) the files are copied 4 at a time and none over 50 MB is kept; for many videos, or for videos above 50 MB, give the run 1 GB or more (Run options → Memory) and raise `maxMediaFileMb`.

**A run the platform stops without warning** (out of memory, run timeout)

- Resurrect it: it goes on from where it stood at most a minute before the stop. The results already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved right after posts are written, at most once every 2 seconds: resurrect the stopped run and the posts it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the last few seconds of them once more.

#### Something doesn't work?

The last line of the log counts the results saved, filtered out, not found on Threads (an account or a post that does not exist, was deleted or is not public), and the requests that failed after every retry. Those requests and the targets not found are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing fails when requests failed, or when every account or post asked was not found; its last message gives the cause. A run that saved some results fails too when Threads refused at least as many of its API calls as it answered (the pages alone hold only the first posts of each account or post), or when at least as many requests failed as were read: a green run with a short dataset would hide the outage. One failed request among many is only a warning. It also fails when Threads changes its pages: the run stops and names what it could not read, instead of ending green with empty columns or no results.

If Threads changes its pages, you are told instead of paying for blank rows: if the first 20 posts read all lack their date, author or counts — or the first 20 profiles their username or followers —, the run saves nothing more, stops and fails, and its last message names the missing field.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which URLs failed and why.

# Actor input Schema

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

Threads usernames (`nasa`, `@nasa`) or profile URLs (`https://www.threads.com/@nasa`). One result per post of each account, newest first, down to the account's first post unless a cap or **Posted after** stops it earlier. Max 1 000 accounts.

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

Also save one profile row per account: name, bio, bio links, follower count, verified badge, and the e-mails and phone numbers written in the bio (with **E-mails from bios** and **Phone numbers from bios**). Read from the same page as the first posts (no extra request).

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

Also save the replies the account wrote under other posts (the profile's Replies tab). Threads shows about 20-30 of them to visitors without an account.

## `includeReposts` (type: `boolean`):

Also save the posts the account reposted (the profile's Reposts tab). Threads shows only the last 1-4 reposts to visitors without an account.

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

Threads post URLs (`https://www.threads.com/@nasa/post/DdXJKzbkqPg`; threads.net links work too). One result for the post (with its view count, which Threads shows only on the post's own page), then its replies (see **Max replies per post**). Max 1 000 posts.

## `maxReplies` (type: `integer`):

Replies to save under each post of **Post URLs** (and under every post found when **Replies of every post found** is on). 0 = the post only. Threads shows visitors about 80 % of the replies it counts: hidden, deleted and some nested replies are missing.

## `repliesSort` (type: `string`):

Top = Threads' own ranking (most relevant first), Recent = newest first.

## `repliesForAllPosts` (type: `boolean`):

Also collect the replies under every post found through **Usernames** and the searches, not only under **Post URLs**. One or more extra requests per post that has replies.

## `query` (type: `string`):

Free-text search, as typed in the Threads search box (e.g. `artificial intelligence`). With **Deep search**: up to several hundred posts for a common word, a few dozen for a rare one; without it, about 20-35.

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

Several keywords in one run: one search per keyword. Added to **Search keyword**; posts found by several searches are saved once.

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

Topic searches (`ai`, `#nfl`): the posts filed under that topic — about 20-30 per topic, more with **Deep search** (the topic page and the `#tag` searched as a keyword).

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

Find more posts per keyword and topic: after the first search page, also Threads' Recent and topic views, a one-word keyword as a hashtag (`#nike`), the longer phrases found around your keyword in the results (`nike dunk`, `nike stock`) and the site in other languages — keeping only the posts that contain your keyword (text, quoted post, shared link, image description or topic; case and accents ignored), as Threads pads its results with loosely related posts. Off = the one search page Threads shows, every post of it (about 20-35).

## `maxSearchPagesPerQuery` (type: `integer`):

Upper bound on the Threads search pages read for one keyword or topic by **Deep search** (about 1 MB each). The search also stops by itself after several pages in a row without a new matching post, or once **Max posts per source** is reached.

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

Any mix of Threads profile URLs, post URLs and search URLs (`https://www.threads.com/search?q=apify`): each is handled like the matching field above. A text file of URLs (one per line, uploaded or linked) works too. Max 1 000 URLs.

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

Maximum number of results (posts, replies and profiles) to save for the whole run, after deduplication and filters. 0 = no limit.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH source, so that the first one cannot use up the whole **Max results** budget: an account's posts, its replies and its reposts are three sources (each with this cap); a post with its replies, a keyword and a topic are one each. The profile row is not counted. 0 = no per-source cap.

## `includeAuthorProfiles` (type: `boolean`):

Fill the author follower count and bio of every post, by opening the profile page of each distinct author once (1 extra page per author; charged as an extra event, see Pricing).

## `includeBioEmails` (type: `boolean`):

Pull the e-mail addresses written in each bio into their own fields: on profile rows (`emails`) and, with Author follower counts, on every post of the author (`authorEmails`). Charged once per account whose bio has at least one e-mail address (an extra event, see Pricing); a bio without any costs nothing. Unticked (default): those fields stay empty.

## `includeBioPhones` (type: `boolean`):

Pull the phone numbers written in each bio into their own fields: on profile rows (`phones`) and, with Author follower counts, on every post of the author (`authorPhones`). Charged once per account whose bio has at least one phone number (an extra event, see Pricing); a bio without any costs nothing. Unticked (default): those fields stay empty.

## `includeSentiment` (type: `boolean`):

Add an AI sentiment label to the text of each post and reply: positive, neutral or negative, with a score from 0 to 1, in two extra fields. Charged once per post or reply that gets a label (an extra event, see Pricing); a post without text costs nothing. Requires 2 GB of memory (Run options → Memory): with less, the option is skipped, the log says so and nothing is charged. Unticked (default): those fields stay empty.

## `aiLabels` (type: `array`):

Your own labels, judged on the text of each post and reply: a name such as `pricing`, or a name and a sentence that is true when the label applies, after a colon, such as `competitor: The author compares tools`. Up to 20. Each post and reply gets the labels that apply, with a score from 0 to 1, in `aiLabelMatches`. Charged per post and per label judged, whether it applies or not (an extra event, see Pricing); a post without text costs nothing. Requires 2 GB of memory (Run options → Memory): with less, the option is skipped, the log says so and nothing is charged. Empty (default): off.

## `downloadMedia` (type: `boolean`):

Keep a copy of the photos and videos of each post, and the audio track of its video, in the run's key-value store (`media-<post id>-<n>.<extension>`) and put the links in `storedMediaUrls` (same order as `mediaUrls`) and `storedAudioUrl`. The links Threads gives in `mediaUrls` are signed and expire: your copy does not. Charged once per file kept (an extra event, see Pricing); a file that could not be kept (too big, gone, out of time) costs nothing and shows as `null`. The files are kept for the posts the run delivers. For many videos, give the run 1 GB or more of memory (Run options → Memory). Unticked (default): nothing is downloaded and those fields stay empty.

## `maxMediaFileMb` (type: `integer`):

With **Download photos and videos**: a file larger than this is not kept and not charged (`null` in `storedMediaUrls`). A photo is a fraction of a MB, a video a few MB to a few tens. Above 50, give the run 1 GB or more of memory (Run options → Memory): with less, no file over 50 MB is kept.

## `includeWebsiteContacts` (type: `boolean`):

Open the website each author cites in its bio (its home page and up to two of its contact, about or legal pages; one page for a link-in-bio page such as Linktree) and add the e-mail addresses, phone numbers and social links found there, in `authorWebsite`, `authorWebsiteEmails`, `authorWebsitePhones` and `authorSocialLinks`. Needs **Author follower counts** (the links come from the bio): without it the option does nothing. Charged once per author for whom at least one e-mail address or phone number is found (an extra event, see Pricing; separate from **E-mails from bios** and **Phone numbers from bios**, which read the bio itself); a website that cannot be opened or gives nothing costs nothing. Links to Instagram, Facebook, YouTube, TikTok, X, LinkedIn, WhatsApp and Telegram are never opened, they are listed as they are. Unticked (default): those fields stay empty.

## `includeKeywordStats` (type: `boolean`):

Add a summary of each keyword and topic you search to the run's key-value store, in the `KEYWORD_STATS` record (never in the dataset): number of posts and replies, first and last date, posts per day, average and median likes, replies, reposts, quotes and views, median engagement rate, share of posts with media, share of verified authors, languages when Threads gives them, top 10 hashtags, top 10 authors, top 5 posts by likes, and the share of positive, neutral and negative posts when **AI sentiment label** is on. Only the posts found by a keyword or topic search are summarised, one summary per search: the posts of an account, of a post URL and the replies under a post are not (a post that two searches both show counts under the first). Charged once per search given (an extra event, see Pricing); a search needs at least 5 posts in the run and at most 50 are given, the biggest first. With **Only new posts**, only the posts delivered in this run are counted. Unticked (default): nothing is added.

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

Only posts published on or after this date: `2026-09-01` (a day in UTC, while Threads shows your own time zone), or a period before now such as `7 days`, `2 weeks`, `1 month` (API: `24 hours` and full ISO date-times work too). On an account, the history stops as soon as it reaches older posts (pinned posts excepted).

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

Only posts published on or before this date (the whole UTC day is included), or older than a period such as `30 days`.

## `minLikes` (type: `integer`):

Only posts with at least this many likes. 0 = no minimum. A post whose like count is unknown (some accounts hide it) is dropped.

## `minReplies` (type: `integer`):

Only posts with at least this many replies. 0 = no minimum. A post whose reply count is unknown is dropped.

## `minReposts` (type: `integer`):

Only posts reposted at least this many times (quotes not counted: the number under Threads' repost button adds them). 0 = no minimum. A post whose repost count is unknown is dropped.

## `mediaOnly` (type: `boolean`):

Only posts with at least one image or video.

## `verifiedOnly` (type: `boolean`):

Only posts whose author has the verified badge. A post whose author's badge is unknown is dropped.

## `languages` (type: `array`):

Only posts written in one of these languages, as two-letter ISO 639-1 codes: `en`, `fr`, `ja`, `pt`… (case ignored; `pt-BR` reads as `pt`). It reads the language column of the output, given by Threads or detected from the text. A post whose language is unknown (a text too short to tell, nothing from Threads) is dropped while this filter is on. Profiles are never filtered.

## `minAuthorFollowers` (type: `integer`):

Only posts whose author has at least this many followers. 0 = no minimum. Needs **Author follower counts**: the followers are only known once the author's profile page is read. Unticked, this filter is ignored (a warning in the log says so): no post is dropped and no check is charged for it. Ticked, the profile page of each author is read, and charged as an author profile, once per author, for every post the other filters keep — even when the post is then dropped for its author's followers. A post whose author's page cannot be read is dropped.

## `includeAuthors` (type: `array`):

Keep only the posts written by these accounts: usernames such as `nasa` or `@nasa` (case ignored; a profile URL works too). Useful with keyword and topic searches, to keep the posts of a list of accounts.

## `excludeAuthors` (type: `array`):

Drop the posts written by these accounts: usernames such as `spambot` or `@spambot` (case ignored; a profile URL works too).

## `includeKeywords` (type: `array`):

Keep only the posts whose text, image descriptions, link card, hashtags or topic contain one of these words (case and accents ignored; a word is also found inside a longer word: "art" finds "party"). With a keyword search, type the same words to drop the results Threads returns without them.

## `excludeKeywords` (type: `array`):

Drop the posts whose text, image descriptions or link card contain one of these words (case and accents ignored; a word is also found inside a longer word: "art" finds "party").

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

Skip the posts and replies that a previous run (same **Memory key**) already delivered: they are not saved and not charged. On an account, the history stops after 20 posts in a row already delivered (pinned posts excepted; fewer under a small **Max results** or **Max posts per source**): older posts that a cap left out of a previous run are not fetched later. First run = everything is new.

## `stateKey` (type: `string`):

Name of the memory used by **Only new posts**. Give each schedule / task its own key (e.g. `brand-watch`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every post again. Untick it afterwards.

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

Apify Proxy or your own proxies. Keep the default (Apify Proxy): it is included in the price, and the Actor switches to another IP by itself when Threads refuses one. The residential Apify proxy is not available in this Actor.

## `maxConcurrency` (type: `integer`):

Maximum number of requests processed in parallel.

## `maxRequestsPerMinute` (type: `integer`):

Global request rate. Threads limits the number of requests per IP, not their speed: lowering this does not help.

## `maxRequestRetries` (type: `integer`):

Retries per page before it is marked as failed. Requests for posts, replies and search results are always retried at least 10 times, each time on another IP, whatever this says; above 10, this setting decides.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "usernames": [
    "nasa"
  ],
  "includeProfile": true,
  "includeReplies": false,
  "includeReposts": false,
  "postUrls": [],
  "maxReplies": 100,
  "repliesSort": "top",
  "repliesForAllPosts": false,
  "searchQueries": [],
  "hashtags": [],
  "deepSearch": true,
  "maxSearchPagesPerQuery": 300,
  "startUrls": [],
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "includeAuthorProfiles": false,
  "includeBioEmails": false,
  "includeBioPhones": false,
  "includeSentiment": false,
  "downloadMedia": false,
  "maxMediaFileMb": 50,
  "includeWebsiteContacts": false,
  "includeKeywordStats": false,
  "minLikes": 0,
  "minReplies": 0,
  "minReposts": 0,
  "mediaOnly": false,
  "verifiedOnly": false,
  "languages": [],
  "minAuthorFollowers": 0,
  "includeAuthors": [],
  "excludeAuthors": [],
  "includeKeywords": [],
  "excludeKeywords": [],
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 4,
  "maxRequestsPerMinute": 120,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# 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": [
        "nasa"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

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