Reference

Rate limits

Sixty requests a minute per key, the headers that tell you where you stand, and how to back off correctly.

60 requests per minute, per API key. Fixed window.

Requests authenticated with a browser session rather than a key — which is the playground, not anything you would write — are limited to 20 per minute per account, separately.

Headers

Every rate-limited response carries all three, including the 429:

HeaderMeaning
X-RateLimit-LimitThe ceiling for this window
X-RateLimit-RemainingWhat is left
X-RateLimit-ResetUnix seconds when the window rolls over

A 429 also carries Retry-After, in seconds.

Backing off

Read Retry-After and wait. If you are writing your own retry loop, exponential backoff with jitter on 429 and 502, and no retry at all on 400, 401, 402, 403 or 404 — none of those get better by being sent again.

import time, random, openai

def with_retry(fn, attempts=5):
    for i in range(attempts):
        try:
            return fn()
        except openai.RateLimitError as e:
            wait = float(e.response.headers.get("retry-after", 0)) or (2 ** i + random.random())
            time.sleep(wait)
        except openai.APIStatusError as e:
            # 402 means top up, 4xx means fix the request. Neither is helped by retrying.
            if e.status_code != 502:
                raise
            time.sleep(2 ** i + random.random())
    raise RuntimeError("still rate limited after retries")

The openai SDK already retries 429 and 5xx with backoff by default. Set max_retries on the client rather than writing your own unless you need something specific.

If you need more

Ask. There is no self-serve tier that raises it, and the limit exists to stop a runaway loop spending a balance in seconds rather than to ration capacity. Tell us what you are building and what rate you need.

What counts

A request counts when it is accepted, including one that then fails at the model. A request refused by the limiter does not consume any of your balance.