{
  "openapi": "3.0.1",
  "info": {
    "title": "Threads Search Scraper: Posts by Keyword, Mentions & Monitoring",
    "description": "Search Threads by keywords, phrases and hashtags without login: hundreds of recent posts per keyword, only posts that contain your keyword, views, author followers and bio contacts, monitoring of new mentions. Export JSON, CSV or Excel.",
    "version": "0.0",
    "x-build-id": "tEWffE7BEAaJ86Vjc"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/nice_dev~threads-search-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-nice_dev-threads-search-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/nice_dev~threads-search-scraper/runs": {
      "post": {
        "operationId": "runs-sync-nice_dev-threads-search-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/nice_dev~threads-search-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-nice_dev-threads-search-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "keywords": {
            "title": "Keywords",
            "maxItems": 100,
            "uniqueItems": true,
            "type": "array",
            "description": "Words, phrases or hashtags, as typed in the Threads search box: `nike`, `artificial intelligence`, `#ai`. Put a phrase in quotes (`\"air max\"`) to require the exact phrase. `@account` = the posts of that account (its whole history). Max 100 keywords of 200 characters.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "maxItemsPerKeyword": {
            "title": "Max posts per keyword",
            "minimum": 0,
            "maximum": 10000,
            "type": "integer",
            "description": "Posts to save for EACH keyword (after filters and deduplication). 0 = as many as Threads shows. A rare keyword can return fewer: Threads shows visitors only its recent public posts (see **Deep search**).",
            "default": 50
          },
          "sortByRecent": {
            "title": "Newest first",
            "type": "boolean",
            "description": "On: Threads' Recent view is read first and each page is saved newest first. Off: Threads' Top ranking first. Threads' public search shows recent posts either way (about 90 % from the last 24 hours).",
            "default": true
          },
          "deepSearch": {
            "title": "Deep search",
            "type": "boolean",
            "description": "Find more posts per keyword: after Threads' Top, Recent and topic views, also search 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 posts that contain your keyword. Off = the three views only (about 15-35 posts per keyword).",
            "default": true
          },
          "includeViews": {
            "title": "View counts",
            "type": "boolean",
            "description": "Fill `viewCount` by reading each post a keyword search finds on its own page, the only place Threads shows the views (about 0.8 MB and 1 s per post; very new posts can have none yet). The posts of accounts (`@account`, **Search inside accounts**) and replies have no views. Turn it off for the fastest runs.",
            "default": true
          },
          "fromUsers": {
            "title": "Search inside accounts",
            "maxItems": 1000,
            "uniqueItems": true,
            "type": "array",
            "description": "Usernames (`nasa`, `@nasa`) or profile URLs: every post of these accounts (their whole history, newest first) that contains one of the keywords. Without keywords, all their posts. Max 1 000 accounts.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "Threads URLs",
            "maxItems": 1000,
            "type": "array",
            "description": "Threads search URLs (`https://www.threads.com/search?q=nike`), profile URLs or post URLs: handled like a keyword, an @account keyword or a single post. A text file of URLs (one per line, uploaded or linked) works too. Max 1 000 URLs.",
            "default": [],
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "maxItems": {
            "title": "Max results",
            "minimum": 0,
            "maximum": 1000000,
            "type": "integer",
            "description": "Maximum number of results (posts, replies and profiles) for the whole run, after deduplication and filters. 0 = no limit.",
            "default": 1000
          },
          "requireKeywordMatch": {
            "title": "Only posts that contain a keyword",
            "type": "boolean",
            "description": "Keep only the posts in which one of your keywords appears (text, quoted post, shared link, image description or topic; case and accents ignored). Threads pads its public results with loosely related posts: turned off, you get them too (field `matchedKeywords` empty).",
            "default": true
          },
          "postedAfter": {
            "title": "Posted after",
            "type": "string",
            "description": "Only posts published on or after this date: `2026-09-01` (a day in UTC), or a period before now such as `24 hours`, `7 days`, `2 weeks`. Threads' public search mostly shows posts from the last day or two; on an account, the history stops at older posts (pinned posts excepted)."
          },
          "postedBefore": {
            "title": "Posted before",
            "type": "string",
            "description": "Only posts published on or before this date (the whole UTC day is included), or older than a period such as `30 days`."
          },
          "minLikes": {
            "title": "Min likes",
            "minimum": 0,
            "maximum": 1000000000,
            "type": "integer",
            "description": "Only posts with at least this many likes. 0 = no minimum.",
            "default": 0
          },
          "minReplies": {
            "title": "Min replies",
            "minimum": 0,
            "maximum": 1000000000,
            "type": "integer",
            "description": "Only posts with at least this many replies. 0 = no minimum.",
            "default": 0
          },
          "minReposts": {
            "title": "Min reposts",
            "minimum": 0,
            "maximum": 1000000000,
            "type": "integer",
            "description": "Only posts reposted at least this many times (quotes not counted: the number under Threads' repost button adds them). 0 = no minimum.",
            "default": 0
          },
          "mediaOnly": {
            "title": "Only posts with media",
            "type": "boolean",
            "description": "Only posts with at least one image or video.",
            "default": false
          },
          "mediaTypes": {
            "title": "Media types",
            "maxItems": 5,
            "uniqueItems": true,
            "type": "array",
            "description": "Only the posts of these kinds: `text` (no photo or video of its own: a link card, a poll or a GIF can come with it), `image` (one photo), `carousel` (several photos or videos), `video`, `audio` (a voice note). Empty = every kind.",
            "items": {
              "type": "string",
              "enum": [
                "text",
                "image",
                "video",
                "carousel",
                "audio"
              ],
              "enumTitles": [
                "Text",
                "Image",
                "Video",
                "Carousel",
                "Voice note"
              ]
            },
            "default": []
          },
          "excludeReplies": {
            "title": "Exclude replies",
            "type": "boolean",
            "description": "Drop the replies (posts written under another post) and keep only top-level posts.",
            "default": false
          },
          "verifiedOnly": {
            "title": "Verified authors only",
            "type": "boolean",
            "description": "Only the posts whose author has the verified badge. Off = every author.",
            "default": false
          },
          "excludeAuthors": {
            "title": "Exclude authors",
            "maxItems": 1000,
            "uniqueItems": true,
            "type": "array",
            "description": "Drop the posts of these accounts: usernames (`nasa`, `@nasa`) or profile URLs. Max 1 000 accounts.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "excludeKeywords": {
            "title": "Exclude keywords",
            "maxItems": 50,
            "uniqueItems": true,
            "type": "array",
            "description": "Drop the posts whose text, image descriptions or link title contain one of these words (case and accents ignored). A word is also found inside a longer one: `art` drops `party` too.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "includeAuthorProfiles": {
            "title": "Author profiles",
            "type": "boolean",
            "description": "Fill the author's follower count and bio on every post, by opening the profile page of each distinct author once (charged as an extra event per author, see Pricing). Unticked (default): no follower count nor bio.",
            "default": false
          },
          "includeAuthorContacts": {
            "title": "Author contacts",
            "type": "boolean",
            "description": "Also give the e-mail addresses and phone numbers written in the author's bio (`authorEmails`, `authorPhones`). Needs **Author profiles**; charged once per author who has at least one (see Pricing). Nothing is looked up outside Threads.",
            "default": false
          },
          "includeProfile": {
            "title": "Profile of each searched account",
            "type": "boolean",
            "description": "For `@account` keywords and **Search inside accounts**: also save one profile row per account (name, bio, links, followers, e-mails and phones of the bio). Read from the same page as its first posts (no extra request).",
            "default": false
          },
          "repliesForAllPosts": {
            "title": "Replies of every post found",
            "type": "boolean",
            "description": "Also save the replies under every post found (see **Max replies per post**). One or more extra requests per post that has replies.",
            "default": false
          },
          "maxReplies": {
            "title": "Max replies per post",
            "minimum": 0,
            "maximum": 10000,
            "type": "integer",
            "description": "Replies to save under each post found (with **Replies of every post found**) and under each post URL. 0 = the post only. Threads shows visitors about 80 % of the replies it counts.",
            "default": 20
          },
          "repliesSort": {
            "title": "Replies order",
            "enum": [
              "top",
              "recent"
            ],
            "type": "string",
            "description": "Top = Threads' own ranking (most relevant first), Recent = newest first.",
            "default": "top"
          },
          "includeSentiment": {
            "title": "AI sentiment label",
            "type": "boolean",
            "description": "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.",
            "default": false
          },
          "aiLabels": {
            "title": "AI labels",
            "maxItems": 20,
            "type": "array",
            "description": "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.",
            "items": {
              "type": "string"
            }
          },
          "includeKeywordStats": {
            "title": "Keyword statistics",
            "type": "boolean",
            "description": "Add a summary of each keyword 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. A post that contains several keywords counts under each. Charged once per keyword given (an extra event, see Pricing); a keyword needs at least 5 posts in the run and at most 50 keywords are given, the biggest first. With **Only new posts**, only the posts delivered in this run are counted. Unticked (default): nothing is added.",
            "default": false
          },
          "downloadMedia": {
            "title": "Download photos and videos",
            "type": "boolean",
            "description": "Keep a copy of the photos, videos and voice notes of each post 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.",
            "default": false
          },
          "maxMediaFileMb": {
            "title": "Largest file to keep",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "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.",
            "default": 50
          },
          "includeWebsiteContacts": {
            "title": "Contacts from the author's website",
            "type": "boolean",
            "description": "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 profiles** (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); 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.",
            "default": false
          },
          "onlyNew": {
            "title": "Only new posts",
            "type": "boolean",
            "description": "Skip the posts that a previous run (same **Memory key**) already delivered: they are not saved and not charged. Schedule the Actor (every hour, every day) to follow a brand or a topic: each run returns only what is new. First run = everything is new. An account (`fromUsers`, @account) stops after 20 posts in a row already delivered (pinned posts excepted).",
            "default": false
          },
          "stateKey": {
            "title": "Memory key",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$",
            "maxLength": 64,
            "type": "string",
            "description": "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 `_`.",
            "default": "default"
          },
          "resetState": {
            "title": "Reset the memory",
            "type": "boolean",
            "description": "Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every post again. Untick it afterwards.",
            "default": false
          },
          "maxSearchPagesPerKeyword": {
            "title": "Max search pages per keyword",
            "minimum": 3,
            "maximum": 2000,
            "type": "integer",
            "description": "Upper bound on the Threads search pages read for one keyword by **Deep search** (about 1 MB each). The search also stops by itself after several pages in a row without a new matching post.",
            "default": 300
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "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.",
            "default": {
              "useApifyProxy": true
            }
          },
          "maxConcurrency": {
            "title": "Max concurrency",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Maximum number of requests processed in parallel. With **Views**, each search page also reads the pages of its posts, up to 4 at once (never more than this number).",
            "default": 4
          },
          "maxRequestsPerMinute": {
            "title": "Max requests per minute",
            "minimum": 10,
            "maximum": 2000,
            "type": "integer",
            "description": "Rate of the search pages and API calls. The pages of the posts (views) and of the authors are read inside them and not counted here. Threads' pages are not limited per IP; its API is, whatever the speed: lowering this does not help.",
            "default": 120
          },
          "maxRequestRetries": {
            "title": "Max request retries",
            "minimum": 0,
            "maximum": 20,
            "type": "integer",
            "description": "Retries per request before it is marked as failed.",
            "default": 5
          },
          "debugLog": {
            "title": "Debug log",
            "type": "boolean",
            "description": "Include debug messages in the run log.",
            "default": false
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}