# Search providers

> Requests are answered by Google by default. With engine=auto (or a per-key setting) SerpKite can fall back to Brave, Bing, Yahoo or DuckDuckGo when Google is unavailable, and always labels the engine that answered.

SerpKite is a Google SERP API, and **every request is answered by Google unless you say otherwise**. Behind each Google request, SerpKite already retries across its own proxy pools and fetch methods when one of them is blocked or slow. That failover is always on, costs you nothing extra, and never changes which search engine you get.

For workloads where *some* answer beats no answer (agents, chatbots, research tools), you can also let SerpKite fall back to other search engines when Google is blocked or times out. This is opt-in, per request or per key, and the response always says which engine produced it.

## The `engine` parameter

`engine` is accepted by [/v1/search](https://serpkite.com/docs/endpoints/search), [/v1/news](https://serpkite.com/docs/endpoints/news), [/v1/images](https://serpkite.com/docs/endpoints/images) and [/v1/videos](https://serpkite.com/docs/endpoints/videos):

| Value | What happens |
| --- | --- |
| `google` (default) | Google only. SerpKite fails over across its own proxy pools, never to another engine. |
| `auto` | Google first; if Google is blocked or times out, the next enabled fallback engine that serves this vertical answers. |
| `consensus` (search only) | Several independent engines in parallel, merged and ranked by agreement. See [Consensus mode](#consensus-mode). |
| One provider, e.g. `brave` | That provider only. |
| A list, e.g. `["google", "brave"]` | Only those providers, in SerpKite's route order. In a query string, send `engine=google,brave`. |

cURL:

```bash
curl https://api.serpkite.com/v1/search \
  -H "Authorization: Bearer $SERPKITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"q":"best espresso machine 2026","country":"us","engine":"auto"}'
```

TypeScript:

```ts
import { SerpKite } from "serpkite";

const sk = new SerpKite(); // reads SERPKITE_API_KEY
const res = await sk.search({ q: "best espresso machine 2026", country: "us", engine: "auto" });
console.log(res.results[0].title, res.meta.credits_used);
```

Python:

```python
from serpkite import SerpKite

sk = SerpKite()  # reads SERPKITE_API_KEY
res = sk.search("best espresso machine 2026", country="us", engine="auto")
print(res.results[0].title, res.meta.credits_used)
```

Go:

```go
package main

import (
	"context"
	"fmt"
	"log"

	serpkite "github.com/serpkite/serpkite-go"
)

func main() {
	ctx := context.Background()
	c := serpkite.NewClient() // reads SERPKITE_API_KEY
	res, err := c.Search(ctx, serpkite.SearchParams{Q: "best espresso machine 2026", Country: "us", Engine: serpkite.Engines("auto")})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res.Results[0].Title, res.Meta.CreditsUsed)
}
```

Parameter errors (a bad `country`, an unknown parameter) never trigger a fallback: they return `400` straight away. `auto` and `consensus` can't be combined with other values, and naming only providers that don't serve the endpoint (or aren't enabled) returns `400 invalid_request` with a link to this page.

## Which providers serve which verticals

| Provider | `engine` | `/v1/search` | `/v1/news` | `/v1/images` | `/v1/videos` | Other verticals | Notes |
| --- | --- | --- | --- | --- | --- | --- | --- |
| **Google** (default) | `google` | Yes | Yes | Yes | Yes | Yes, all | The default for every request. Every vertical and all Google-only blocks. |
| Brave Search | `brave` | Yes | Yes | Yes | Yes | No | Its own independent index. |
| Bing | `bing` | Yes | Yes | Yes | Yes | No | Microsoft's index. |
| Yahoo | `yahoo` | Yes | Yes | No | No | No | Results largely come from Bing's index. |
| DuckDuckGo | `duckduckgo` | Yes | Yes | Yes | Yes | No | Web results largely from Bing's index; news, images and videos from its own feeds. |
| Mojeek | `mojeek` | Yes | No | No | No | No | Web results only, from its own independent index. |
| Wikipedia | `wikipedia` | Yes | No | No | No | No | The best matching article, from Wikipedia's official API. A source for engine=consensus (or by name), never an auto fallback. |

Google is always available. The fallback engines are enabled per deployment, so `engine=auto` only uses the ones that are currently switched on, and the route can change as SerpKite adds or pauses providers. Verticals not listed for a fallback engine (maps, places, reviews, shopping, scholar, patents, autocomplete, lens) are answered by Google only: `engine=auto` simply uses Google there, and naming a fallback engine returns `400`.

## Honest labelling: `meta.engine` and `meta.route`

A result is never relabelled. `meta.engine` names the provider that actually produced it, and `meta.route` lists each provider attempt behind a fresh result, in order, with its outcome and duration:

```json
"request": { "endpoint": "search", "engine": "auto", "q": "best espresso machine 2026", "country": "us" },
"meta": {
  "request_id": "req_01J8ZK4M6Q2V7",
  "credits_used": 1,
  "cached": false,
  "engine": "brave",
  "route": [
    { "provider": "google", "outcome": "blocked", "ms": 2140 },
    { "provider": "brave", "outcome": "ok", "ms": 612 }
  ],
  "parse_quality": "ok",
  "latency_ms": 2790
}
```

- `request.engine` echoes what you asked for (`google`, `auto`, one provider or a list).
- `meta.route` outcomes include `ok`, `partial`, `empty`, `blocked`, `timeout` and `error`. SerpKite's own proxy pools are internal and never appear in the route.
- Cache hits have no `meta.route`. The cache never mixes providers: a Google-only request is only ever served a cached Google result.
- With `format: "markdown"` there is no `meta`; SerpKite's [response headers](https://serpkite.com/docs/response-headers) still carry the request ID and credits.

If you need Google specifically (rank tracking, SEO audits, anything that compares against google.com), keep the default and check `meta.engine` if you're unsure how a key is configured.

## What a fallback result lacks

Fallback engines map into the same response shape (`results` with `title`, `link`, `snippet`…), so your parser keeps working, but their pages simply don't have Google's extras:

- No knowledge graph, answer box, People Also Ask, top stories or local pack unless that engine has an equivalent block. Fields a provider doesn't have are absent or empty.
- Ranking, snippets and result counts come from that engine's own index, so positions are not comparable with Google's.
- `parse_quality` is judged per provider.

## Billing follows the provider

You pay for the provider that answered, and only for that one. Every provider currently costs the same credits as Google for the same request, so a fallback never costs more. Failed, blocked and empty attempts along the route are free, just like a failed Google request: the request is settled once, at the price of the answer you get. `X-Credits-Used` and `meta.credits_used` show the actual charge. See [Credits and billing](https://serpkite.com/docs/credits-and-billing).

## Consensus mode

`engine: "consensus"` on [/v1/search](https://serpkite.com/docs/endpoints/search) asks several independent search indexes at once and merges what they return, like a metasearch engine:

- SerpKite starts up to three providers from its route, one per index. Yahoo and DuckDuckGo serve Bing's results, so at most one of the three is Bing-backed. Wikipedia's official API (the best matching article) can be one of them; it is only ever a consensus source, never an `auto` fallback.
- Results are deduplicated by URL (ignoring `www.`, a trailing `/` and tracking parameters such as `utm_*`) and ranked by how many providers returned them. Among equally agreed results, Wikipedia articles and results whose title and snippet contain your query's words come first, then the best position any provider gave.
- Each result has `sources`, the providers that returned it. `meta.engine` is `"consensus"` and `meta.route` lists every provider started.
- It stops as soon as `num` unique results are in hand, or after a few seconds with whatever has arrived. Providers still running are cancelled (`canceled` in the route, `timeout` for the deadline) and ones never started cost nothing.

```json
"results": [
  { "position": 1, "title": "The Best Espresso Machines", "link": "https://www.seriouseats.com/best-espresso-machines-5185482", "domain": "seriouseats.com", "sources": ["brave", "bing"] },
  { "position": 2, "title": "Espresso machine - Wikipedia", "link": "https://en.wikipedia.org/wiki/Espresso_machine", "domain": "en.wikipedia.org", "sources": ["wikipedia"] }
],
"meta": { "engine": "consensus", "credits_used": 3, "route": [ { "provider": "brave", "outcome": "ok", "ms": 640 }, { "provider": "wikipedia", "outcome": "ok", "ms": 410 }, { "provider": "bing", "outcome": "ok", "ms": 1180 } ] }
```

**Billing:** one page at each provider that returned results, added up (so up to three times a single search). Providers that failed, came back empty, were blocked or never started are free, and a cache hit (`max_age`) costs half. The whole reservation counts against your spend cap and key limit. Consensus answers are cached separately: they are never served to a single-engine request, or the reverse.

## Per-key setting

In the dashboard, [API keys](https://serpkite.com/docs/api-keys) have a switch: **Allow fallback to other search engines** (off by default). With it on, requests from that key that don't send `engine` behave as `engine=auto`. An explicit `engine` always wins, so `engine: "google"` keeps a single request Google-only even on a key with fallback on.

This is useful when you can't change the calling code, for example an agent framework or an [MCP](https://serpkite.com/docs/mcp) client that doesn't expose the parameter.

## Always Google

Some surfaces stay on Google regardless of `engine` or the key setting:

- The [Custom Search compatible endpoint](https://serpkite.com/docs/endpoints/customsearch) (`GET /customsearch/v1`), because it promises Google Custom Search results.
- Every vertical without a fallback engine in the table above.

Related: [Common parameters](https://serpkite.com/docs/parameters), [Errors](https://serpkite.com/docs/errors), [Caching](https://serpkite.com/docs/caching).