At scale, limits shape your architecture: queues, backoff, caching and batching all exist because of them.
Your organisation can only send so much per minute, measured per model class in three ways:
- RPM: requests per minute.
- ITPM: input tokens per minute.
- OTPM: output tokens per minute, counted as tokens are actually produced.
Limits work like a token bucket: capacity refills continuously instead of resetting each minute, so a short burst can trigger a 429 even if your per-minute total looks fine. A sudden jump in traffic can also hit acceleration limits; ramp up gradually.
Your limits depend on your usage tier, which rises automatically with usage history. The Console's Limits page shows the current values. Cached input is good news here: for most models, tokens read from the prompt cache do not count toward ITPM, so caching raises your effective throughput.
Every response carries headers such as anthropic-ratelimit-requests-remaining and anthropic-ratelimit-input-tokens-reset, and a 429 usually includes retry-after (seconds to wait). Read headers with client.messages.with_raw_response.create(...) if you want to slow down before hitting the wall.
There are also spend limits: a monthly cap per tier, plus any lower cap you set yourself. A tier cap returns 429 with no retry-after and the error code enforced_spend_limit_reached; retrying will keep failing until the month resets or the tier changes, so alert a human instead. Your own cap returns a 400.
Example
import anthropic
client = anthropic.Anthropic()
raw = client.messages.with_raw_response.create(
model="claude-opus-5-5", max_tokens=50,
messages=[{"role": "user", "content": "ping"}],
)
h = raw.headers
print("requests left:", h.get("anthropic-ratelimit-requests-remaining"))
print("input tokens left:", h.get("anthropic-ratelimit-input-tokens-remaining"))
msg = raw.parse() # the normal Message object
try:
client.messages.create(model="claude-opus-5-5", max_tokens=50,
messages=[{"role": "user", "content": "hi"}])
except anthropic.RateLimitError as e:
if e.response.headers.get("retry-after") is None:
print("Probably a spend cap: alert someone, don't retry")Remember
- Limits: RPM, ITPM, OTPM per model class, by usage tier
- Token bucket: bursts can 429; ramp traffic gradually
- Cache reads don't count toward ITPM on most models; spend-cap 429s won't clear by retrying