Skip to main content
When a request to the Custom Search JSON API fails, the response body always includes a structured error object that identifies the problem. Start there before reaching for this guide. The sections below walk you through the most frequent issues developers encounter, explain what triggers them, and give you exact steps to resolve them.

Reading the error response

Every error response follows the same shape:
Check three fields first: error.code (the HTTP status), error.errors[0].reason (the machine-readable cause), and error.message (the human-readable description). All three are needed to narrow down the issue.

400 Bad Request — Missing or invalid parameter

What causes it

A 400 response means the API could not parse or validate your request. The most common triggers are:
  • Missing q — Every request must include a non-empty q parameter.
  • Missing cx — Every request must include a valid Search Engine ID.
  • Invalid num valuenum must be an integer between 1 and 10.
  • Invalid start valuestart must be between 1 and 91.
  • Malformed URL — Special characters in q must be percent-encoded.

How to fix it

1

Confirm q and cx are present

Re-read your request URL and verify both q and cx appear as query parameters. A minimal valid request looks like this:
2

URL-encode your query

Replace spaces with + or %20 and encode special characters. Most HTTP client libraries handle this automatically if you pass q as a named parameter rather than concatenating strings manually.
3

Validate numeric parameters

Ensure num is between 1–10 and start is between 1–91. Values outside these ranges produce a 400.
4

Inspect the error message

The error.message field usually names the offending parameter. For example: "Invalid value for: num must be between 1 and 10".

401 Unauthorized — API key invalid or missing

What causes it

A 401 means the API rejected your authentication credentials. Typical causes:
  • The key parameter is absent from the request.
  • The API key was deleted or regenerated in the Cloud Console and the old value is still in use.
  • The key belongs to a different Google Cloud project than the one with the Custom Search API enabled.
  • The key was copy-pasted with leading or trailing whitespace.

How to fix it

1

Check that key is in the request

Confirm the key query parameter is present on every request. The API does not accept keys passed in headers.
2

Verify the key in the Cloud Console

Go to Google Cloud Console → APIs & Services → Credentials and confirm your key appears in the list and has not been deleted or rotated.
3

Check the key's project

Make sure the key belongs to the same project where the Custom Search API is enabled. Keys from other projects will be rejected even if they are otherwise valid.
4

Copy the key again

In the Cloud Console, click the copy icon next to your key to get a fresh, whitespace-free copy. Update your environment variable or config file.
If you suspect a key has been compromised, delete it immediately and create a new one. Leaked keys can result in unexpected charges if your billing quota is enabled.

403 Forbidden — Quota exceeded or key restriction

What causes it

A 403 response covers several distinct situations. Check error.errors[0].reason to distinguish them:
What it means: You’ve used all your allotted queries for the day (100 on the free tier).How to fix it:
  • Wait until midnight Pacific Time for the quota to reset.
  • Enable billing on your Cloud project to raise the limit to 10,000 queries/day.
  • Add caching to your application so repeated identical queries don’t consume quota. See Rate Limits and Quotas for detailed strategies.

429 Too Many Requests — Rate limit exceeded

What causes it

A 429 differs from a 403 rateLimitExceeded in that it indicates you’ve exceeded a per-second or per-minute throughput limit rather than the daily quota. The Custom Search API enforces a burst limit to prevent sudden spikes from degrading service for all users.

How to fix it

1

Implement exponential backoff

When you receive a 429, wait and retry with increasing delays. Start with a 1-second delay, then 2 s, 4 s, 8 s, and so on, with a small random jitter to avoid thundering-herd effects.
2

Spread requests over time

If you’re running bulk queries (e.g., processing a list of search terms), add a small delay between requests instead of firing them in rapid succession.
3

Check for runaway loops

Audit your code for infinite loops or recursive calls that could generate requests far faster than intended.

Empty results — No items returned

What causes it

A successful 200 response can still contain no results (items is absent or empty). This happens when:
  • The search engine scope is too narrow — Your Programmable Search Engine is scoped to specific sites that don’t contain pages matching the query.
  • The query is over-constrained — A combination of exactTerms, excludeTerms, fileType, and siteSearch leaves no matching documents.
  • The start value is too high — Google typically returns far fewer than 100 results for many queries; if start=81 yields no items, the result set is simply exhausted.
  • SafeSearch is filtering aggressively — For certain queries, safe=active removes all results.

How to fix it

1

Test the query in the Control Panel

Open the Programmable Search Engine control panel, navigate to your engine, and use the Preview tool to run the same query. This confirms whether the issue is in the engine configuration or your API call.
2

Check your engine's site scope

Go to Setup → Sites to search. If the engine is restricted to specific sites, either add more sites or enable Search the entire web.
3

Simplify the query

Remove optional filter parameters one at a time (exactTerms, fileType, dateRestrict) to identify which constraint is eliminating all results.
4

Check the totalResults field

Even when items is empty, searchInformation.totalResults tells you how many results Google found in total. A value of "0" confirms no matches exist; a non-zero value suggests the start offset exceeds what Google will return.
5

Try safe=off

If you’re searching for content that SafeSearch might filter, test with safe=off to see if results appear. Then decide whether to adjust your engine’s SafeSearch settings.

Unexpected results — Wrong pages appearing

What causes it

Your results include pages from sites you didn’t intend, are missing results from sites you expected, or the ranking seems wrong. Common causes:
  • siteSearch misconfigured — Passing siteSearchFilter=e (exclude) instead of i (include), or vice versa.
  • Engine scope overrides the siteSearch parameter — If your engine is already restricted to specific sites, a siteSearch that tries to include a different site may return nothing.
  • Wrong cx value — The request is targeting a different engine than intended.
  • orTerms broadening results unexpectedlyorTerms adds alternative terms to the query with OR logic, which can surface unrelated pages.

How to fix it

1

Confirm the cx value

Log or print the exact cx value your application is sending. Copy it and paste it into the Programmable Search Engine control panel to confirm it maps to the engine you expect.
2

Verify siteSearchFilter direction

Double-check whether you want to include or exclude the site:
3

Remove orTerms temporarily

If you’re using orTerms, try removing it and see whether results become more focused. orTerms operates as a union and can significantly widen the result set.
4

Review engine boosted/buried sites

In the control panel, check Search features → Refinements and Sites to search → Boost settings. Boosted sites appear higher in results and may be crowding out other domains you expect.

Quick-reference error table

Google’s API infrastructure occasionally returns 500 errors during incidents. Before spending time debugging your code, check the Google Cloud Status Dashboard to rule out a platform-wide issue.