Google Translate API Rate Limits Explained (and the "User Rate Limit Exceeded" Error)
Google Translate API Rate Limits Explained (and the "User Rate Limit Exceeded" Error)
If you landed here from a search, you probably just saw 403 User Rate Limit Exceeded or 429 Resource has been exhausted in your logs. The first half of this post is the practical fix. The second half is the story of how running a translation app taught us these limits the expensive way.
What "User Rate Limit Exceeded" Actually Means
The Google Cloud Translation API enforces several distinct quotas, and the error you get tells you which one you hit:
userRateLimitExceeded(HTTP 403) — you exceeded the per-user short-window quota. This is a burst limiter: you sent too many characters too fast from one user context, even if your project-wide quota is fine. It's the most common error for apps that funnel all traffic through a single server IP or API key without distinguishing end users.rateLimitExceeded/RESOURCE_EXHAUSTED(HTTP 429) — your project exceeded its per-minute character quota. All requests from your project are throttled until the window rolls over.dailyLimitExceeded(HTTP 403) — you've burned the project's daily quota (or your billing cap). Nothing resets until midnight Pacific.
The critical thing all three have in common: Google Translate quotas are measured in characters, not requests. A request translating "cat" and a request translating five paragraphs are wildly different against your quota, even though they're both "one call." If you're rate-limiting or budgeting your own app by request count, your model is wrong — more on how we learned that below.
The Quota Tiers
- Free tier: the first 500,000 characters per month are free (applied as a billing credit).
- Paid usage: roughly $20 per million characters after that, billed per character — including whitespace and characters in requests that fail validation on your side after translation. Every character you send counts.
- Per-minute and per-user quotas: each project has a characters-per-minute ceiling and a per-user burst ceiling. Unlike the price, these are adjustable — go to IAM & Admin → Quotas in the Cloud Console, filter for the Translation API, and you can request increases or, just as usefully, lower them to cap your worst-case bill.
That last point is underrated: quotas are a cost-control tool, not just an obstacle. Setting a deliberately modest per-minute cap means a runaway loop in your code fails with a 429 instead of a four-digit invoice.
How to Fix It
1. Retry with exponential backoff and jitter. Rate-limit errors are transient by design. The standard pattern:
import random, time
def translate_with_backoff(client, text, target, max_retries=5):
for attempt in range(max_retries):
try:
return client.translate(text, target_language=target)
except Exception as e:
status = getattr(e, "code", None)
if status not in (403, 429):
raise # real error — don't retry
if attempt == max_retries - 1:
raise # out of retries
# 1s, 2s, 4s, 8s... plus jitter so parallel workers don't sync up
time.sleep(2 ** attempt + random.random())
The jitter matters. If twenty workers all hit the limit at once and all sleep exactly two seconds, they all come back at once and hit it again.
2. Batch your text. The API accepts multiple strings per request. One request with 50 short strings consumes the same character quota as 50 individual requests, but avoids per-request overhead and burst-limit trouble.
3. Cache aggressively. Translation output for identical input is deterministic enough to cache. If your app ever translates the same string twice, you're paying twice for one answer. A simple hash-keyed cache in front of the API is often the single biggest quota saver.
4. Track characters, not calls. Whatever internal limiter or budget alarm you have, denominate it in characters so it matches how Google actually bills and throttles. This is the one that bit us — here's that story, because the failure mode is sneakier than it sounds.
How a Translation App Learned This the Hard Way
(Landed here from a rate-limit message on the mixer? This half is for you — what the limit is, why it exists, and how to get translating again.)
When you paste a sentence into Translation Mixer and watch it tumble through six languages before landing back in English as something wonderfully weird, it looks effortless. Behind the scenes, each hop is a real Cloud Translation API call. Translating a phrase through seven languages isn't one operation — it's seven separate billed calls, and each call's cost scales with the character count of the text at that hop.
The $6 Wake-Up Call
Early on, Translation Mixer rate-limited users by counting API requests. The thinking was simple: limit how many times someone can call the translate endpoint, and you limit costs.
Then one morning: an alert. Overnight, a user had submitted some very long text — multiple times. Each submission was only a handful of API calls, so the request-based limiter saw nothing unusual. But those calls contained a lot of characters, and the character-based billing statement told a different story.
The damage was about $6. Not catastrophic — but the same pattern with longer inputs, more concurrent users, or a bot hammering the endpoint could have generated hundreds of dollars overnight with no one awake to stop it. Six dollars is a cheap lesson. It's the exact per-request-vs-per-character mismatch described above, running in production, billing us instead of erroring.
The Fix: Counting Characters Instead
We threw out request-based limiting entirely. Now the system tracks the total characters you've submitted within a rolling window; hit the ceiling and you'll see a rate-limit message — not because you clicked too many times, but because you've consumed your share of translation capacity for that period. The limiter finally speaks the same language as the bill.
There's a tiered system based on whether you're logged in:
- Logged-in users get a higher character allowance, with an 8-hour rolling window.
- Anonymous users get a lower allowance, with a 12-hour rolling window.
⚠️ Specific limits and windows are subject to change; the rate-limit message you see always reflects current values.
The gap exists because anonymous sessions are what bots use. A script can hammer an endpoint endlessly without creating an account; tighter anonymous limits make that unprofitable while leaving plenty of room for real people playing with language chains. Signing in is free and immediately unlocks the higher tier.
Why Rate Limits Exist on Free Tools at All
Translation Mixer is free — no subscriptions, no paywalls. But "free to the user" doesn't mean "free to run." Every translation costs real money, fractions of a cent at a time, and at high volume with large inputs it adds up fast.
Rate limits are the mechanism that keeps a free tool free. Think of a free coffee station at a community event: it works because the organizers budgeted for reasonable use. If one person fills a thermos and walks off, there's nothing left for anyone else. Rate limits are the "one cup per person" sign — not stinginess, just how the coffee stays free.
If You Hit Our Limit
It's temporary — the rolling window resets continuously, no midnight wait. If it happens often:
- Sign in for the higher allowance and shorter 8-hour window.
- Break long text into shorter segments — a paragraph at a time instead of a full page.
- Use fewer language hops — a four-language chain consumes fewer characters than a ten-language one.
The Bigger Picture
Every API-powered product rate-limits something — requests, tokens, characters, compute seconds. The specifics vary; the goal is the same: keep the service sustainable for everyone. If you're building on the Translate API, the takeaway from our production experience is one sentence: make your internal limits and alarms count the same unit Google bills — characters — and set your Cloud Console quotas low enough that bugs fail loudly instead of expensively.
If you enjoy Translation Mixer and want to help keep it running, there are a couple of ways to show your support. If you're learning a language, consider subscribing to one of our affiliate partners — LanguaTalk for live tutoring sessions or LingoPie for learning through TV shows and movies. They're genuinely useful services, and a subscription through our links helps offset the API and server costs that keep Translation Mixer free. Or, if you'd just like to contribute directly, the Buy Me a Coffee button on the site is always appreciated — every little bit genuinely helps.
Curious what all those API calls actually produce? Run a sentence through a language chain → and see. Or read How Translation Mixer Was Born and A Brief History of Machine Translation for more from behind the scenes.
Try it yourself →
Send your own sentence through the translation telephone game and see what comes back.
Related Posts
How Translation Mixer Was Born
How Translation Mixer started: a pandemic, two laughing kids, and a chain of Google Translate tabs that produced something inexplicably funny.
The History of Machine Translation (1954–2026)
The history of machine translation in one wild arc: a staged 1954 Cold War demo, the funding winter that followed, the statistical comeback, and the 2016 neural leap — with a timeline of all eight turning points.