Custom Search (CSE-compatible)
For apps moving off the Google Custom Search JSON API: same query params (key, cx, q, start, num…), same items[] and searchInformation shape.
For apps moving off the Google Custom Search JSON API, which Google shuts down on January 1, 2027. Same query parameters, same items[] and searchInformation shape. Change the host and the key, keep your parser.
cx is accepted and ignored: results come from the whole web, not a programmable search engine. Use siteSearch or a site: operator to restrict to a domain. This endpoint keeps Google's own parameter names (gl, hl, lr…) and is not under /v1.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
q required | string | The search query. Required. | |
key | string | Your SerpKite API key (or send Authorization: Bearer). |
|
cx | string | Accepted and ignored. | |
start | integer | 1 | Index of the first result, 1–91 (1, 11, 21…). |
num | integer | 10 | Results per call, 1–10. |
gl | string | Country code (Google CSE name). | |
hl | string | Interface language (Google CSE name). | |
lr | string | Language restrict, e.g. lang_de. |
|
safe | string | SafeSearch. One of: active, off. |
|
dateRestrict | string | Recency, e.g. d7, w2, m6, y1. |
|
siteSearch | string | Restrict to a site. | |
searchType | string | image for image results. One of: image. |
Example request
Pass your key as ?key= like Google's API, or send Authorization: Bearer $SERPKITE_API_KEY.
curl "https://api.serpkite.com/customsearch/v1?q=site%3Adocs.python.org+asyncio&cx=any" \
-H "Authorization: Bearer $SERPKITE_API_KEY"Response fields
| Field | Type | Description |
|---|---|---|
kind | string | customsearch#search. |
searchInformation | object | searchTime, formattedSearchTime, totalResults, formattedTotalResults. |
items[] | array | kind, title, htmlTitle, link, displayLink, snippet, htmlSnippet, formattedUrl, htmlFormattedUrl, pagemap, image. |
queries | object | request[] and nextPage[] as in the CSE API. |
Example response
{
"kind": "customsearch#search",
"searchInformation": {
"searchTime": 0.94,
"formattedSearchTime": "0.94",
"totalResults": "1240000",
"formattedTotalResults": "1,240,000"
},
"items": [
{
"kind": "customsearch#result",
"title": "asyncio — Asynchronous I/O",
"htmlTitle": "<b>asyncio</b> — Asynchronous I/O",
"link": "https://docs.python.org/3/library/asyncio.html",
"displayLink": "docs.python.org",
"snippet": "asyncio is a library to write concurrent code using the async/await syntax."
}
],
"queries": {
"request": [
{
"searchTerms": "site:docs.python.org asyncio",
"count": 10,
"startIndex": 1
}
]
}
}Errors
Errors use one shape: {"error":{"code","message","request_id"}}. Errors are never billed.
Full list in Errors.
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | A parameter is missing or invalid. |
| 401 | unauthorized | The API key is missing, invalid or revoked. |
| 402 | insufficient_credits | Your balance is too low. Buy a pack or wait for the monthly free grant. |
| 429 | rate_limited | Too many requests per second for your plan. Retry after the Retry-After header. |
| 503 | upstream_error | Google could not be fetched or parsed. Not billed; retry after Retry-After. |
Notes
- Errors use SerpKite's error shape (
{"error":{"code","message","request_id"}}), not Google's.