Found in AI answers?Hire Theory Road
Theory Road.

Google Ads API RESOURCE_EXHAUSTED: Why Your Quota Ran Out.

A RESOURCE_EXHAUSTED lockout can stop every job that shares your Google Cloud project for hours, offline conversion uploads included. Here is how we read the error, find the job that spent the quota, and keep it from happening again.

By October 18, 202610 min read

When the Google Ads API returns RESOURCE_EXHAUSTED with a rate scope of DEVELOPER, the cause is almost always one of five things: your Google Cloud project hit its daily operation limit for its access level, a script ran large validateOnly dry runs that spent the quota the same as real changes, a mutate job sent hundreds of individual operations that each counted, reports re-ran the same searches instead of reading a cache, or conversion uploads share the same project as everything else. You confirm which one from the quotaErrorDetails in the error, the access level in Google Cloud Console, and your own logs for the last 24 hours. The fix is to validate once and cache the result, cut repeated searches, give critical uploads their own project and schedule, and make reports fall back to a stored snapshot.

The Google Ads API meters usage in operations. A Search or SearchStream request is one operation, every individual operation inside a mutate request is one operation, and any other request (a ConversionUploadService.UploadClickConversions call, for example) is one operation. RESOURCE_EXHAUSTED is the QuotaError that means "too many requests" against that daily allowance. RESOURCE_TEMPORARILY_EXHAUSTED is a different QuotaError that means too many requests in a short amount of time, a per second rate limit you recover from in seconds, not hours.

Is the quota tied to the developer token or the Google Cloud project?

As of October 2026, Google Ads API access levels and daily quotas belong to the Google Cloud project that owns your OAuth credentials, not to the developer token. Google sunset developer tokens on September 9, 2026 and transferred each active token's access level to the Cloud projects that used it. You can still send the developer-token header, but Google documents that it is optional and ignored. The QuotaRateScope enum now describes DEVELOPER as a per project quota, formerly the developer token quota. So when the error says rateScope DEVELOPER, read it as "this Cloud project is out of operations". ACCOUNT scope means a single customer account is being rate limited.

So a second developer token no longer buys a separate quota. A second Cloud project, with its own OAuth client or service account and access level, does.

The five causes we find most often.

We hit this twice on our own tooling, both times with a lockout that lasted many hours, and both times the trigger was a change set, not a report.

  • Daily operation limit reached: the project sits at Explorer or Basic access and the last 24 hours of searches, mutate operations and uploads crossed 2,880 or 15,000 operations
  • validateOnly dry runs counted like real changes: in our accounts, validating a change set of several hundred operations (new ad groups with keywords and responsive search ads) consumed quota the same way the real mutate would, and running the dry run several times burned through the day
  • Large mutates counted per operation: one request carrying 400 keyword operations is 400 operations against the daily limit, not one
  • Reports re-running the same searches: dashboards and agents querying the same customers on every refresh, with nothing cached
  • Shared project for everything: uploads, reporting and change scripts use one Cloud project, so when one job spends the quota, the uploads stop too

How do you tell which quota you hit?

Read the quotaErrorDetails inside the error before you retry anything: rateScope tells you project or account, rateName names the bucket, and retryDelay tells you how long to wait. Google documents quota_error_details as carrying the scope (account or developer), the rate bucket name and the retry delay. In REST it sits in the GoogleAdsFailure under error.details.

The error payload. Log the full failure, not just the message. RESOURCE_EXHAUSTED with rateScope DEVELOPER is the daily project quota. RESOURCE_TEMPORARILY_EXHAUSTED is the short term rate limit. In our lockouts the retryDelay ran to hours, which is the tell that backoff in a loop will not help.

The Google Ads API Overview page in Google Cloud Console. Open the Cloud project that owns the OAuth client or service account your script uses and read its current access level. Test, Explorer, Basic and Standard each have a different ceiling.

