Comparing Brave Search Across Countries? Start With Matched Samples.
Before calling a Brave result difference geographic, pair the same query and settings across countries close together in time. Compare URL and host overlap at equal usable depth, and flag a short side as incomplete. One pair is a sample, not every searcher’s view.
I founded Serpent API, so this is an affiliated guide to its country and organic-result fields. The numerical example is illustrative, not an authenticated parsed run of these queries. Brave also publishes country codes for its own API; compare the two contracts on your use case.
Design a fair country pair
Choose a decision that needs geographic context, such as which sites appear for a product category in the US versus the UK. Write down the country pair and query list before collecting. Do not compare “running shoes” in one country with “trainers” in another if you intend to isolate the country parameter.
Run both country requests close together, with the same num, language and safe setting. Preserve each organic row with position and URL. Compute URL overlap and domains unique to each country. Review the pages behind country-specific results before labeling localization; a global page can appear in one sample by chance.
Save both result lists at equal depth
The Serpent web contract uses two-letter country codes and does not offer city-level targeting. Brave’s official Search API also documents country codes, but its response shape and locale controls have to be mapped separately. Country input is a setting, not a guarantee of complete local coverage.
| Field or control | Use in this workflow | Check before trusting it |
|---|---|---|
q, engine, country | Preserve the exact request identity. | Compare only samples with intended matching settings. |
results.organic[] | Read url, title and position from each usable row. | Validate array and row types; a position is an observed list location. |
num and returned count | Keep requested depth separate from usable rows. | Requested results are best-effort; never fill missing rows with invented values. |
delivery, meta.partialResults | Mark short or incomplete observations for review. | Inspect these before interpreting a missing URL as a change. |
Collect paired Brave samples
Install requests and set SERPENT_API_KEY in your local environment. This complete Python example shows the request and parsed-field handling for the workflow. It has been syntax-checked locally, but the sample query output has not been validated against an authenticated production response. Run it against your account before adopting it.
import os
from datetime import datetime, timezone
from urllib.parse import urlsplit, urlunsplit, parse_qsl, urlencode
import requests
BASE = "https://apiserpent.com"
KEY = os.environ["SERPENT_API_KEY"]
def snapshot(engine, query, country="us", num=10, deep=False):
endpoint = "/api/search" if deep else "/api/search/quick"
response = requests.get(
BASE + endpoint,
params={"engine": engine, "q": query, "country": country,
"num": num, "format": "full"},
headers={"X-API-Key": KEY}, timeout=55 if deep else 30)
response.raise_for_status()
data = response.json()
if data.get("success") is not True or not isinstance(data.get("results"), dict):
raise ValueError("No usable results object")
rows = data["results"].get("organic")
if not isinstance(rows, list):
raise ValueError("Organic rows are missing")
return {"observed_at": datetime.now(timezone.utc).isoformat(),
"query": query, "country": country, "engine": engine,
"requested": num, "organic": rows,
"delivery": data.get("delivery"),
"partial": (data.get("meta") or {}).get("partialResults")}
def normalized_url(raw):
if not isinstance(raw, str) or not raw.startswith(("https://", "http://")):
return None
parts = urlsplit(raw)
host = (parts.hostname or "").lower().removeprefix("www.")
path = parts.path.rstrip("/") or "/"
query = urlencode(sorted((k, v) for k, v in parse_qsl(parts.query)
if not k.lower().startswith("utm_")))
return urlunsplit((parts.scheme.lower(), host, path, query, ""))
query = "running shoe stores"
left = snapshot("brave", query, country="us", num=20)
right = snapshot("brave", query, country="gb", num=20)
def url_set(sample):
return {key for row in sample["organic"] if isinstance(row, dict)
if (key := normalized_url(row.get("url")))}
us, gb = url_set(left), url_set(right)
print({"query": query,
"us": {"returned": len(left["organic"]), "delivery": left["delivery"]},
"gb": {"returned": len(right["organic"]), "delivery": right["delivery"]},
"shared_urls": sorted(us & gb),
"us_only_urls": sorted(us - gb), "gb_only_urls": sorted(gb - us),
"sampled_at": [left["observed_at"], right["observed_at"]]})
How to read the output: This code compares exact normalized URLs. For a domain comparison, extract each URL’s hostname first, then compare those sets separately. Never call the country-only set “exclusive to that country” without a broader observation period; it means only that the URL appeared on one side of this pair.
Budget the repeated pairs
Ten queries across two countries once a week for four weeks use 10 × 2 × 4 = 80 Quick calls. At the documented Serpent Default rate of $0.60 per 1,000 Web calls, metered usage is $0.048. Deep requests bill per requested page. Brave’s official plan lists $5 per 1,000 requests and $5 monthly credits as of October 5, 2026; direct unit cost is only one part of the decision.
Serpent’s published pricing gives Web-category rates by account tier. The figures above use the documented Default rate as a dated planning example, not a measured invoice. Confirm your tier, optional features and actual charges in your account before scaling. A response with fewer rows does not by itself change the requested-page unit for Deep.
Compare direct and shared API contracts
| Option | Useful for | Published access or billing unit | Decision |
|---|---|---|---|
| Brave Search API | Official direct Brave search with documented country codes. | $5/1,000 Search requests and $5 monthly credits listed October 5, 2026. | Best for an official Brave-only client that can map its response. |
| Serpent Brave Quick | Shared organic schema for paired country snapshots. | One Web unit per Quick request; Default $0.60/1,000. | Useful across engines; confirm parsed country behavior with your queries. |
| Manual Brave Search | Visual spot check with interface context. | Human time. | Use for explaining a surprising country-specific page. |
Where can a country comparison go wrong?
The sample pair does not control a searcher’s exact city, language preferences or history. If one side returns fewer rows, the apparent URL overlap can be misleading; report requested and returned counts first. Repeat on several dates before using drift to make content or market decisions. No country comparison here is a measured production benchmark.
Calculate overlap with a stated denominator
Run the two country requests near one another and save their individual UTC times. Compare only pairs with the same query text, endpoint, requested depth and other supported settings. A country difference is an observation in two returned lists; the requests do not isolate the reason a ranking changed, and they do not represent every searcher in either country.
| Illustrative pair | Calculation | Defensible reading |
|---|---|---|
| US: 20 returned, UK: 20 returned; 12 normalized URLs shared | 12 shared URLs ÷ 28 distinct URLs = 42.9% Jaccard overlap. | The two sampled URL sets differ; review the eight URLs unique to each list. |
| US: 20 returned, UK: 9 returned | Keep both returned counts beside any overlap. | The unequal depth weakens a country comparison; do not call eleven US-only URLs region-exclusive. |
| Same domain, different landing URLs | Compare URL overlap and host overlap separately. | A low URL overlap may coexist with similar publisher coverage. |
The first row is invented arithmetic for a method demonstration, not a Brave measurement. Recheck a surprising URL in the Brave interface and repeat the pair on another date. If your decision concerns market-specific competitors, manually label useful country-specific pages; a set-overlap score alone cannot tell whether a difference matters to users.
Before you call a difference geographic
- Pair one fixed query set across two country codes and keep every other documented request setting the same.
- Save returned URL, domain, position, requested and returned counts for each country and UTC observation time.
- Compare exact URLs and distinct domains separately, and inspect a few country-specific changes in the Brave interface.
- Describe only the observed sample difference; rerun before claiming a durable regional pattern.
Try one paired country comparison
Start with the few queries that drive a real decision. Save the returned rows and their limits before increasing the schedule.
Get an API keyFAQ
Does country=us reproduce every US searcher’s results?
No. It is a country-level request setting, not a user-specific or city-level simulation.
How should I compare result sets?
Compare normalized URLs and distinct domains separately, while retaining original positions and query settings.
Is one paired run enough to claim localization?
No. Repeat at different times, inspect returned counts and review the pages before assigning a cause.
How do Brave’s API and Serpent billing units differ?
The official plan prices Search requests; Serpent Quick uses one Web unit per call and Deep uses requested-page units. Compare output contracts as well as prices.





