Retrieval API endpoint
Search Brave's public web results. limit (1-50, default 10) is honoured by reading up to 3 result pages; each successful result page read costs 3 credits, and optional page reads (5 credits each) remain scoped to each result host. country and language select the result locale (defaults us and en-us).
/web/searchSearches Brave's public web results and can read a bounded number of returned pages. Requires the x-api-key header. A response may contain partial coverage when the source fails; successful hits are retained, with any page-read failure included alongside its hit. Page reads remain within each selected result's public host scope.
Each result page read from the search source costs 3 credits, and a search reads up to 3 result pages (about 20 results each) to reach limit. A limit of up to 20 costs 3 credits, 21 to 40 up to 6, and 41 to 50 up to 9; only result pages that were read successfully are charged. If a later result page fails, the results already collected are returned with partial set to true and a source_failed warning, and only the successful pages are charged. Optional page reads from scrape are priced separately, at 5 credits each. The precheck reserves the worst case: result pages plus scrape_limit page reads, at most 34 credits.
Request body:
q: required, 1–1000 characters.limit: optional, 1–50 results; default 10. Up to limit results are returned by reading further result pages (about 20 results per page, at most 3 pages); fewer are returned when the source has no more distinct results. The effective maximum is also bounded by capabilities.country: optional. Result country; defaults to us. Allowed values: all, ar, at, au, be, br, ca, ch, cl, cn, de, dk, es, fi, fr, gb, gr, hk, id, in, it, jp, kr, mx, my, nl, no, nz, ph, pl, pt, ru, sa, se, sg, tr, tw, us, za. Example: us. An unknown value returns a 400 error before any search.language: optional. Result language; defaults to en-us. Allowed values: de-de, en-ca, en-gb, en-in, en-us, fi-fi, fr-ca, fr-fr, ja-jp, pt-br, sq-al, sw-ke, zh-tw. Example: en-us. An unknown value returns a 400 error before any search.include_domains, exclude_domains: optional, up to 20 unique hostnames each, at most 256 characters per value. The lists may not overlap.scrape: optional object with render, only_main_content, max_age, and wait_for fields. render values are auto, http, browser; auto is the default and uses the available HTTP reader in P1. Only auto and http are available; browser returns 503. only_main_content defaults to true. max_age is in milliseconds from 0 to 604800000, default 86400000; wait_for is in milliseconds from 0 to 10000, default 0, and is only valid with render=browser.scrape_limit: optional, 1–5 pages, default 3 when scraping is requested. Reject it when scrape is absent.max_credits: optional positive integer budget for result-page queries and page reads. It must cover at least one result page (3 credits). A result page that the budget cannot cover is not read; the response is then partial with a budget warning and returns the results already collected.Response enum values:
coverage[].status: ok, failed, not_indexed, unsupported.coverage[].failure.reason and items[].fetch_failure.reason: invalid_url, unsupported_content_type, blocked, not_found, rate_limited, timeout, upstream_error, internal_error, out_of_scope, robots_disallowed, duplicate, limit_reached, unsupported_filter, unknown_source, idempotency_conflict, invalid_cursor, result_expired, full_text_unavailable, budget_exhausted.warnings[].code: source_failed, source_not_indexed, discovery_truncated, ranking_window_limit, imprecise_date_excluded, content_unavailable, cached_source_stale.passages[].locator is descriptive; it has no enum fields.Example request:
{
"q": "Go context cancellation",
"limit": 5,
"country": "us",
"language": "en-us",
"scrape": {"render": "http"},
"scrape_limit": 2
}
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| request (body) | object | Yes | Search request |
curl -X POST "https://api.crawlora.net/api/v1/web/search" \
-H "x-api-key: $CRAWLORA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"country":"us","exclude_domains":["string"],"include_domains":["string"],"language":"en-us","limit":1,"max_credits":1,"q":"string","scrape":{"max_age":1,"only_main_content":true,"render":"auto","wait_for":1},"scrape_limit":1}'{
"country": "us",
"exclude_domains": [
"string"
],
"include_domains": [
"string"
],
"language": "en-us",
"limit": 1,
"max_credits": 1,
"q": "string",
"scrape": {
"max_age": 1,
"only_main_content": true,
"render": "auto",
"wait_for": 1
},
"scrape_limit": 1
}{
"code": 200,
"msg": "OK",
"data": {
"items": [
{
"rank": 1,
"url": "https://go.dev/blog/context",
"title": "Go Concurrency Patterns: Context",
"snippet": "Context carries deadlines and cancellation signals...",
"provider": "brave",
"retrieved_at": "2026-10-09T04:00:00Z"
}
],
"partial": false,
"coverage": [
{
"source_id": "brave",
"status": "ok",
"retrieved_at": "2026-10-09T04:00:00Z"
}
],
"usage": {
"search_requests": 1,
"fetch_attempts": 0,
"fetched_urls": 0,
"browser_renders": 0,
"input_tokens": 0,
"output_tokens": 0,
"credits_reserved": 0,
"credits_charged": 3,
"credits_released": 0,
"settlement_pending": false
},
"warnings": []
}
}Request schema
#/definitions/retrievalplatform.WebSearchRequest
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| country | string | No | all, ar, at, au, be, br, ca, ch, cl, cn, de, dk, es, fi, fr, gb, gr, hk, id, in, it, jp, kr, mx, my, nl, no, nz, ph, pl, pt, ru, sa, se, sg, tr, tw, us, za | us | Country is the result country; defaults to us. | |
| exclude_domains | array | No | ||||
| include_domains | array | No | ||||
| language | string | No | de-de, en-ca, en-gb, en-in, en-us, fi-fi, fr-ca, fr-fr, ja-jp, pt-br, sq-al, sw-ke, zh-tw | en-us | Language is the result language; defaults to en-us. | |
| limit | integer | No | Limit is the number of results to return, 1 to 50 (default 10). Up to 3 result pages are read to reach it, at 3 credits per page read. | |||
| max_credits | integer | No | ||||
| q | string | Yes | ||||
| scrape | retrievaltypes.FetchOptions | No | ||||
| scrape.max_age | integer | No | ||||
| scrape.only_main_content | boolean | No | ||||
| scrape.render | retrievaltypes.RenderMode | No | auto, http, browser | |||
| scrape.wait_for | integer | No | ||||
| scrape_limit | integer | No |
Response schema
Inline response schema
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | Code is the HTTP status code or a custom code used to indicate the result of the request @example 200 | |||
| data | retrievalplatform.WebSearchResponse | No | ||||
| data.coverage | array | No | ||||
| data.coverage[].corpus_revision | string | No | ||||
| data.coverage[].failure | retrievaltypes.Failure | No | ||||
| data.coverage[].failure.message | string | No | ||||
| data.coverage[].failure.reason | retrievaltypes.FailureReason | No | invalid_url, unsupported_content_type, blocked, not_found, rate_limited, timeout, upstream_error, internal_error, out_of_scope, robots_disallowed, duplicate, limit_reached, unsupported_filter, unknown_source, idempotency_conflict, invalid_cursor, result_expired, full_text_unavailable, budget_exhausted | |||
| data.coverage[].failure.retry_after_seconds | integer | No | ||||
| data.coverage[].failure.retryable | boolean | No | ||||
| data.coverage[].indexed_at | string | No | ||||
| data.coverage[].retrieved_at | string | No | ||||
| data.coverage[].source_id | string | No | ||||
| data.coverage[].status | retrievaltypes.CoverageStatus | No | ok, failed, not_indexed, unsupported | |||
| data.items | array | No | ||||
| data.items[].document | retrievaltypes.Document | No | ||||
| data.items[].document.content_sha256 | string | No | ||||
| data.items[].document.content_type | string | No | ||||
| data.items[].document.document_id | string | No | ||||
| data.items[].document.fetched_at | string | No | ||||
| data.items[].document.final_url | string | No | ||||
| data.items[].document.links | array | No | ||||
| data.items[].document.markdown | string | No | ||||
| data.items[].document.metadata | retrievaltypes.DocumentMetadata | No | ||||
| data.items[].document.metadata.author | string | No | ||||
| data.items[].document.metadata.description | string | No | ||||
| data.items[].document.metadata.language | string | No | ||||
| data.items[].document.metadata.modified_at | string | No | ||||
| data.items[].document.metadata.published_at | string | No | ||||
| data.items[].document.metadata.title | string | No | ||||
| data.items[].document.passages | array | No | ||||
| data.items[].document.passages[].locator | retrievaltypes.PassageLocator | No | ||||
| data.items[].document.passages[].locator.anchor | string | No | ||||
| data.items[].document.passages[].locator.end_byte | integer | No | ||||
| data.items[].document.passages[].locator.end_line | integer | No | ||||
| data.items[].document.passages[].locator.heading | string | No | ||||
| data.items[].document.passages[].locator.page | integer | No | ||||
| data.items[].document.passages[].locator.start_byte | integer | No | ||||
| data.items[].document.passages[].locator.start_line | integer | No | ||||
| data.items[].document.passages[].passage_id | string | No | ||||
| data.items[].document.passages[].score | number | No | ||||
| data.items[].document.passages[].text | string | No | ||||
| data.items[].document.revision | string | No | ||||
| data.items[].document.source_url | string | No | ||||
| data.items[].document.truncated | boolean | No | ||||
| data.items[].fetch_failure | retrievaltypes.Failure | No | ||||
| data.items[].fetch_failure.message | string | No | ||||
| data.items[].fetch_failure.reason | retrievaltypes.FailureReason | No | invalid_url, unsupported_content_type, blocked, not_found, rate_limited, timeout, upstream_error, internal_error, out_of_scope, robots_disallowed, duplicate, limit_reached, unsupported_filter, unknown_source, idempotency_conflict, invalid_cursor, result_expired, full_text_unavailable, budget_exhausted | |||
| data.items[].fetch_failure.retry_after_seconds | integer | No | ||||
| data.items[].fetch_failure.retryable | boolean | No | ||||
| data.items[].provider | string | No | ||||
| data.items[].rank | integer | No | ||||
| data.items[].retrieved_at | string | No | ||||
| data.items[].snippet | string | No | ||||
| data.items[].title | string | No | ||||
| data.items[].url | string | No | ||||
| data.partial | boolean | No | ||||
| data.usage | retrievaltypes.Usage | No | Usage record, 10 fields: browser_renders, credits_charged, credits_released, credits_reserved, fetch_attempts, fetched_urls, input_tokens, output_tokens, search_requests, settlement_pending. Described under Map a public website API. | |||
| data.warnings | array | No | ||||
| data.warnings[].code | retrievaltypes.WarningCode | No | source_failed, source_not_indexed, discovery_truncated, ranking_window_limit, imprecise_date_excluded, content_unavailable, cached_source_stale | |||
| data.warnings[].message | string | No | ||||
| data.warnings[].source_id | string | No | ||||
| msg | unknown | No | Msg is the message that describes the result of the request @example "Request successful" |
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 401 | Unauthorized | #/definitions/app.Response |
| 402 | Payment Required | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 500 | Internal Server Error | #/definitions/app.Response |
| 503 | Service Unavailable | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X POST "https://api.crawlora.net/api/v1/web/search" \
-H "x-api-key: $CRAWLORA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"country":"us","exclude_domains":["string"],"include_domains":["string"],"language":"en-us","limit":1,"max_credits":1,"q":"string","scrape":{"max_age":1,"only_main_content":true,"render":"auto","wait_for":1},"scrape_limit":1}'