Custom Search JSON API 403
The same call works at SpecStream.
The 403 "This project does not have the access to Custom Search JSON API" has its cause on Google's own page: the API is closed to new customers, and Google ends it for everyone on January 1, 2027. Your key and billing are fine.
Send the same call to SpecStream. Change https://www.googleapis.com to https://api.specstream.ai and put a SpecStream key in key=. The path, q, num, start and Google's JSON reply stay as they are, and cx is accepted and not used.
SpecStream scores 97.9 F-score on all 1,000 SimpleQA Verified questions and 64.0 item F1 on all 200 WideSearch tasks, on the benchmarks page. A search costs $0.005, and new accounts get $10 of credit, no card.
New accounts get $10 of credit, no card. It covers 2,000 searches.
The same call at SpecStream and at Google
| SpecStream | Google Custom Search JSON API | |
|---|---|---|
| Open to a new project | Yes. Create a key under Agents & API in the workspace and start with $10 of credit, no card | No. Google's overview page says the API is closed to new customers. Existing customers have until January 1, 2027 |
| What a 403 means | One thing: the call would go over the spending limit set on the account or the key. Raise the limit and the same call answers | PERMISSION_DENIED, "This project does not have the access to Custom Search JSON API", returned to projects with the API enabled and billing active (Stack Overflow, April and June 2026) |
| A wrong key | 401 with status UNAUTHENTICATED and reason invalid_token, in Google's error shape | 400 API_KEY_INVALID, as a developer found by sending a garbage key while the real key got the 403 |
| Daily quota | None. Calls spend from your balance. An empty balance returns 402 with status FAILED_PRECONDITION | 100 free queries a day, then $5 per 1,000 up to 10,000 queries a day, for existing customers |
| The request | GET /customsearch/v1?key=...&q=...&num=&start=, as your code sends it today. cx is accepted and not used. exactTerms, orTerms, siteSearch and hq shape the search as they do on Google | GET /customsearch/v1 with q, an API key and cx, the ID of a Programmable Search Engine you configured |
| The reply | Google's JSON: kind customsearch#search, items[] with title, link, snippet, displayLink, htmlTitle, htmlSnippet and formattedUrl, searchInformation.totalResults and queries.nextPage. Your parser reads it unchanged | Metadata about the search and the engine, and an items array with the URL, title and text snippets of each result, in JSON |
| A refused argument | 400 with status INVALID_ARGUMENT and a message that names the parameter, such as "Use a num of 1 to 10." | 400 "Request contains an invalid argument." with reason badRequest, returned to an Azure Logic App while the same URL worked in a browser (Stack Overflow, October 2025) |
| Price per 1,000 searches | $5. A call of up to 10 results is one search at $0.005 | $5 per 1,000 queries after 100 free queries a day, for existing customers until January 1, 2027 |
| What answers the call | The whole live web, read at the moment of the call. 97.9 F-score on all 1,000 SimpleQA Verified questions (978 correct) | The Programmable Search Engine you configured |
| More than 10 results a search | On the same key, GET /v1/web-search returns up to 100 results for one search with num, and an answer with the page it was read from. num=100 costs $0.059 | 1 to 10 results a call. Never more than 100 results for a query |
Why the 403 ends at SpecStream
The call that returns 403 today, answered
# Before: 403 PERMISSION_DENIED
curl "https://www.googleapis.com/customsearch/v1?key=$GOOGLE_KEY&cx=$CX&q=open+source+vector+databases&num=10"
# After: 200 with items[]
curl "https://api.specstream.ai/customsearch/v1?key=$SPECSTREAM_KEY&cx=$CX&q=open+source+vector+databases&num=10"Your code keeps its path, its parameters and its parser. The address changes, and the key. The reply has Google's shape, field for field: kind, queries with request and nextPage, searchInformation and items.
How to tell the 403 from a key, cx or quota mistake
A 403 with "does not have the access" is the closed API. One developer enabled the API, linked billing, made a new unrestricted key and waited two hours, and every key and every cx got the same 403. The same developer sent a garbage key and got 400 API_KEY_INVALID, so a key mistake shows as a 400, not a 403.
A quota error is a different case: Google gives 100 free queries a day and stops existing customers at 10,000 a day. A 400 INVALID_ARGUMENT with "Request contains an invalid argument." means Google refused one parameter of that request. On SpecStream there is no daily quota, and a refused parameter comes back with a message that names it.
What stays the same
The route reads q and Google's operators (hq, exactTerms, orTerms, siteSearch), num from 1 to 10, start and the fields mask. safe, gl, hl, lr, cr, sort and filter are accepted and echoed in queries.request. The key goes in key=, in X-Goog-Api-Key or as a Bearer token. searchType=image is refused: the route returns web results.
$5 per 1,000 searches, with no daily limit
A search of up to 10 results takes $0.005 from your balance: 10,000 searches a day cost $50, and search 10,001 is answered like the first. Credit you buy never expires, and a call stopped by a 429 charges nothing. Every rate is on the pricing page.
The most accurate web search API, at about one second
SpecStream scores 97.9 F-score on all 1,000 official SimpleQA Verified questions (978 correct), and 64.0 item F1 and 43.4 row F1 on all 200 official WideSearch tasks. The Extract API scores 0.908 F1 on WCXB. Each score and its method is on the benchmarks page.
On November 9, 2026 production took 1 to 20 searches a second through the fast search every drop-in route uses, and answered 718 of 720. The median was 0.82 s at 1 search a second and 1.07 s at 20 a second, and the 95th percentile stayed between 1.09 and 1.73 s. One account takes up to 8,800 searches a minute; a call over that gets a 429 with Retry-After and is not charged.
You decide what is kept
Zero retention is a field on each key. A search made with such a key keeps no request text and no answer after the reply. The charge keeps the account, the key, the request ID, the price and the time.
POST https://api.specstream.ai/v1/account/keys
{
"name": "production",
"scopes": ["account:read", "finds:spend"],
"spend_cap_cents": 500000,
"zero_retention": true
}Search is the first call, and the same key does the rest
GET /v1/web-search returns up to 100 results for one search and an answer with the page it was read from. The Extract API reads up to 20 pages or documents a call at $0.80 per 1,000 pages, and a page with no text is not charged. Deep Search returns every match on the live web as structured rows at 5¢, 15¢ or $1 a row, with the most a run can cost quoted before it starts.
What else a 403 project can call
Vertex AI Search (Agent Search)
Google's suggestion on the Custom Search page, for searching up to 50 domains. It is a POST to a serving config on discoveryengine.googleapis.com, at $1.50 per 1,000 queries on Search Standard and $4.00 on Search Enterprise. SpecStream searches the whole live web on the GET your code already sends, at $5 per 1,000.
Grounding with Google Search
A Gemini API tool at $14 per 1,000 search requests after 5,000 free a month on Gemini 3 and newer models. It returns a model's response grounded in the results, not an items list. SpecStream returns the results in Google's JSON 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. Its reply has Brave's shape, so Custom Search code is rewritten for it. SpecStream answers the Custom Search call as it is, and Brave's call too, on one key.
Serper
Google results as JSON: 2,500 free queries, then $50 for 50,000 credits, and credits are valid for 6 months. SpecStream credit you buy never expires, and it answers Serper's call at https://api.specstream.ai/serper as well as Google's.
How SpecStream scores
The same numbers as the benchmarks page, from the official tasks and scorers.
How to end the 403
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. Set the base address to https://api.specstream.ai where your code has https://www.googleapis.com or https://customsearch.googleapis.com, and send the SpecStream key in key=.
import requests
BASE = "https://api.specstream.ai" # was https://www.googleapis.com
reply = requests.get(
f"{BASE}/customsearch/v1",
params={"key": SPECSTREAM_KEY, "cx": CX, "q": "open source vector databases", "num": 10},
)
reply.raise_for_status()
for item in reply.json()["items"]:
print(item["title"], item["link"], item["snippet"])const params = new URLSearchParams({ key: process.env.SPECSTREAM_KEY, cx: CX, q: "open source vector databases", num: "10" });
const reply = await fetch(`https://api.specstream.ai/customsearch/v1?${params}`).then((r) => r.json());
for (const item of reply.items) console.log(item.title, item.link, item.snippet);3. Leave the rest. q, num and start work as before, and queries.nextPage gives the next start. Each call is billed as one search on your key, inside the spending limit you give it.
Frequently asked questions
Something we didn't answer? Talk to a human
Why does the Custom Search JSON API say "This project does not have the access"?
PERMISSION_DENIED. The same call answers at https://api.specstream.ai/customsearch/v1 with a SpecStream key.Google Custom Search API 403 forbidden with billing enabled: how do I fix it?
https://api.specstream.ai with a SpecStream key, and items[] comes back in Google's JSON.Why is the Google Custom Search API not working?
400 API_KEY_INVALID, so a 403 is not a key mistake. SpecStream answers the same call today.Is the 403 caused by the 100 queries a day limit?
What does Custom Search 400 INVALID_ARGUMENT mean?
400 with a message that names it, such as "Use a num of 1 to 10."Can I still get a Custom Search JSON API key?
key= parameter, and a new account starts with $10 of credit, which covers 2,000 searches.How much does SpecStream cost for the same call?
429 is not charged. Every rate is on the pricing page.Sources
SpecStream wrote this page. Each Google figure comes from Google's own pages, and each error text from the Stack Overflow question that shows it.
- Google Custom Search JSON API overviewdevelopers.google.com/custom-search/v1/overview, read Nov 10, 2026
- Google Programmable Search Engine blog, January 20, 2026programmablesearchengine.googleblog.com/2026/01/updates-to-our-web-search-products.html, read Nov 10, 2026
- Google Custom Search JSON API reference, cse.listdevelopers.google.com/custom-search/v1/reference/rest/v1/cse/list, read Nov 10, 2026
- Google Custom Search JSON API, using RESTdevelopers.google.com/custom-search/v1/using_rest, read Nov 10, 2026
- Stack Overflow: persistent 403, does not have the accessstackoverflow.com/questions/79950572, read Nov 10, 2026
- Stack Overflow: 403 with billing enabledstackoverflow.com/questions/79918133, read Nov 10, 2026
- Stack Overflow: 400 INVALID_ARGUMENT from an Azure Logic Appstackoverflow.com/questions/79788744, read Nov 10, 2026
- Google Cloud: Agent Search pricingcloud.google.com/generative-ai-app-builder/pricing, read Nov 10, 2026
- Google Cloud: Agent Search, servingConfigs.searchcloud.google.com/generative-ai-app-builder/docs/reference/rest/v1/projects.locations.collections.engines.servingConfigs/search, read Nov 10, 2026
- Gemini API: Grounding with Google Searchai.google.dev/gemini-api/docs/google-search, read Nov 10, 2026
- Brave Search APIbrave.com/search/api/, read Nov 10, 2026
- Serperserper.dev/, read Nov 10, 2026
- SpecStream benchmarksspecstream.ai/benchmarks, read Nov 10, 2026
- SpecStream pricingspecstream.ai/pricing, read Nov 10, 2026
- SpecStream for agentsspecstream.ai/agents.md, read Nov 10, 2026




