{
  "openapi": "3.0.1",
  "info": {
    "title": "Threads Scraper & Threads Keyword Monitor",
    "description": "Threads scraper and Threads keyword monitor, no login. Scrape Threads posts by keyword or #hashtag (deep search with date range), plus Threads profiles, replies, reposts and media. Find Threads influencers: follower counts, emails, phones and links from bios. JSON, CSV, Excel. $1.99 per 1,000 posts.",
    "version": "0.1",
    "x-build-id": "7B5EGAEHu4CrehsNZ"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/reportable_broth~threads-scraper-monitor/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-reportable_broth-threads-scraper-monitor",
        "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/reportable_broth~threads-scraper-monitor/runs": {
      "post": {
        "operationId": "runs-sync-reportable_broth-threads-scraper-monitor",
        "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/reportable_broth~threads-scraper-monitor/run-sync": {
      "post": {
        "operationId": "run-sync-reportable_broth-threads-scraper-monitor",
        "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",
            "type": "array",
            "description": "Keywords or #hashtags to search on Threads. By default each returns the ~20 freshest public posts per sort mode (ideal for scheduled monitoring). Set Max posts per keyword or a date range below to go deeper. Leave empty if you only want profiles.",
            "items": {
              "type": "string"
            }
          },
          "usernames": {
            "title": "Usernames (profile scrape)",
            "type": "array",
            "description": "Threads usernames (with or without @) to scrape ALL public posts from, paginating through history. No login needed.",
            "items": {
              "type": "string"
            }
          },
          "maxPostsPerProfile": {
            "title": "Max posts per profile",
            "minimum": 1,
            "type": "integer",
            "description": "Stop paginating a profile after this many posts. Each post is charged once.",
            "default": 100
          },
          "profileTabs": {
            "title": "Profile tabs to also scrape",
            "type": "array",
            "description": "Extra tabs to pull for each account in Usernames. Replies = replies this account wrote (only their own replies are returned, not the posts they replied to). Reposts = what this account reposted. Media = their posts with images or video. Anonymous access returns the first page of each tab. An empty result is normal for accounts that simply do not repost or reply publicly.",
            "items": {
              "type": "string",
              "enum": [
                "replies",
                "reposts",
                "media"
              ],
              "enumTitles": [
                "Replies",
                "Reposts",
                "Media (image / video posts)"
              ]
            },
            "default": []
          },
          "profileDetails": {
            "title": "Profile details (followers, bio, email, phone, links)",
            "type": "boolean",
            "description": "For each account in Usernames, also return one record with follower count, bio, bio links, verified badge, and any emails, phone numbers and links found in the bio. Parsed from the profile page that is already loaded, so it adds no extra requests and is not charged. Look for items with _source = profile_info.",
            "default": false
          },
          "postUrls": {
            "title": "Post URLs (get replies)",
            "type": "array",
            "description": "Threads post URLs, e.g. https://www.threads.com/@user/post/ABC123. Returns the post plus its replies. Logged-out visitors only see the first page of replies (usually 10-20), so that's what you get. Each row is charged as one post.",
            "items": {
              "type": "string"
            }
          },
          "maxRepliesPerPost": {
            "title": "Replies per post URL",
            "minimum": 0,
            "maximum": 10000,
            "type": "integer",
            "description": "How many replies to get for each post URL. 0 = first page only (about 10-20, the old behavior). Higher numbers page through all replies - no login needed. Each reply is billed as one post.",
            "default": 0
          },
          "replySort": {
            "title": "Reply order",
            "enum": [
              "top",
              "recent"
            ],
            "type": "string",
            "description": "Order of replies when paging past the first page.",
            "default": "top"
          },
          "includeAuthorThread": {
            "title": "Include the author's own thread",
            "type": "boolean",
            "description": "When the author continued the post in a thread (1/5, 2/5 ...), also return those posts (_source = thread, with thread_index). Billed per post.",
            "default": false
          },
          "startUrls": {
            "title": "Any Threads URLs",
            "type": "array",
            "description": "Paste any Threads links and each is routed automatically: profile URL (threads.com/@user) → profile scrape, profile tab URL (threads.com/@user/reposts, /replies, /media) → that tab only, post URL → post + replies, search URL (threads.com/search?q=...) → keyword search, hashtag URL (search?q=...&serp_type=tags or /tag/...) → hashtag search. threads.net and threads.com both work; malformed links are skipped with a warning.",
            "items": {
              "type": "string"
            }
          },
          "modes": {
            "title": "Sort modes",
            "type": "array",
            "description": "recent = newest posts (best for monitoring). top = Threads' relevance ranking. tags = hashtag search.",
            "items": {
              "type": "string",
              "enum": [
                "recent",
                "top",
                "tags"
              ],
              "enumTitles": [
                "Recent (newest first)",
                "Top (relevance)",
                "Tags (#hashtag)"
              ]
            },
            "default": [
              "recent"
            ]
          },
          "expandQueries": {
            "title": "Expand each keyword",
            "minimum": 0,
            "maximum": 5,
            "type": "integer",
            "description": "Also search up to this many related searches people actually type (e.g. 'nike' -> 'nike shoes', 'nike air max'). Rows from expanded searches have expanded_from set. 0 = off. Monitor memory still follows your original keywords.",
            "default": 0
          },
          "maxPostsPerKeyword": {
            "title": "Max posts per keyword (deep search)",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "20 = classic mode: one quick page of the freshest posts per keyword and sort mode (set it lower, e.g. 5, to get and pay for fewer). Set higher (up to 10,000) to switch on deep search, which walks back through time window by window to collect many more posts. Without a Start date, deep search looks back 30 days. Threads shows a handful of posts per hour of history (roughly 2-15 depending on the keyword), so this is a ceiling, not a promise.",
            "default": 20
          },
          "startDate": {
            "title": "Start date",
            "type": "string",
            "description": "Only posts from this date onward (UTC). YYYY-MM-DD, or relative like '7 days', '24 hours', '30 minutes', '3 months'. Setting a date range switches on deep search, so older posts are reachable, not only the latest 20."
          },
          "endDate": {
            "title": "End date",
            "type": "string",
            "description": "Only posts up to this date (inclusive, UTC). YYYY-MM-DD or relative like '1 month'. Empty = now."
          },
          "fromAuthor": {
            "title": "Only posts by this account",
            "type": "string",
            "description": "Optional. Search your keywords inside one account's posts only, e.g. 'zuck' + keyword 'AI' = everything @zuck wrote about AI. Works with dates."
          },
          "searchLanguage": {
            "title": "Result language",
            "enum": [
              "en",
              "zh-TW",
              "zh-CN",
              "ja",
              "ko",
              "th",
              "vi",
              "id",
              "ms",
              "tl",
              "es",
              "pt",
              "fr",
              "de",
              "it",
              "ar",
              "ru",
              "tr",
              "hi"
            ],
            "type": "string",
            "description": "Which language the results should lean towards. Many keywords are used by people writing in several languages and Threads mixes them together; picking a language here biases the result set towards it.\n\nThis is a preference, not a hard filter — a keyword only one language uses will return that language whatever you pick. Every post also carries a detected `language` field in the output, which you can filter on.",
            "default": "en"
          },
          "findAccounts": {
            "title": "Also return the accounts talking about your keywords",
            "type": "boolean",
            "description": "Adds account records to the dataset, aggregated from the posts found: who posts about your keywords, how many matching posts each has, and their total engagement. Useful for finding creators, KOLs and prospects. These records are NOT charged separately - they are a summary of posts you already paid for. Look for items with _source = account.",
            "default": false
          },
          "accountDetails": {
            "title": "Account details for the top N accounts",
            "minimum": 0,
            "maximum": 200,
            "type": "integer",
            "description": "When 'Also return the accounts' is on, enrich the top N accounts (most matching posts first) with follower count, bio, bio links, and emails / phone numbers / links found in the bio - useful for influencer outreach and lead lists. Each account needs one extra page load. 0 turns it off. Not charged separately.",
            "default": 20
          },
          "searchAccounts": {
            "title": "Search accounts by keyword",
            "type": "boolean",
            "description": "Also run Threads' account search (the Profiles tab) for each keyword: username, name, bio, followers, verified. Returns up to about 50 accounts per keyword, free of charge (_source = account_search).",
            "default": false
          },
          "maxAccountsPerKeyword": {
            "title": "Accounts per keyword",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "For 'Search accounts by keyword'.",
            "default": 20
          },
          "onlyNew": {
            "title": "Only return posts not seen in previous runs",
            "type": "boolean",
            "description": "Keeps a per-task memory of post IDs (7 days). Turn on for scheduled monitoring so every run yields only NEW posts. Turn off to always get the full ~20 per keyword.",
            "default": true
          },
          "maxAgeHours": {
            "title": "Max post age (hours)",
            "minimum": 0,
            "type": "integer",
            "description": "Drop posts older than this. 0 = no limit.",
            "default": 0
          },
          "minLikes": {
            "title": "Minimum likes",
            "minimum": 0,
            "type": "integer",
            "description": "Drop posts with fewer likes. 1 removes the zero-engagement filler that keyword search often returns. Dropped posts are not charged and not remembered, so they can still come back in a later run once they gain likes.",
            "default": 0
          },
          "minReplies": {
            "title": "Minimum replies",
            "minimum": 0,
            "type": "integer",
            "description": "Drop posts with fewer replies. Not charged.",
            "default": 0
          },
          "minReposts": {
            "title": "Minimum reposts",
            "minimum": 0,
            "type": "integer",
            "description": "Drop posts with fewer reposts. Not charged.",
            "default": 0
          },
          "filterKeywords": {
            "title": "Keep only posts containing",
            "type": "array",
            "description": "Case-insensitive words or phrases; a post is kept when its text, hashtags or topic tag contain ANY of them (English words match whole words, so 'AI' does not match 'email'). Works for every source (search, profiles, replies). Empty = keep everything. Dropped posts are not charged.",
            "items": {
              "type": "string"
            }
          },
          "strictKeywordMatch": {
            "title": "Only posts that actually mention the keyword",
            "type": "boolean",
            "description": "Threads search is loose and mixes in related posts that never mention your keyword. Turn this on to keep only search results whose text, hashtags or topic tag contain your keyword (English keywords match whole words; multi-word keywords match as a phrase, without spaces like #iPhone17, or with every word present). Same logic as the keyword_match field. Dropped posts are not charged.",
            "default": false
          },
          "languages": {
            "title": "Keep only these languages",
            "type": "array",
            "description": "ISO codes: en, zh, ja, ko, th, vi, id, ms, tl, es, pt, fr, de, it, tr, ar, ru, hi, he, el. Keeps only posts whose detected language field matches. Unlike Result language (a soft preference), this is a hard filter; posts whose language cannot be detected (emoji-only, very short) are dropped. zh covers both Traditional and Simplified; ru covers Cyrillic-script languages (e.g. Ukrainian) and ar covers Arabic-script languages (e.g. Persian, Urdu). Unsupported codes are ignored with a warning. Not charged.",
            "items": {
              "type": "string"
            }
          },
          "maxItems": {
            "title": "Maximum posts per run",
            "minimum": 0,
            "type": "integer",
            "description": "Stop after delivering this many posts in total across all keywords, usernames and URLs - a hard cap on what one run can cost. When the cap is hit, remaining searches are skipped (order is shuffled each run so every keyword gets its turn on schedules). The run also stops by itself if your platform 'max total charge' for the run is reached. 0 = no cap.",
            "default": 0
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Residential proxy recommended. Anonymous Threads pages are light (~50 KB per 20 posts), so proxy cost is negligible.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          },
          "concurrency": {
            "title": "Concurrency",
            "minimum": 1,
            "maximum": 16,
            "type": "integer",
            "description": "Parallel requests.",
            "default": 4
          },
          "cookie": {
            "title": "Your Threads cookie (only for views and follower lists)",
            "type": "string",
            "description": "Log in at threads.com, open DevTools > Network, copy the Cookie request header (must contain sessionid). A secondary account is recommended. Stored encrypted and only sent to Threads. Needs your own Threads cookie for now. If enough people use this, we will consider adding a no-cookie option (at an extra cost)."
          },
          "includeViews": {
            "title": "Add view counts",
            "type": "boolean",
            "description": "Adds view_count to every post returned (one extra request per post). Needs your own Threads cookie for now. If enough people use this, we will consider adding a no-cookie option (at an extra cost).",
            "default": false
          },
          "followListUsernames": {
            "title": "Get followers / following of these accounts",
            "type": "array",
            "description": "Usernames (without @). Returns one row per account in the list (_source = follower or following), free of charge. Threads shows only part of the follower list for very large accounts. Needs your own Threads cookie for now. If enough people use this, we will consider adding a no-cookie option (at an extra cost).",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "followListType": {
            "title": "Which list",
            "enum": [
              "followers",
              "following",
              "both"
            ],
            "type": "string",
            "description": "For 'Get followers / following'.",
            "default": "followers"
          },
          "maxFollowsPerUser": {
            "title": "Max accounts per list",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "For 'Get followers / following'.",
            "default": 100
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}