App Logo
search.brave.com

Brave search

Search the web on Brave, one page of results at a time. Returns each result's title, url, snippet and date, plus the query it actually ran. An empty result list always means Brave itself reported nothing for the query, and the reason is returned alongside it — the script raises an error rather than quietly returning nothing when the page cannot be read, so an empty answer can be trusted as a fact about the query. Search operators (site:, quoted phrases, OR) are honored. site:domain also covers subdomains, and site:domain/path narrows to a path prefix. When too few pages match, Brave drops the operators and answers a looser query instead; the result says so, and those results should not be treated as filtered. For coverage questions, site:domain on its own is a ranked sample rather than a full inventory — add search terms, and judge by whether real articles come back or just homepages and section pages. Paging deeper does not enumerate a domain either: the pool behind a single query is finite and Brave re-serves earlier pages once it runs out, so dedupe results by url, stop when a page adds nothing new, and widen coverage with more query strings rather than more pages. Brave sometimes shows a rate-limit challenge; the script clears it automatically, and if it persists it raises an error — wait 30-60 seconds before retrying.

Input

query required

Search query. Operators site:/""/OR are honored. NOTE `site:domain` also covers its SUBDOMAINS (site:example.com returns docs.example.com), and `site:domain/path` narrows to a path prefix — the cheapest way to slice a large site.

offset optional

0-based page index (0 = first page, ~20 results). The pool behind one query string is FINITE and its depth varies by query; past its end Brave re-serves earlier pages (measured: `site:reduck.ai` at offset 4 returned offset 2's list). `hasMore` in the output is Brave's own word on whether a next page exists — page while it is true, and dedupe on url anyway. Default 0.

exactMatch optional

Meant to force the literal query by clicking Brave's 'Search instead for' link. MEASURED NO-OP — do not rely on it. On three typo'd queries (2026-08-08) Brave returned results for the CORRECTED spellings while offering no such link and reporting rewrittenTo null, so the flag did nothing and said nothing about it. It can only work when Brave ANNOUNCES a rewrite, which it appears to have stopped doing for spelling corrections. To pin a literal string, quote it in `query` instead. Default false.

Output

count required

How many result cards were extracted from THIS page — literally results.length. NOT a match count and NOT an estimate of what Brave holds for the query; there is no such number on the page. A full page reads ~16-20.

query required
offset required
hasMore required

Whether Brave offers a next page for this query — its pager's next-page control, enabled or disabled. false on a pool's last page and on an empty answer. This is the end-of-pool signal: page while true, dedupe on url regardless, because the last page can repeat an earlier one.

results required

The page's organic web results, in rank order. EMPTY ONLY WHEN BRAVE SAID SO — see `emptyBecause`. If this script reads zero rows off a page that Brave answered normally it THROWS instead of returning [], because a silent empty is indistinguishable from a real one to any schema and would be read as 'the domain has nothing on this topic'.

emptyBecause required

Why `results` is empty, in Brave's own terms — and null whenever `results` is non-empty. One of: the operators were relaxed (too few documents matched them), Brave's no-matches banner, or its no-results message. This is what makes an empty answer READABLE: an empty set is a fact about the query, never a scraper failure, because the failure case throws.

operatorsApplied required

Whether Brave honored the operators in `query`. false = Brave found too few matching documents, dropped the operators and answered a RELAXED query instead (it shows a 'search operators were not applied — Too few matches were found' banner): `results` are then soft relevance over the whole web, NOT filtered, so treat them as empty for any hard-filter use such as a site: coverage check. ONLY MEANINGFUL WHEN `query` CONTAINS AN OPERATOR — for an operator-free query it is vacuously true. Detected language-independently via the banner's /help/operators link, with the English sentence as a fallback; either signal reports false, so it errs toward warning you.

rewrittenTo optional

What Brave actually searched if it ANNOUNCED an auto-rewrite, else null. Read off the English 'Showing results for' line, so it stays null on a localized SERP — and also, measured, when Brave silently corrects a typo and announces nothing. null therefore means 'no rewrite was announced', never 'the literal query was searched'.

FAQ

Search the web on Brave, one page of results at a time. Returns each result's title, url, snippet and date, plus the query it actually ran.
Required: query. Optional: offset, exactMatch.
It returns count, query, offset, hasMore, results, rewrittenTo, emptyBecause, operatorsApplied.
No. It only uses pages of search.brave.com that are reachable without signing in.
It only reads. It looks things up on search.brave.com and changes nothing there.
Ask an AI agent connected to Reduck to run reduck/search.brave.com/search, or run it from a terminal with the Reduck CLI: npx @reduck-ai/cli@latest run --script reduck/search.brave.com/search
It is part of Reduck's official curated catalogue.

Start building not clicking