Your own request log. Count operations, not requests, for the last 24 hours: one per search, one per mutate operation, one per upload or other call. Google measures "per day" as a sliding 24 hour window, so a burst at 3 p.m. yesterday still counts at 2 p.m. today.

What are the daily operation limits for each access level?

Explorer access allows 2,880 operations per day against production accounts, Basic allows 15,000, and Standard is unlimited. Test access is limited to test accounts at 15,000 operations per day. Explorer also blocks some services outright, including Keyword Planner and the other planning services.

Google Ads API access levels and daily operation limits (as of October 2026)
Access levelAccounts it can touchDaily operation limitHow you get it
TestTest accounts only15,000 per dayGranted when you enable the API in a Cloud project
ExplorerTest and production2,880 per day on production, 15,000 on testApply from the Google Ads API Overview page, may be approved automatically
BasicTest and production15,000 per day on bothApply after brand verification of the Cloud project
StandardTest and productionUnlimited daily operationsManual review, typically about 10 business days

Standard removes the daily ceiling but not rate limits, which still return RESOURCE_TEMPORARILY_EXHAUSTED.

Does validateOnly count against the daily quota?

Treat every validateOnly request as if it spends the same operations as the real request. Google's quota page does not exempt validate_only, and it does say that requests rejected with a GoogleAdsFailure still count against the daily operation quota. In our own accounts, dry runs of large change sets counted operation for operation, which is how a cautious "check it first" habit locked us out. Validate once per change set, store the result with a hash of the operations, and only re-validate the parts that changed.

Diagnose top to bottom.

Each step isolates one layer. Stop at the first real failure.

Separate the two errors.
Confirm the quotaError value. RESOURCE_TEMPORARILY_EXHAUSTED is a rate limit: retry with exponential backoff and jitter, as Google recommends. RESOURCE_EXHAUSTED with rateScope DEVELOPER is the daily quota: stop retrying, because every retry that reaches the service can spend more.
Read retryDelay and stop the schedulers.
Pause every cron job, agent and dashboard that authenticates through the same Cloud project.
Identify the project and its access level.
Find which Cloud project owns the OAuth client or service account, then read its access level on the Google Ads API Overview page in Cloud Console.
Count the last 24 hours by job.
Group logged operations by script. Look for validateOnly runs, mutates with hundreds of operations, and searches repeated on a timer. One job is usually most of the total.
Check what else stopped.
List the jobs that share the project. If offline conversion uploads were among them, note the gap so you can re-upload the missed rows once quota returns, within the conversion window.
Fix the spender, then restart in priority order.
Restart conversion uploads first, reporting second, change scripts last. Then confirm uploads landed, using the checks in our Google Ads conversion tracking diagnosis.

Symptom, cause and fix.

Google Ads API RESOURCE_EXHAUSTED: symptoms, likely causes and fixes
SymptomLikely causeFix
RESOURCE_EXHAUSTED, rateScope DEVELOPER, retryDelay in hoursDaily operation limit for the project's access levelStop retries, find the spending job, wait out the window, apply for a higher access level
Quota gone after a dry run, nothing changed in the accountvalidateOnly runs of a large change setValidate once, cache the result, re-validate only changed operations
Quota gone after one bulk buildEach mutate operation counts individuallySpread large builds across days or move to Basic or Standard access
RESOURCE_TEMPORARILY_EXHAUSTED, clears in secondsRate limit on requests or operations per minuteExponential backoff with jitter, cap concurrent tasks, client side rate limiter
Offline conversion uploads failing at the same timeUploads share the Cloud project with change scriptsRun uploads from their own project and schedule, batch up to 2,000 conversions per request
Dashboards blank during the lockoutReports query the API live on every loadServe the last stored snapshot when the API errors
PAGE_SIZE_NOT_SUPPORTED on googleAds:searchpage_size set in the requestRemove page_size, the page size is fixed at 10,000 rows
Keyword Planner calls rejected on a new projectExplorer access blocks planning servicesApply for Basic or Standard access

How do you stop it from happening again?

