LLM Rate Limit Header Decoder

Decode Anthropic and OpenAI rate limit headers: which bucket is actually closest to empty, how long until it refills, and which of the two reset formats you are looking at.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Decode the headers. Nothing leaves this tab.

Wanted a different tool?

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

Requests to spare, tokens nearly gone

95% of the request budget left and 0.6% of the input token budget, which is why a 429 arrives looking unexplained

anthropic-ratelimit-requests-limit: 1000
anthropic-ratelimit-requests-remaining: 950
anthropic-ratelimit-requests-reset: 2026-08-17T15:01:00Z
anthropic-ratelimit-input-tokens-limit: 200000
anthropic-ratelimit-input-tokens-remaining: 1200
anthropic-ratelimit-input-tokens-reset: 2026-08-17T15:00:30Z

OpenAI's relative reset

1m30s is a duration, and code written for Anthropic's timestamp gets NaN from it rather than an error

x-ratelimit-limit-requests: 5000
x-ratelimit-remaining-requests: 4999
x-ratelimit-reset-requests: 12ms
x-ratelimit-limit-tokens: 160000
x-ratelimit-remaining-tokens: 158000
x-ratelimit-reset-tokens: 1m30s

A 429 with retry-after

The provider has already answered the only question worth asking, and it beats any arithmetic on the reset fields

HTTP/1.1 429 Too Many Requests
retry-after: 26
anthropic-ratelimit-input-tokens-limit: 200000
anthropic-ratelimit-input-tokens-remaining: 0
anthropic-ratelimit-input-tokens-reset: 2026-08-17T15:00:30Z

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Watching the request bucket

    Requests, input tokens and output tokens meter separately, and on a token-metered API the request count is almost never the binding one. A long prompt spends the input token bucket many times faster, which is why a 429 so often arrives with request quota apparently to spare.

    Instead:Track every bucket and pace against whichever is closest to empty as a fraction of its limit, not as a raw number.

  2. Parsing the reset field the same way for both providers

    Anthropic sends an absolute RFC 3339 timestamp and OpenAI sends a relative duration such as `6ms` or `1m30s`. Neither wrong parse throws: `Date.parse("6ms")` is NaN and `parseInt` on a timestamp gives the year, so one path waits forever and the other retries immediately into another 429.

    Instead:Detect the shape before parsing. A leading digit followed by a unit suffix is a duration; anything with a `T` and a `Z` is a timestamp.

  3. Computing a backoff when `retry-after` is present

    On a 429 the provider is telling you exactly how long to wait, and arithmetic on the reset fields cannot beat it. Retrying sooner is what turns a brief limit into a sustained one.

    Instead:Honour `retry-after` first, add jitter so a fleet does not all return at the same instant, and fall back to the reset fields only when it is absent.

  4. Comparing an absolute reset against the local clock

    The bucket refills on the server's clock. A machine a few seconds fast computes a shorter wait than the server intended and retries into the limit it was waiting out.

    Instead:Use the response's own `Date` header as the reference point. It is the server's clock, delivered with the number you are comparing against.

The bucket you are watching is not the one that will 429

Paste the response headers and get the only two answers that matter: which meter is closest to empty, and when it comes back. Both providers make that harder than it needs to be, in different ways.

Any bucket reaching zero rejects the request

Requests, input tokens and output tokens are metered separately, and often a combined token bucket as well. Request count is the number most clients track because it is the easiest, and on a token-metered API it is almost never the binding one: a long prompt spends the input token bucket many times faster. That is why a 429 so often arrives with quota apparently to spare.

requests       950 / 1000    95% left
input tokens  1200 / 200000  0.6% left   <- this one 429s

The reset field is a different TYPE per provider

Anthropic sends an absolute RFC 3339 timestamp. OpenAI sends a relative duration such as 6ms or 1m30s. Code written for one and pointed at the other does not error: Date.parse on a duration gives NaN, and parseInt on a timestamp gives the year. One path waits forever and the other retries immediately into another 429.

anthropic-ratelimit-tokens-reset: 2026-08-17T15:04:05Z
x-ratelimit-reset-tokens: 1m30s

parseInt("6ms")  ->  6      a six second wait
"6ms" really is  ->  0.006  six milliseconds

The reset is when the bucket is full, not a window boundary

Both providers use a token bucket that refills continuously, so capacity returns gradually rather than all at once. Waiting the whole reset is safe and is usually far longer than necessary. Pacing so the bucket never empties beats backing off after it does.

retry-after beats anything you compute

On a 429 the provider is telling you exactly how long to wait, and it takes precedence over any arithmetic on the reset fields. Retrying sooner is what turns a brief limit into a sustained one. Add jitter so a fleet of clients does not all return at the same instant and cause the next one.

Clock skew matters for one provider and not the other

An absolute timestamp is compared against your clock, so a machine several seconds fast computes a shorter wait than the server intended. Use the response's own Date header rather than the local clock. A relative duration has no such problem, and also no absolute deadline you can log.

What this cannot see

It reads the headers you paste. It does not call anything, so the numbers are a snapshot of one response rather than your current state, and both buckets have been refilling since. It does not know your organisation's tier or any per-model limits that are not in these headers, and it cannot see limits enforced upstream by a gateway or proxy that strips them. If no rate limit headers appear at all, something between you and the API is removing them, which is worth knowing on its own.