> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nativeport.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nativeport.ai/_mcp/server.

# Serper

Fronts [Serper](https://serper.dev). A single Serper key covers a family of Google SERP verticals — one endpoint each — together with a webpage scraper. All of them sit under `/serper`, with the secret `X-API-KEY` header injected by the gateway.

```
GET|POST /serper                 → https://google.serper.dev/search   (alias)
GET|POST /serper/<endpoint>       → https://google.serper.dev/<endpoint>
GET|POST /serper/webpage          → https://scrape.serper.dev/
```

Plain `/serper` survives as an alias of `/serper/search` (the single-endpoint contract Serper started with), which keeps older clients functional.

## Endpoints

Exactly these endpoints are admitted; anything else under `/serper` is refused with the gateway's own `404` and never reaches Serper.

| Endpoint                                                                                                                    | Upstream                               |
| --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| `search`, `images`, `videos`, `places`, `maps`, `reviews`, `news`, `shopping`, `lens`, `scholar`, `patents`, `autocomplete` | `https://google.serper.dev/<endpoint>` |
| `webpage`                                                                                                                   | `https://scrape.serper.dev/`           |

The `/account` endpoint (which reports remaining credit) is **intentionally not proxied**: it exposes account-wide billing metadata rather than search, and a per-client token has no legitimate claim on the shared balance.

## Request forms

Two request shapes are valid on Serper's side, and the gateway carries both:

* **`POST` carrying a JSON body** — the shape Serper's own docs open with. A JSON **array** (a batched search) is treated like any other body and passed along.
* **`GET` with its controls riding on the query string** — relayed with no changes.

An `apiKey` query parameter from the client is discarded, and any client `X-API-KEY` header gets overwritten — the injected key is therefore the sole credential reaching Serper. `Authorization`, which holds your gateway token, is removed before the request goes upstream.

## Examples

#### Search (POST)

```bash
curl -X POST "$GATEWAY/serper" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"q": "apple inc", "gl": "us", "hl": "en"}'
```

#### News (POST)

```bash
curl -X POST "$GATEWAY/serper/news" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"q": "cloudflare workers"}'
```

#### Search (GET)

```bash
curl "$GATEWAY/serper/search?q=apple+inc&gl=us" \
  -H "Authorization: Bearer $TOKEN"
```

#### Webpage scrape

```bash
curl -X POST "$GATEWAY/serper/webpage" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'
```

#### Batched search

```bash
curl -X POST "$GATEWAY/serper/search" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '[{"q": "apple inc"}, {"q": "google llc"}]'
```

Responses arrive as Serper's JSON, untouched. Field-level request and response detail lives in [Serper's documentation](https://serper.dev); the gateway modifies neither.