Batching operations into fewer requests helps with rate limits, but it does not reduce the daily operation count for mutates. Google counts each mutate operation, so 400 operations in one request and 400 in forty requests cost the same against the day. What does reduce the count:

  • Validate once: hash the change set, store the validation result, and skip the dry run when the hash has not changed
  • Cache reads: store search results with a timestamp and let dashboards and agents read the cache, refreshing on a schedule instead of on every load
  • Use fewer, wider queries: one SearchStream request is one operation no matter how many batches it streams, and paged Search requests with a valid next_page_token do not count again
  • Split critical work by project: conversion uploads on one Cloud project and schedule, bulk changes on another, so a big build cannot starve the uploads
  • Upload in bulk: an UploadClickConversions call counts as one operation and can carry up to 2,000 conversions, so batch rows instead of sending one call per lead
  • Fail soft: on RESOURCE_EXHAUSTED, show the last snapshot with its age

We apply the same rule to every quota limited Google API we run, including the Indexing API: count units before you schedule a job, and never retry against a daily cap.

Google Ads API v19 and later fix the Search page size at 10,000 rows and return PAGE_SIZE_NOT_SUPPORTED if you set page_size. We hit this calling googleAds:search on v22 with code written for older versions. Remove the field and page with next_page_token. Paged requests with a valid token do not count again; an expired or invalid token does.

What is normal and what is a red flag.

Normal: an occasional RESOURCE_TEMPORARILY_EXHAUSTED during a burst that clears after backoff, since Google meters short term rates with a token bucket. Normal: a project at Explorer access running out on a heavy build day, since 2,880 operations is roughly two per minute averaged over 24 hours.

Red flags: RESOURCE_EXHAUSTED with rateScope DEVELOPER on a project that should be nowhere near its limit, which usually means a forgotten scheduler or a retry loop. Any job that retries a daily quota error on a timer. Conversion uploads running on the same project as bulk changes. A dashboard that goes blank instead of showing cached data. After a lockout, run our conversion tracking audit checklist to confirm nothing downstream broke. On Microsoft, a different API failure is covered in Microsoft Ads API settings not saving.

What does RESOURCE_EXHAUSTED mean in the Google Ads API?

It is the QuotaError for too many requests against a quota. With rateScope DEVELOPER it means your Google Cloud project has used its daily operation limit for its access level, measured over a sliding 24 hour window. Read retryDelay in quotaErrorDetails to see how long to wait.

How many operations per day does the Google Ads API allow?

Test access allows 15,000 operations per day against test accounts. Explorer allows 2,880 per day against production accounts and 15,000 against test accounts. Basic allows 15,000 per day on both. Standard is unlimited, though rate limits still apply.

Do validateOnly requests count against the Google Ads API quota?

Google does not document an exemption, and requests rejected with a GoogleAdsFailure still count. In our accounts, validateOnly dry runs of large change sets counted the same as real mutates. Validate once per change set and cache the result.

What is the difference between RESOURCE_EXHAUSTED and RESOURCE_TEMPORARILY_EXHAUSTED?

RESOURCE_TEMPORARILY_EXHAUSTED means too many requests in a short time and clears with exponential backoff. RESOURCE_EXHAUSTED with DEVELOPER scope is the daily operation quota and does not clear until older operations roll out of the 24 hour window.

Will a new developer token give me more Google Ads API quota?

No. Google sunset developer tokens on September 9, 2026, and access levels now belong to the Google Cloud project that owns your OAuth credentials. A separate Cloud project with its own access level has its own quota.

Why does the Google Ads API reject page_size?

From v19 onward the Search page size is fixed at 10,000 rows, and setting page_size returns PAGE_SIZE_NOT_SUPPORTED. Remove the field and page with next_page_token.

Work with us

Let’s talk about what’s next.

A short note on where the business is and where it needs to go. A senior partner replies within one business day.

t@theoryroad.com

Step 1 of 2

How can we help you get found?

What do you need help with?

Next: name, email and budget. That’s it.