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.
| Item | What the documentation says |
|---|---|
| Endpoint | GET https://graph.threads.net/v1.0/keyword_search, only q is required |
| Permissions | threads_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 cap | 2,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 size | limit defaults to 25, maximum 100. The page describes no cursor for a next page |
| Ranking | search_type is TOP (default) or RECENT |
| Filters | search_mode (KEYWORD or TAG), media_type, since, until, author_username |
| Fields in the examples | id, text, media_type, permalink, timestamp, username, has_replies, is_quote_post, is_reply. View counts are not mentioned on that page |
| Sensitive terms | A 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
postsmode. - 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.