Quarra
Guide · Threads

Threads API keyword search: limits, permissions and alternatives

Meta's keyword search exists, and it comes with an approval, a daily cap and Meta's ranking. What the documentation says, a working request in Python, and what to do when that is not enough.

Checked against Meta's Threads API documentation on October 9, 2026.

The short answer

Yes, the official Threads API has keyword search, and it is the right tool if you can get the permission. It needs threads_keyword_search (until your app is approved it only searches your own posts), allows 2,200 queries per user per rolling 24 hours, returns at most 100 posts per request and ranks them its own way. If you need public posts without that approval, or want view counts and several wordings of the same topic, you can read the public search pages instead.

How the official keyword search works

These are the terms in Meta's keyword search documentation, which we read on October 9, 2026.

ItemWhat the documentation says
EndpointGET https://graph.threads.net/v1.0/keyword_search, only q is required
Permissionsthreads_basic and threads_keyword_search. Without approval for the second, search covers only posts owned by the authenticated user. After approval, public posts are searchable
Query cap2,200 queries per user in a rolling 24 hours, counted across all of that user's apps. Repeating a keyword counts again; a search that returns nothing does not count
Page sizelimit defaults to 25, maximum 100. The page describes no cursor for a next page
Rankingsearch_type is TOP (default) or RECENT
Filterssearch_mode (KEYWORD or TAG), media_type, since, until, author_username
Fields in the examplesid, text, media_type, permalink, timestamp, username, has_replies, is_quote_post, is_reply. View counts are not mentioned on that page
Sensitive termsA keyword Meta considers sensitive or offensive returns an empty array

A request in Python

import requests

r = requests.get(
    "https://graph.threads.net/v1.0/keyword_search",
    params={
        "q": "matcha",
        "search_type": "RECENT",
        "limit": 100,
        "fields": "id,text,media_type,permalink,timestamp,username,has_replies,is_quote_post,is_reply",
        "access_token": "<THREADS_ACCESS_TOKEN>",
    },
    timeout=30,
)
for post in r.json().get("data", []):
    print(post["username"], post["timestamp"], post["permalink"])

The access token comes from the usual Threads OAuth flow for your app, and you need a Meta developer app with the Threads use case. That setup is the part that takes time: the approval for threads_keyword_search is a review of your app, and until it comes through you only see your own posts.

Where the official search stops being enough

  • You cannot exhaust a topic: ranking is Meta's, there is no documented way to page past the first 100, and 2,200 queries a day is a ceiling for monitoring many keywords.
  • The fields in the documentation's examples carry no counters, and the page does not mention view counts. It points to the media documentation for other fields: check what your approved app can read before you plan a ranking on it.
  • The approval is tied to an app and a use case. A one-off research question or an agency monitoring many brands has to fit that frame.

Searching public Threads without an account

Threads also shows search results to a visitor who is not logged in. The Threads Scraper reads them for you: no token, no app review, no cookies. Give it keywords or hashtags in search mode:

{
  "mode": "search",
  "searchQueries": ["matcha", "#latteart"],
  "languages": ["en"],
  "minLikes": 5,
  "maxItems": 0
}

Each result is a post with its text, author, counters and, by default, its view count (viewCount, with viewsPerHour and engagementPerView). The row has the same fields as the posts of an account; our export guide shows one in full.

One wording gives one page, so the Actor searches several

Threads shows a logged-out visitor about 20 posts per wording, and different wordings return different posts. By default the Actor also searches the singular and plural, the joined word and the hashtag, and merges the results without duplicates. On “AI agents” it searched “AI agent”, “aiagents” and “#aiagents” as well and returned 104 and 120 unique posts in two runs, where the exact wording alone gave 31 and 33 (October 6, 2026). Turn that off with expandQueries: false, and keep only posts that contain all your words with strictSearch: true.

Only the new posts, every day

Add a name for the watch and schedule the Actor. The first run is a baseline, and each later run returns, and charges, only the posts that watch has not delivered before:

{
  "mode": "search",
  "searchQueries": ["matcha"],
  "watchName": "matcha-mentions",
  "languages": ["en"]
}

From Python

from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("quarra/threads-scraper").call(run_input={
    "mode": "search",
    "searchQueries": ["matcha", "#latteart"],
    "languages": ["en"],
    "minLikes": 5,
    "maxItems": 0,
})
for post in client.dataset(run.default_dataset_id).iterate_items():
    print(post["author"]["username"], post["likeCount"], post["viewCount"], post["url"])

Tested with apify-client 3.2. With apify-client 2.x, write run["defaultDatasetId"] instead of run.default_dataset_id.

Limits we know about

  • Search as a logged-out visitor has no pagination and no date filter, and the ranking varies by language and from day to day. Expanding the wording multiplies the results; it does not make them exhaustive. For a large study, collect the accounts that matter and use posts mode.
  • The language filter reads the text when Threads gives no language: in our tests it kept about 96% of English posts on the accounts we measured, and posts of one word are removed. Short texts are less reliable. A two or three word post that is mostly the keyword can be taken for the keyword's own language.
  • Account discovery by keyword (accountSearch) returns up to about 100 accounts per keyword.
  • Meta's terms and privacy law apply to how you use the data; the Actor reads what a visitor sees without logging in.

What it costs

A search result costs $2.50 per 1,000 on the Free and Starter plans, $2.00 on Scale and $1.75 on Business and above, view count included, plus $0.005 per run. Duplicates, filtered rows and errors are not charged. A watch checked every hour that finds nothing new costs $3.60 a month.

Run it on the Apify Store

Posts and search results cost $2.50 per 1,000 on the Free and Starter plans ($2.00 on Scale, $1.75 on Business and above), view counts included, plus $0.005 per run. Errors and empty results are not charged, and you can set a maximum cost per run.