An OpenRouter 429 error means a rate or capacity limit blocked a request. Diagnose the source before retrying, then use bounded backoff and concurrency control.

A 429 is a capacity signal, not a prompt bug

An OpenRouter 429 means a rate or quota boundary rejected the request. It can originate at the gateway, a free-model allowance, or an upstream provider. The right response depends on which limit fired.

Checked October 15, 2026: quotas and headers can change. Use the current limits documentation for live rules.

First capture the evidence

import os, requests
r=requests.post(
 "https://openrouter.ai/api/v1/chat/completions",
 headers={"Authorization":f"Bearer {os.environ['OPENROUTER_API_KEY']}",
          "Content-Type":"application/json"},
 json={"model":"openrouter/free","messages":[{"role":"user","content":"Hello"}]},
 timeout=(5,30),
)
print("status",r.status_code)
for name in ["Retry-After","X-RateLimit-Limit","X-RateLimit-Remaining","X-RateLimit-Reset"]:
 print(name,r.headers.get(name))
print(r.text[:1000])

Record UTC time, request ID, requested and returned model, safe provider metadata, concurrency, streaming state, and usage. Never log the API key or sensitive prompt.

Common causes

Cause Clue Fix
Per-minute limit Burst traffic; reset header Honor wait and reduce concurrency
Daily free quota :free or free router Wait for reset or use an approved paid model
Upstream provider Provider metadata; another route works Allow fallback providers or models
Retry storm Many workers retry together Add jitter, queueing, and a circuit breaker
Oversized parallel job High concurrency with normal single-call usage Use a semaphore and backpressure

Retry without ignoring Retry-After

Use the bounded Python client for a complete implementation. Parse Retry-After as seconds or an HTTP date. If the required wait exceeds your job deadline, stop and queue the job for later; do not shorten the server’s delay and immediately retry. When no usable header exists, apply exponential backoff with jitter and a maximum attempt count.

Control the crowd, not just each request

Backoff helps one caller; a semaphore or queue controls the fleet. Set a fixed worker count, queue depth, per-job deadline, and circuit breaker. Shed low-priority work before critical interactive traffic fails.

Free-model specifics

Free-model daily and per-minute allowances are separate from paid capacity and may count failed attempts. Check GET /api/v1/key for current account status. When a product needs dependable volume, design a reviewed paid fallback rather than an infinite retry loop.

Routing fixes

  • Allow multiple eligible providers for the same model.
  • Remove an unnecessarily strict provider order.
  • Add a reviewed fallback model.
  • Log the chosen provider/model and compare quality.
  • Do not use fallback to hide a credential, budget, or validation error.

Streaming 429s

A stream may begin with HTTP 200 and later emit an error event. Treat partial output as incomplete and decide whether to replace it, preserve it with a warning, or ask the user to retry. Blind replay can duplicate visible text and cost.

Do not retry these

  • 400: fix payload.
  • 401: fix key.
  • 402: fix credits or spend limit.
  • 403: fix permissions or policy.
  • 404/413/422: fix resource, size, or validation.

OpenRouter 429 error FAQ

Why does switching models help?

Models and providers can have different capacity. Treat that as evidence and measure quality/cost before making the fallback permanent.

Should I always sleep for Retry-After?

Honor a valid delay within your own deadline; otherwise use exponential backoff with jitter.

Does 429 mean nothing was processed?

Not always. A mid-stream provider failure can happen after partial output. Inspect usage and stream state.

Read next

See the routing guide, fallback guide, and Python client.

Official references

Documentation reviewed 15 October 2026. Examples illustrate the request pattern; confirm model availability and account settings before use. No uptime or performance benchmark is claimed.

Similar Posts