# Search filters

> Restrict, exclude or boost domains, bound results by publish date, read typed published_at dates, and get query-ranked highlights instead of whole pages. No extra credits.

These options narrow and reorder what a search returns. They work on [/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) as listed below, cost nothing extra, and every other endpoint rejects them with `400 invalid_request`.

cURL:

```bash
curl https://api.serpkite.com/v1/search \
  -H "Authorization: Bearer $SERPKITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"q":"rust async runtime","include_domains":["github.com","docs.rs"],"exclude_domains":["reddit.com"],"start_date":"2026-01-01"}'
```

TypeScript:

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

const sk = new SerpKite(); // reads SERPKITE_API_KEY
const res = await sk.search({ q: "rust async runtime", include_domains: ["github.com","docs.rs"], exclude_domains: ["reddit.com"], start_date: "2026-01-01" });
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("rust async runtime", include_domains=["github.com","docs.rs"], exclude_domains=["reddit.com"], start_date="2026-01-01")
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: "rust async runtime", IncludeDomains: []string{"github.com", "docs.rs"}, ExcludeDomains: []string{"reddit.com"}, StartDate: "2026-01-01"})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res.Results[0].Title, res.Meta.CreditsUsed)
}
```

## Domain filters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `include_domains` | string[] |  | Only results from these sources, up to 20: a domain (example.com, subdomains match), a path prefix (github.com/org) or a TLD (.gov). Compiled to site: operators and enforced on the results. Search, news, images, videos. |
| `exclude_domains` | string[] |  | Drop results from these sources, up to 20, same formats as include_domains. Search, news, images, videos. |
| `boost_domains` | string[] |  | Move results from these sources to the top without filtering out the rest, up to 20. Search and news. |

Each list takes up to 20 entries, as a JSON array or a comma-separated string:

| Entry | Matches |
| --- | --- |
| `example.com` | `example.com` and every subdomain (`www.`, `docs.`…) |
| `github.com/serpkite` | Pages under that path prefix only |
| `.gov` | Every host in that top-level domain |

- `include_domains` and `exclude_domains` are compiled into Google operators (`q (site:a OR site:b) -site:c`) and then enforced on the returned rows, because a fallback engine may treat `site:` as a hint. Rows that don't match are dropped and `position` is renumbered. A page where nothing matches is an empty result and is not billed.
- `q` plus the compiled operators must stay within 2,048 characters.
- They can't be combined with `engine: "consensus"`.
- `boost_domains` (search and news) filters nothing: matching rows move to the top, and both groups keep their original order.
- `request` echoes the caller's `q` and the normalised lists, never the compiled operators.

## Date range

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `start_date` | string |  | Only results published on or after this date (YYYY-MM-DD). Google's custom date range; can't be combined with time or tbs. |
| `end_date` | string |  | Only results published on or before this date (YYYY-MM-DD). |

`start_date` and `end_date` (`YYYY-MM-DD`, either or both) become Google's custom date range (`tbs=cdr:1,cd_min:…,cd_max:…`). They can't be combined with `time` or `tbs`. When a request falls back to another engine ([`engine`](https://serpkite.com/docs/providers)), the range goes along; an engine that can't filter by date is skipped rather than answering unfiltered.

## Typed dates: published_at

Organic results, news, top stories and videos carry Google's `date` as shown ("3 days ago", "Mar 3, 2026"). When it parses, SerpKite adds `published_at` in ISO 8601: a date (`2026-09-30`) for absolute and day-level relative dates, a UTC time (`2026-10-03T09:00:00Z`) for "2 hours ago". Relative dates are resolved against the time the page was fetched, so cached results keep the right date.

## Highlights

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `highlights` | boolean | `false` | With include_content: return up to 3 query-ranked passages (~600 characters each) per fetched page in results[].highlights instead of the whole page. No extra credits. |

With [`include_content`](https://serpkite.com/docs/include-content) on /v1/search, `highlights: true` returns up to 3 passages of about 600 characters per fetched page in `results[].highlights` instead of the whole page in `content`. Passages are split along the page's headings and ranked against `q` with BM25 (a lexical ranker: deterministic, no model involved). Each one has `text`, `score` (higher is better, comparable within one response) and `heading`, the section path it sits under.

```json
{
  "position": 1,
  "title": "Async in depth",
  "link": "https://docs.example.org/async",
  "domain": "docs.example.org",
  "published_at": "2026-09-30",
  "highlights": [
    { "text": "An async runtime drives futures to completion by polling them…", "score": 7.412, "heading": "Async in depth > Runtimes" }
  ]
}
```

Highlights cost nothing on top of `include_content` (+1 credit per fetched page). In `format: "markdown"` each passage is wrapped in a `highlight` tag under its result; `format: "compact"` lists the passage texts.

## Choose the matching workflow

Use filters and highlights in a [RAG pipeline](https://serpkite.com/docs/guides/rag-pipeline) to focus the evidence you retrieve. `/v1/rank` rejects domain filters, boosts and highlights because they would change the positions being measured. [Search and news monitors](https://serpkite.com/docs/guides/scheduled-monitoring) save domain includes/excludes and `time`, but do not accept absolute date ranges, boosts or highlights.

Related: [Common parameters](https://serpkite.com/docs/parameters), [Page content](https://serpkite.com/docs/include-content), [Search providers](https://serpkite.com/docs/providers).