Search1API
Compatible APIs

Google CSE compatibility reference

Migrate basic Google CSE web searches before January 1, 2027. Keep cse().list() and items parsing with Search1API's compatible endpoint; review cx, pagination and filter limits.

Google's Custom Search JSON API is closed to new customers, and existing customers must transition by January 1, 2027. See Google's official API notice and Programmable Search Engine announcement.

Search1API provides a compatible endpoint for first-page web search. It uses Search1API's Google engine and returns the items[].title, link and snippet fields that existing CSE clients read. It does not call the retiring Custom Search JSON API.

Replace https://www.googleapis.com/customsearch/v1 with:

https://api.search1api.com/compat/google/customsearch/v1

Send a Search1API key in the key query parameter, replacing the Google API key. Authorization: Bearer YOUR_API_KEY also works. Conflicting credentials return 400. Responses use Cache-Control: no-store, and Search1API masks query-string keys in its application logs.

Your old cx does not import your search engine

cx is optional here and is accepted only as an opaque compatibility value. It does not load Google's saved sites, exclusions, refinements, promotions or ranking rules. Without an explicit filter, requests search the web. If your old engine searched a set of sites, recreate those restrictions before switching. Use siteSearch for one site or URL prefix, or the native Search API for multiple include_sites and exclude_sites.

For the migration overview and configuration changes, see Migrate from Google CSE.

Configure your client

The official google-api-python-client supports overriding the API endpoint with client_options. The base below ends with /compat/google/ including the trailing slash; the SDK appends customsearch/v1 itself.

import os
from googleapiclient.discovery import build

with build(
    "customsearch",
    "v1",
    developerKey=os.environ["SEARCH1API_API_KEY"],
    client_options={
        "api_endpoint": "https://api.search1api.com/compat/google/",
    },
) as service:
    response = service.cse().list(
        q="hono cloudflare workers",
        cx="YOUR_OLD_ENGINE_ID",
        num=5,
    ).execute()

    for item in response.get("items", []):
        print(item["title"], item["link"], item["snippet"])

Tested with google-api-python-client 2.201.0 against a local gateway with stubbed upstream services. Search calls, explicit site filtering and HttpError handling were verified; this does not measure live ranking or latency.

curl --get 'https://api.search1api.com/compat/google/customsearch/v1' \
  --data-urlencode 'q=hono cloudflare workers' \
  --data-urlencode 'num=5' \
  -H "Authorization: Bearer $SEARCH1API_API_KEY"

An HTTP client that already sends key may continue doing so with a Search1API key. Keep credential-bearing URLs private.

Clients with a hardcoded Google URL need an endpoint override or a code change. A setting named base_url is not enough if the client discards its path. Framework wrappers that construct their own Google client may need that client configured explicitly; they have not been tested here. Google's embedded Search Element JavaScript and the old /siterestrict endpoint are not covered.

Supported parameters

ParameterBehavior
qRequired, non-empty search query.
keySearch1API key, not a Google key. Optional when a Bearer key is provided.
cxOptional, opaque value echoed in queries.request; Google configuration is not imported. Listed in X-Search1API-Ignored.
numInteger from 1 to 10, default 10. Invalid values return 400.
startOmit or set to 1. Any other value returns 400 before searching or charging credits.
siteSearchOne site or URL prefix, translated into a site: filter. Defaults to inclusion.
siteSearchFilteri to include or e to exclude siteSearch; requires siteSearch.
lrA single lang_XX or three-letter language code maps to the native language hint. Boolean combinations and regional forms are ignored. Search1API's language semantics may differ from CSE's restrictions.
dateRestrictOnly d1, w1, m1, y1 map to native day, week, month and year windows. Other values are ignored, not rounded to a different period.
searchTypeOmit or use web. Image search returns 400; images attached to native search results are not CSE image search.
safeOmit or use off. active returns 400 because CSE SafeSearch filtering is unavailable.
altOmit or use json. JSONP callback and other output formats return 400.

Other parameters, including hl, gl, cr, sort, exactTerms, excludeTerms, fileType, rights, filter, fields and image filters, are ignored. hl is a UI language and is not treated as a result-language restriction. If your application depends on one of these options, review the difference before migrating.

X-Search1API-Ignored lists ignored option names, never values, as a bounded comma-separated list of percent-encoded names. It reports at most 50 names; a name longer than 120 encoded characters becomes option_name_truncated. Check it when evaluating requests; it includes cx whenever supplied. This header does not mean the old engine configuration was applied.

Response and pagination

Successful responses contain kind: "customsearch#search", queries.request, searchInformation.searchTime in seconds and an items array. Each item contains kind: "customsearch#result", title, link, displayLink (the host name) and snippet.

An empty successful search returns items: []. Search results and rankings can differ from CSE. HTML highlighting, pagemap, promotions, refinements, spelling corrections and search-total estimates are omitted rather than fabricated.

Only the first page is available. queries.nextPage and queries.previousPage are not returned. Pagination loops and applications using searchInformation.totalResults need adjustment; do not assume full CSE compatibility from the basic result format.

Credits and errors

A completed search costs 1 credit, including a confirmed empty search, and shares the native account rate limit. Technical search failures are not charged. No page-content crawling is performed. See Credits and limits.

Errors use Google's envelope: { "error": { "code": 400, "message": "…", "errors": [{ "domain": "global", "reason": "invalid", "message": "…" }] } }. HTTP status codes remain those of Search1API: 400 for invalid or unavailable behavior, 401 for an invalid key, 402 for insufficient credits, 403 for forbidden access and 429 for rate limiting. A 429 preserves the native Retry-After header. Error reasons follow the Google format; 402 is still Search1API's credit-balance status, not a daily Google quota.

Migration checklist

  1. Confirm that you use the Custom Search JSON API rather than the embedded Search Element.
  2. Recreate any site restrictions previously stored behind cx.
  3. Replace the endpoint and key; keep your supported cse().list() calls and items parsing.
  4. Remove pagination and image-search calls from this endpoint, and review ignored filters and unavailable metadata.
  5. Run representative queries and verify error handling before switching production traffic.

On this page