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, and Brave does not say when you reach the end — it re-serves earlier pages. Measured: `site:semianalysis.com nvidia` returned identical lists at offset 1 and offset 3, while `site:rippletide.com` at offset 3 was still entirely new. So dedupe on url across pages and stop when a page adds nothing; never assume N pages means 20N results. 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
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'.

Start building not clicking