OpenWebSearch API
copy markdown
Use one API to query multiple web search providers. Choose a provider—or an
ordered fallback list—and receive results in one normalized response while the
original provider payload remains available under raw.
Base URL: https://api.openwebsearch.ai
Quickstart
Create an API key, save it as OPENWEBSEARCH_API_KEY, and send your first
search request.
export OPENWEBSEARCH_API_KEY="ows_..."Run your first search
fetch
const response = await fetch("https://api.openwebsearch.ai/v1/search", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENWEBSEARCH_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
provider: "exa",
query: "What changed in browser automation this week?",
max_results: 10,
}),
});
const { results, provider, usage } = await response.json();Authentication
Send your API key as a bearer token with every API request.
Authorization: Bearer YOUR_API_KEYAuthentication failures return a standard 401 error envelope.
Endpoints
| Method | Path | Description |
|---|---|---|
POST | /v1/search | Search through one provider or an ordered fallback list. |
GET | /v1/providers | Discover providers, result limits, and parameter support. |
Search request
Send a JSON body to POST /v1/search.
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | A non-empty search query. |
provider | string | Yes, unless providers is set | One provider slug. |
providers | string[] | Yes, unless provider is set | Ordered provider fallback list. Takes precedence over provider. |
allow_fallbacks | boolean | No | Enables fallback through providers. Defaults to true for lists with multiple entries. |
strict_params | boolean | No | Reject unsupported parameters instead of dropping them with a warning. Defaults to false. |
max_results | integer | No | Number of results. Defaults to 10 and is capped per provider. |
country | string | No | Two-letter ISO country code, such as "us". |
include_domains | string[] | No | Restrict results to these domains. |
exclude_domains | string[] | No | Exclude results from these domains. |
start_date | string | No | Earliest publication date in YYYY-MM-DD format. |
end_date | string | No | Latest publication date in YYYY-MM-DD format. |
recency | string | No | One of day, week, month, or year. |
safe_search | string | No | One of off, moderate, or strict. |
provider_options | object | No | Provider-native options keyed by provider slug. |
You must provide either provider or a non-empty providers list. Query
GET /v1/providers to discover the live provider slugs and supported
parameters.
Unified response
Every successful request returns the same top-level shape. The provider field
identifies the provider that actually served the request, including when a
fallback was used.
{
"id": "srch_req-3f0c...",
"provider": "exa",
"query": "browser automation",
"results": [
{
"title": "Browser automation in 2026",
"url": "https://example.com/browser-automation",
"snippet": "A look at what changed across headless browsers this year.",
"content": "Full page content when available.",
"published_date": "2026-08-02",
"score": 0.91,
"source": "example.com",
"raw": {}
}
],
"usage": {
"cost": 0.007,
"results_count": 1
},
"warnings": []
}Result fields
| Field | Type | Description |
|---|---|---|
title | string or null | Result title. |
url | string | Canonical result URL. |
snippet | string or null | Short excerpt or description. |
content | string or null | Full text when supplied by the provider. |
published_date | string or null | Provider-supplied publication date. Never fabricated. |
score | number or null | Provider-supplied relevance score. Never fabricated. |
source | string or null | Domain or source name. |
raw | any | Original untouched provider result. |
usage.cost is the USD cost of the request and usage.results_count is the
number of normalized results returned.
Provider selection and fallback
Set provider for a single-provider request:
fetch
const response = await fetch("https://api.openwebsearch.ai/v1/search", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENWEBSEARCH_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
query: "latest advances in fusion energy",
provider: "brave",
max_results: 5,
}),
});Set providers for an ordered fallback chain:
fetch
const response = await fetch("https://api.openwebsearch.ai/v1/search", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENWEBSEARCH_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
query: "latest advances in fusion energy",
providers: ["exa", "perplexity", "brave"],
allow_fallbacks: true,
max_results: 5,
}),
});The gateway returns the first successful response. It tries the next provider when a provider returns no results, times out, or has a transient failure. Invalid requests stop immediately and do not trigger fallback. Results from multiple providers are never blended.
Provider capabilities
Not every provider supports every filter in the same way. Each unified parameter has one of three support levels:
| Level | Meaning |
|---|---|
native | The provider supports the parameter directly. |
emulated | OpenWebSearch translates or approximates the parameter. |
unsupported | The provider cannot honor the parameter. |
Use capability discovery before choosing a provider or fallback order:
fetch
const response = await fetch("https://api.openwebsearch.ai/v1/providers", {
headers: {
Authorization: `Bearer ${process.env.OPENWEBSEARCH_API_KEY}`,
},
});
const { providers } = await response.json();{
"providers": [
{
"slug": "brave",
"max_results_cap": 20,
"params": {
"country": "native",
"include_domains": "emulated",
"exclude_domains": "emulated",
"start_date": "emulated",
"end_date": "emulated",
"recency": "native",
"safe_search": "native"
}
}
]
}By default, unsupported parameters are dropped and reported in warnings.
Set strict_params: true to return a 400 instead.
Supported providers
OpenWebSearch supports Exa, Tavily, Brave, Bing, Perplexity, Interfaze,
Parallel, Apify Serp, Valyu, and Octen. Use GET /v1/providers as the source
of truth for current slugs, limits, and capabilities.
Provider-specific options
Use provider_options when you need a native provider feature that is not part
of the unified schema. These fields are passed to that provider and can
override gateway defaults.
fetch
const response = await fetch("https://api.openwebsearch.ai/v1/search", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENWEBSEARCH_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
query: "transformer architecture",
provider: "exa",
provider_options: {
exa: {
type: "neural",
contents: { text: true, highlights: true },
},
},
}),
});Provider-specific options are intentionally not portable. Keep them scoped under the matching provider slug.
Warnings
Non-fatal adjustments are returned in warnings[].
| Code | Meaning |
|---|---|
param_unsupported | The provider cannot honor a requested parameter, so it was dropped. |
max_results_clamped | max_results exceeded the provider limit and was reduced. |
domains_truncated | A translated domain-filter expression exceeded the provider limit. |
recency_emulated | recency was converted into a concrete date range. |
domain_filter_conflict | The provider cannot apply include and exclude lists together. |
Errors
All errors use the same envelope:
{
"error": {
"message": "Human-readable description",
"type": "invalid_request_error",
"code": "invalid_request",
"param": "query",
"provider": "exa",
"request_id": "req-3f0c..."
}
}| HTTP status | Type | Typical cause |
|---|---|---|
400 | invalid_request_error | Invalid JSON, parameters, dates, or provider. |
401 | authentication_error | Missing or invalid API key. |
403 | permission_error | The project cannot make the request. |
429 | rate_limit_error | Rate limit exceeded. |
502 | provider_error | A provider failed or all fallbacks were exhausted. |
500 | internal_error | Unexpected API error. |
When relevant, errors include param and provider. Supply an x-request-id
header to use your own request identifier; otherwise OpenWebSearch generates
one.
Rate limits
Responses include X-RateLimit-Limit, X-RateLimit-Remaining, and
X-RateLimit-Reset. A 429 response also includes Retry-After.
More examples
Filters with strict parameter handling
fetch
const response = await fetch("https://api.openwebsearch.ai/v1/search", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENWEBSEARCH_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
query: "transformer architecture",
provider: "exa",
max_results: 3,
include_domains: ["arxiv.org"],
start_date: "2024-01-01",
strict_params: true,
}),
});