<!-- twin of https://specstream.ai/google-custom-search-api-python -->
# Google Custom Search API in Python: the call that still answers

Compared on Nov 10, 2026. The page: https://specstream.ai/google-custom-search-api-python

Google ends the Custom Search JSON API on January 1, 2027, and it is already closed to new customers. A new Google key no longer comes with it.

SpecStream answers the same `GET /customsearch/v1` in Google's JSON. In Python, set the base address to `https://api.specstream.ai` and pass a SpecStream key as `key`. `items[]`, `start` and `queries.nextPage` work as on Google.

It is the most accurate web search API in the world: 97.9 F-score on all 1,000 SimpleQA Verified questions, on the [benchmarks](https://specstream.ai/benchmarks?utm_source=alternatives&utm_campaign=google-custom-search-api-python) page. Searches cost $5 per 1,000.

[Get an API key](https://specstream.ai/signup?src=alternatives-google-custom-search-api-python&utm_source=alternatives-md&utm_campaign=google-custom-search-api-python&returnTo=%2Fworkspace%2Fsearch%3Froute%3Dgoogle) New accounts get $10 of credit, no card. It covers 2,000 searches.

## The Custom Search call from Python: SpecStream, Google and Vertex AI Search

| | SpecStream | Google Custom Search JSON API | Vertex AI Search |
|---|---|---|---|
| The call | `GET https://api.specstream.ai/customsearch/v1` with `key`, `q`, `num` and `start`. `cx` is accepted and not used | `GET https://www.googleapis.com/customsearch/v1` with `q`, an API key and `cx`, the ID of a Programmable Search Engine you configured | `POST https://discoveryengine.googleapis.com/v1/{servingConfig}:search`, a different request and reply |
| Open to new customers | Yes. Create a key in a minute and start with $10 of credit, no card | No. Closed to new customers, and discontinued on January 1, 2027 | Yes, with a free trial of 10,000 queries per account a month |
| What it searches | The whole live web, read at the moment of the call. `siteSearch` keeps a search to one site | The Programmable Search Engine you configured | Up to 50 domains. For full web search, Google asks you to contact it |
| Price per 1,000 | $5 per 1,000 searches. A call of up to 10 results is $0.005 | $5 per 1,000 queries after 100 free queries a day, for existing customers | $1.50 per 1,000 queries on Search Standard Edition, $4.00 on Search Enterprise Edition |
| What Python reads | Google's JSON: `items[]` with `title`, `link`, `snippet`, `displayLink`, `htmlTitle`, `htmlSnippet` and `formattedUrl`, `searchInformation.totalResults` and `queries.nextPage` | An `items` array with the URL, title and text snippets of each result, in JSON | Search Enterprise Edition includes generated answers, at $4.00 per 1,000 queries |
| Results a call | `num` from 1 to 10, as on Google. Up to 100 in one search on `GET /v1/web-search` | 1 to 10 results a call, and never more than 100 for a query | Billed per query: any API call to Enterprise Search counts as one |
| What a call costs when it fails | A `429` with `Retry-After` charges nothing. With an `Idempotency-Key`, a retried call is charged once | Its terms say you may be charged for each successful request | A request is any API call, direct or through an integration or the console |

## Why Python code that called Custom Search moves to SpecStream

### The call with requests

This is the whole program. It reads `items[]` as Google's reply had them, and treats a missing `items` as no results, which is how Google answers a search that finds nothing.

```
import os
import requests

BASE = "https://api.specstream.ai"  # was https://www.googleapis.com
KEY = os.environ["SPECSTREAM_API_KEY"]

reply = requests.get(
    f"{BASE}/customsearch/v1",
    params={"key": KEY, "q": "open source vector databases", "num": 10},
    timeout=30,
)
if reply.status_code != 200:
    raise RuntimeError(reply.json()["error"]["message"])

data = reply.json()
print(data["searchInformation"]["totalResults"], "results")
for item in data.get("items", []):
    print(item["title"], item["link"], item["snippet"], sep="\n  ")
```

An error comes back in Google's shape, `{"error": {"code", "message", "errors", "status"}}`, so code that reads `error.message` keeps working.

### The same call with urllib, no package to install

```
import json
import os
import urllib.parse
import urllib.request

params = urllib.parse.urlencode({
    "key": os.environ["SPECSTREAM_API_KEY"],
    "q": "open source vector databases",
    "num": 10,
})
url = f"https://api.specstream.ai/customsearch/v1?{params}"

with urllib.request.urlopen(url, timeout=30) as response:
    data = json.load(response)

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

### Paging with start and queries.nextPage

`start` is 1-based, as on Google. Each reply carries `queries.nextPage[0].startIndex` while there are more results, so the loop asks for the next page until it is gone. Each page is one search at $0.005.

```
import os
import requests

URL = "https://api.specstream.ai/customsearch/v1"
KEY = os.environ["SPECSTREAM_API_KEY"]

def search(q, pages=3):
    start, found = 1, []
    for _ in range(pages):
        data = requests.get(
            URL, params={"key": KEY, "q": q, "num": 10, "start": start}, timeout=30
        ).json()
        found += data.get("items", [])
        next_page = data.get("queries", {}).get("nextPage")
        if not next_page:
            break
        start = next_page[0]["startIndex"]
    return found

for item in search("open source vector databases"):
    print(item["link"])
```

### The parameters your code already sends

`q`, `num` and `start` work as on Google. `exactTerms`, `orTerms`, `siteSearch` and `hq` shape the search as they do there, and `fields` cuts the reply to the parts you name. The key also works in the `X-Goog-Api-Key` header or as a Bearer token. `searchType=image` is refused with a `400`: this route returns web results.

### $5 per 1,000 searches and the best scores published

A call of up to 10 results is $0.005, with no daily limit, and a `429` charges nothing. SpecStream scores 97.9 F-score on all 1,000 SimpleQA Verified questions (978 correct) and 64.0 item F1 and 43.4 row F1 on all 200 WideSearch tasks. On production on November 9, 2026, the median fast search took 0.82 s at 1 search a second and 1.07 s at 20 a second.

### What is kept from a search

Only the charge's account, key, request ID, price and time, on a key with zero retention: no request text and no answer after the reply. Set `"zero_retention": true` on the key when you create it, or later on the same key.

### The same key reads pages and returns rows

The [Extract API](https://specstream.ai/extract-api?utm_source=alternatives&utm_campaign=google-custom-search-api-python) reads up to 20 pages or documents a call at $0.80 per 1,000 pages and scores 0.908 F1 on WCXB. [Deep Search](https://specstream.ai/deep-search?utm_source=alternatives&utm_campaign=google-custom-search-api-python) returns every match for a request in plain words as structured rows at 5¢, 15¢ or $1 a row, and quotes the most a run can cost before it starts.

## Other options for the Custom Search JSON API in Python

### Vertex AI Search

Google's suggestion for searching up to 50 domains, at $1.50 per 1,000 queries on Search Standard Edition. It takes a `POST` to `discoveryengine.googleapis.com` with its own request and reply, so the Python code is rewritten. SpecStream answers the call your code already sends, on the whole web.

### Grounding with Google Search in the Gemini API

A Gemini model searches and writes an answer grounded in the results. On Gemini 3 and newer it costs $14 per 1,000 search requests after 5,000 free a month. Your code gets the model's answer. SpecStream returns `items[]` to your code at $5 per 1,000.

### Brave Search API

A search API on Brave's own index at $5 per 1,000 requests, with $5 in free credits every month and 50 queries per second. Its guide describes the move as swapping the endpoint and updating how you read the response. On SpecStream the Python that reads Google's response stays.

## How to run the Python example

1. Create a key under Agents & API in the workspace. A new account gets $10 of credit, no card, which covers 2,000 searches.

2. Put it in the environment.

```
export SPECSTREAM_API_KEY="your key"
pip install requests
```

3. Run the `requests` example above. In code that already calls Google, change `https://www.googleapis.com` or `https://customsearch.googleapis.com` to `https://api.specstream.ai` and the key. `cx` can stay in the call.

If your code uses Google's own client library, change one line. `google-api-python-client` and `googleapis` for Node both work against `https://api.specstream.ai`: set the address where the client is built, put the SpecStream key where Google's key went, and `cse().list(q=..., cx=...)` stays as it is. Tested on November 10, 2026 with versions 2.201.0 and 189.0.0.

```
# Python: google-api-python-client
from googleapiclient.discovery import build

service = build("customsearch", "v1", developerKey=SPECSTREAM_API_KEY,
                client_options={"api_endpoint": "https://api.specstream.ai"})
reply = service.cse().list(q="open source vector databases", cx="any").execute()

// Node: googleapis
const customsearch = google.customsearch({ version: "v1", auth: SPECSTREAM_API_KEY, rootUrl: "https://api.specstream.ai/" });
const reply = await customsearch.cse.list({ q: "open source vector databases", cx: "any" });
```

When your product needs every match in place of a results page, write the request in plain words. SpecStream reads it back as the conditions every row must meet and the facts to bring back, quotes the most it can cost, and delivers the rows after you approve.

## Frequently asked questions

### How do I use the Google Custom Search API in Python?

Send `GET /customsearch/v1` with `key`, `q` and `num` using `requests` or `urllib`, and read `items[]`. Google closed the API to new customers and ends it on January 1, 2027. The same call works at `https://api.specstream.ai/customsearch/v1` with a SpecStream key.

### Do I need the google-api-python-client package?

No. Plain `requests` is enough, as in the example above. If your code already uses `google-api-python-client`, keep it: pass `client_options={"api_endpoint": "https://api.specstream.ai"}` to `build`, put the SpecStream key in `developerKey`, and `service.cse().list(q=..., cx=...).execute()` works as before. Tested on November 10, 2026 with version 2.201.0.

### How do I get more than 10 results in Python?

Page with `start`: 1, then 11, then 21, or read `queries.nextPage[0].startIndex` from each reply. On the same key, `GET https://api.specstream.ai/v1/web-search` returns up to 100 results in one search for $0.059.

### Do I still need a search engine ID (cx)?

No. `cx` is accepted and not used, so code that sends it runs unchanged. SpecStream searches the whole live web, and `siteSearch` keeps a search to one site.

### What does the Custom Search JSON API cost?

$5 per 1,000 queries after 100 free queries a day, up to 10,000 queries a day, for existing customers until January 1, 2027. SpecStream costs $5 per 1,000 searches with no daily limit. Every rate is on the [pricing](https://specstream.ai/pricing?utm_source=alternatives&utm_campaign=google-custom-search-api-python) page.

### Why does my code get a KeyError on items?

A search with 0 results has no `items` key, on Google and on SpecStream. Read it with `data.get("items", [])`, as the examples here do.

## Sources

SpecStream wrote this page. Each figure about Google comes from Google's own pages, and each other figure from that company's own page.

- [Google Custom Search JSON API overview](https://developers.google.com/custom-search/v1/overview), read Nov 9, 2026
- [Google Custom Search JSON API reference, cse.list](https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list), read Nov 9, 2026
- [Google Custom Search JSON API, using REST](https://developers.google.com/custom-search/v1/using_rest), read Nov 9, 2026
- [Google Custom Search terms of service](https://developers.google.com/custom-search/terms), read Nov 9, 2026
- [Programmable Search Engine blog: updates to our web search products](https://programmablesearchengine.googleblog.com/2026/01/updates-to-our-web-search-products.html), read Nov 9, 2026
- [Google Cloud: Agent Search pricing](https://cloud.google.com/generative-ai-app-builder/pricing), read Nov 9, 2026
- [Google Cloud: servingConfigs.search method](https://cloud.google.com/generative-ai-app-builder/docs/reference/rest/v1/projects.locations.collections.engines.servingConfigs/search), read Nov 9, 2026
- [Gemini API: Grounding with Google Search](https://ai.google.dev/gemini-api/docs/google-search), read Nov 9, 2026
- [Brave Search API](https://brave.com/search/api/), read Nov 9, 2026
- [Brave, alternatives to the Google Search API](https://brave.com/learn/google-api-shutdown/), read Nov 9, 2026
- [SpecStream benchmarks](https://specstream.ai/benchmarks), read Nov 10, 2026
- [SpecStream pricing](https://specstream.ai/pricing), read Nov 10, 2026
- [SpecStream for agents](https://specstream.ai/agents.md), read Nov 10, 2026
