Brave search
Input
query requiredSearch 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 optional0-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 optionalMeant 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 requiredHow 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 requiredoffset requiredresults requiredThe 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 requiredWhy `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 requiredWhether 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 optionalWhat 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'.
