# API rate limit exceeded: fixes for 12 crypto exchanges

URL: https://fincodelabs.com/en/blog/api-rate-limit-exceeded-crypto-exchanges · Publisher: Fincode (Fincode Yazılım ve Teknoloji A.Ş.), Istanbul, Turkey · Category: Exchange APIs · Published: 2026-11-06 · Updated: 2026-11-06

API rate limit exceeded? Limits, scopes, exact error codes and penalties for 12 crypto exchanges from their official docs, plus a tested Python fix.

**Short answer:** **API rate limit exceeded** means a crypto exchange has counted more requests, or more request weight, than your IP address, account or key may send in the current window. Stop every worker sharing that counter, wait as long as the exchange says, then pace later calls through one shared limiter. In twelve exchanges' official documents read on 5 November 2026, the signal ranges from HTTP 429 to codes inside an HTTP 200 reply, such as OKX 50011.

The limits below come from each exchange's API documentation and the header column from keyless public requests, all on 5 November 2026. Never paste a live API key or secret into a forum, chat, AI tool or ticket while debugging; nothing here needs one (see [API key security for trading bots](https://fincodelabs.com/en/blog/api-key-security-trading-bots)).

This is technical education, not a recommendation of any exchange, and automated trading can lose money. Availability depends on your jurisdiction and each platform's terms. Article 99/A of Capital Markets Law No. 6362 treats activity by foreign crypto-asset platforms directed at Turkish residents as unauthorized.

## Crypto exchange API rate limits compared: 12 exchanges

First find out what your limit counts (weight, credits or requests) and whose it is: IP address, account (UID), key or endpoint.

**REST rate limits in official documents, read 5 November 2026; messages as published**

| Exchange | Model and scope | Signal | Penalty or wait |
| --- | --- | --- | --- |
| Binance | Weight per IP per minute; unfilled orders per account | HTTP 429, `-1003` "Too much request weight used; current limit is %s request weight per %s. ..." | `Retry-After` in seconds; HTTP 418 IP ban, 2 minutes to 3 days |
| BingX | Per UID and endpoint; market data 500 per 10 seconds per IP | HTTP 429; `100410` "rate limitation" | "recover after 5 minutes"; HTTP 418 IP auto-ban |
| Bitget | Per endpoint; REST and WebSocket share quotas; 6,000 per IP per minute overall | HTTP 429 "Too Many Requests" | Not stated |
| Bybit | 600 per 5 seconds per IP; rolling one-second limit per UID and endpoint | `10006` "Too many visits. Exceeded the API Rate Limit."; `10018` "Exceeded the IP Rate Limit."; HTTP 403 "access too frequent"; HTTP 429 "System level frequency protection" | After a 403, end all HTTP sessions and wait 10 minutes or more |
| Delta Exchange (India) | 20,000 units per fixed 5-minute window; per IP without a key, per user ID with one | HTTP 429 Too Many Requests | `X-RATE-LIMIT-RESET`, milliseconds left |
| Deribit | Credits per sub-account: queries cost 500 from a pool of 50,000 refilled at 10,000 a second; orders use volume tiers; public calls per IP | `10028` `too_many_requests` | Session closed; reconnect once credits refill |
| Gate | Per endpoint: public 200 per 10 seconds per IP; private per UID | HTTP 429 "Too many requests" | `X-Gate-RateLimit-Reset-Timestamp` |
| HTX | Per UID and endpoint, all keys combined (older documents) | No general REST code found | `X-HB-RateLimit-Requests-Expire` |
| Kraken | Counter per API key: 15 or 20 by tier, decaying 0.33 to 1 per second; trading counter per pair | `EAPI:Rate limit exceeded`; `EOrder:Rate limit exceeded`; `EService: Throttled: [UNIX timestamp]` | A few seconds, longer if calls continue |
| KuCoin | Pools by VIP level: private per UID, public per IP; weighted endpoints | HTTP 429, `429000` | `gw-ratelimit-reset`, milliseconds |
| MEXC | Weight per 10 seconds: per IP without a key, per account with one | HTTP 429 "Too many requests" | `Retry-After`; IP ban, 2 minutes to 3 days |
| OKX | Per endpoint: public per IP, private per user ID, orders per instrument; 1,000 order requests per 2 seconds per sub-account | `50011` "Rate limit reached. Please refer to API documentation and throttle requests accordingly." (HTTP 200) or "Too Many Requests" (HTTP 429); `50061` for the sub-account limit | Not stated |

Endpoint costs are in separate guides: [Binance API rate limit](https://fincodelabs.com/en/blog/binance-api-rate-limit), [Bybit API in Python](https://fincodelabs.com/en/blog/bybit-api-python), [OKX API in Python](https://fincodelabs.com/en/blog/okx-api-python) and [Kraken API in Python](https://fincodelabs.com/en/blog/kraken-api-python).

## Rate limit headers: documented and actually returned

Use rate-limit headers where an exchange sends them, but expect gaps on public endpoints.

**Public requests without a key, 5 November 2026, 21:59 to 22:01 Istanbul time (UTC+3)**

| Exchange | Documented headers | Seen |
| --- | --- | --- |
| Binance | `X-MBX-USED-WEIGHT-1M`; `Retry-After` in seconds | Used weight 1 |
| BingX | `X-RateLimit-Requests-Remain`, `X-RateLimit-Requests-Expire` | 499 and 10000 |
| Bitget | `x-mbx-used-remain-limit`, quota left for the endpoint | 19 |
| Bybit | `X-Bapi-Limit`, `X-Bapi-Limit-Status`, `X-Bapi-Limit-Reset-Timestamp` in Unix milliseconds | None on server time or spot ticker |
| Gate | `X-Gate-RateLimit-Requests-Remain`, `-Limit`, `-Reset-Timestamp` | 199 of 200; reset in Unix seconds |
| HTX | `X-HB-RateLimit-Requests-Remain`, `-Expire` | None on server time or ticker |
| KuCoin | `gw-ratelimit-limit`, `-remaining`, `-reset` in milliseconds | 2000, 1998, 29999 on the level-1 order book; none on server time |
| Delta, Deribit, Kraken, MEXC, OKX | Delta: `X-RATE-LIMIT-RESET` on 429; MEXC: `Retry-After` | None (Deribit on its testnet; production did not answer) |

Retry-After counts seconds; KuCoin's and Delta's resets count milliseconds.

## Delta Exchange API rate limit: 20,000 units per 5 minutes

Delta Exchange's documentation, covering its India platform, gives a default quota of 20,000 units per fixed 5-minute window. Reads such as order book, tickers, open orders and balances cost 3 units, order placement or edits 5, history and fills 10, batch orders 25, anything unlisted 1. A product-level cap of 500 operations per second can also return 429.

The keyless `GET /v2/rate_limits/quota` showed `current_quota` rising by 3 per call on 5 November: it reports units used, not left, and the call costs 3 units although unlisted endpoints are documented at 1. Rechecked at 22:56 Istanbul time: unlisted `GET /v2/assets` also cost 3, a single-symbol ticker 0.

> **Hypothetical example.** Polling open orders and balances once a second uses 2 x 3 x 300 = 1,800 units per window, 9% of 20,000; adding an order book poll for 20 symbols (20 x 3 x 300 = 18,000) spends 99% before a single order.

## Bybit too many visits, and the question of days

Bybit's 10006 "Too many visits" is the per-second limit for one endpoint on your UID; nothing on Bybit's rate limit or error code pages, read in full on 5 November 2026, pairs it with a number of days.

- **10006** clears within the rolling window; wait until `X-Bapi-Limit-Reset-Timestamp`.
- **10018 and HTTP 403** are IP limits; for the 403 (600 requests per 5 seconds), end all HTTP sessions and wait at least 10 minutes. A GET with an empty JSON body or a U.S. IP address also returns 403, and waiting fixes neither.
- **Days apply to keys.** Bybit's key documentation says a key with no IP bound becomes invalid after 90 days, or 7 days after a password change. An expired key returns 33004 (derivatives) or -2015 (spot), "Your api key has expired": an authentication failure no wait will fix. `GET /v5/user/query-api` reports `deadlineDay` and `expiredAt`.

## Where the official documents contradict themselves

Four exchanges' documents contradict themselves or their servers: code against live headers and keep a margin.

- **KuCoin.** The Classic rate limit page says quotas reset every second, with a VIP 5 example of 700 requests per second, while its table lists quotas per 30 seconds (VIP 5 spot 16,000, about 533 a second). The 29,999 ms public reset seen on 5 November 2026 fits the table; private pools were not tested.
- **MEXC.** The current documentation on mexc.com gives 300 weight per 10 seconds shared by IP-weighted endpoints and 500 by account-weighted ones; the older GitHub-hosted version gives each endpoint an independent 500. Both versions also give two penalties: bans of 2 minutes to 3 days, and, in the FAQ, normal access after 10 minutes.
- **BingX.** The common error list still shows 100410 "rate limitation", while a changelog entry dated 9 October 2025 says 100410 would become 109429 (APIRateLimit) on 16 October 2025. Handle both.
- **HTX.** The GitHub-hosted documentation's change log ends in June 2022, and the newer site it points to could not be read on 5 November 2026.

## How to fix API rate limit exceeded errors in Python

Put one shared limiter in front of each counter, honor the exchange's wait, back off exponentially when it gives none, and stop on bans, firewall blocks and expired keys.

It runs on Python 3.11 with `requests` against a local mock server (no exchange, no key) whose replies include OKX's 50011 inside an HTTP 200. The first reply's Retry-After of 1e-400 parses to 0, so the 1-second floor applies.

```python
import math, threading, time
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import requests

SLOW_DOWN = {("bingx", "100410"), ("bingx", "109429"), ("bybit", "10006"), ("bybit", "10018"),
             ("kucoin", "429000"), ("okx", "50011"), ("okx", "50061")}
STOP = {("bybit", "33004"), ("bybit", "-2015")}   # expired key: waiting will not help
WAITS = {"Retry-After": 1, "gw-ratelimit-reset": 1000, "X-RATE-LIMIT-RESET": 1000}  # KuCoin, Delta: ms
MAX_WAIT = 300.0

class Stop(Exception):
    pass

class Limiter:                                    # token bucket for all workers
    def __init__(self, rate, burst):
        self.rate, self.burst = rate, max(burst, 1)
        self.tokens, self.stamp, self.resume = float(burst), time.monotonic(), 0.0
        self.lock = threading.Lock()

    def acquire(self):
        while True:
            with self.lock:
                now = time.monotonic()
                self.tokens = min(self.burst, self.tokens + (now - self.stamp) * self.rate)
                self.stamp = now
                wait = max(self.resume - now, (1 - self.tokens) / self.rate)
                if wait <= 0:
                    self.tokens -= 1
                    return
            time.sleep(wait)

    def pause(self, seconds):
        with self.lock:
            self.resume = max(self.resume, time.monotonic() + seconds)

def exchange_wait(headers):                       # seconds; None if missing or unusable
    for name, per_second in WAITS.items():
        try:
            seconds = float(headers.get(name) or "") / per_second
        except ValueError:
            continue
        if math.isfinite(seconds):
            return max(seconds, 0.0)
    return None

def call(venue, limiter, url, tries=5, floor=1.0):
    for attempt in range(tries):
        limiter.acquire()
        r = requests.get(url, timeout=10)
        try:
            data = r.json()
        except ValueError:
            data = None
        code = str(data.get("retCode", data.get("code", ""))) if isinstance(data, dict) else ""
        if (venue, code) in STOP or r.status_code in (401, 403, 418):
            raise Stop(f"HTTP {r.status_code} code {code or '-'}: stop and alert")
        if r.status_code == 429 or (venue, code) in SLOW_DOWN:
            wait = max(floor * 2 ** attempt, exchange_wait(r.headers) or 0.0)
            if wait > MAX_WAIT:
                raise Stop(f"asked to wait {wait:.0f} s: stop and alert")
            limiter.pause(wait)                   # all workers wait
            print(f"HTTP {r.status_code} code {code or '-'}: pausing {wait:.1f} s")
            continue
        r.raise_for_status()
        if data is None:
            raise Stop(f"HTTP {r.status_code}: unreadable body")
        return data
    raise Stop("still limited after retries")

REPLIES = [(429, {"Retry-After": "1e-400"}, "<html>Too Many Requests</html>"),
           (200, {}, '{"code": "50011", "msg": "Rate limit reached."}'),
           (200, {}, '{"code": "0", "data": []}')]

class Mock(BaseHTTPRequestHandler):
    def do_GET(self):
        status, headers, body = REPLIES.pop(0)
        self.send_response(status)
        for k, v in {**headers, "Content-Length": str(len(body))}.items():
            self.send_header(k, v)
        self.end_headers()
        self.wfile.write(body.encode())

    def log_message(self, *args):
        pass

server = ThreadingHTTPServer(("127.0.0.1", 0), Mock)
threading.Thread(target=server.serve_forever, daemon=True).start()
url, limiter = f"http://127.0.0.1:{server.server_port}/", Limiter(rate=5, burst=5)
print(call("okx", limiter, url))
server.shutdown()
```

Output:

```
HTTP 429 code -: pausing 1.0 s
HTTP 200 code 50011: pausing 2.0 s
{'code': '0', 'data': []}
```

Also tested on 5 November 2026: "1e400", "nan", dates and garbage in Retry-After fall back to backoff (`sleep` raises on infinity and NaN); 86,400 seconds, HTTP 401 and 418, HTML with HTTP 200 and Bybit's expired-key 33004 all stop the program; KuCoin's 29,000 ms reset pauses 29 s; a pause set while another thread slept held it too. Codes are keyed by exchange because numbers collide: 10028 is Deribit's `too_many_requests` but a unified-account error on Bybit. A dropped connection raises rather than retries; see the [CCXT error handling guide](https://fincodelabs.com/en/blog/ccxt-rate-limit-error-handling) for what is safe to resend.

## How to stay under crypto exchange API limits

Most limit errors disappear when a program asks for less.

- **Stream instead of polling** prices, books and order updates ([WebSocket heartbeat and reconnect](https://fincodelabs.com/en/blog/websocket-heartbeat-reconnect)), remembering that Bitget counts REST and WebSocket against one quota.
- **Cache reference data** (Deribit allows 1 `public/get_instruments` call a second sustained, against 20 by default), keep one queue per counter, stagger restarts and alert before the quota runs out. The [API rate limit calculator](https://fincodelabs.com/en/tools/api-rate-limit-calculator) budgets your own numbers.
- **Do not dodge limits** with extra IP addresses, keys or accounts unless the exchange's own documents allow it; otherwise ask the exchange for a higher limit.

For integration work in general, see [exchange API integration](https://fincodelabs.com/en/services/exchange-api-integration); naming these exchanges here does not mean Fincode integrates them or has built on them. A [trading bot code review](https://fincodelabs.com/en/services/trading-bot-code-review) can check existing limit handling.

## Frequently asked questions

### What does API rate limit exceeded mean?

A counter for your IP address, account or key is full for the current window. Stop, wait, then pace or reduce your calls.

### How long does an API rate limit block last?

As read on 5 November 2026, Bybit asks for at least 10 minutes after an IP-limit 403, BingX says 5 minutes, and Binance and MEXC ban IPs for 2 minutes to 3 days when 429s are ignored.

### What does Bybit too many visits mean?

It is retCode 10006, the per-second limit for one endpoint on your UID. Wait for X-Bapi-Limit-Reset-Timestamp; it is unrelated to the 90-day expiry of keys with no bound IP.

### Do public endpoints count toward the limit?

Yes. Binance, BingX, Bitget, Bybit, Delta Exchange, Deribit, Gate, KuCoin, MEXC and OKX document per-IP limits that cover them.

## Sources

- [Binance Spot API documentation: Error codes (-1003)](https://github.com/binance/binance-spot-api-docs/blob/master/errors.md)
- [BingX API documentation (rate limit, error codes, change log)](https://bingx-api.github.io/docs/)
- [Bitget API: Quick Start, rate limit section](https://www.bitget.com/docs/uta/quick-start)
- [Bybit V5 API: Rate Limit Rules](https://bybit-exchange.github.io/docs/v5/rate-limit)
- [Bybit V5 API: Error Codes](https://bybit-exchange.github.io/docs/v5/error)
- [Bybit V5 API: Create Sub UID API Key (key expiry without a bound IP)](https://bybit-exchange.github.io/docs/v5/user/create-subuid-apikey)
- [Delta Exchange API documentation: Rate Limits and rate limit quota](https://docs.delta.exchange/)
- [Deribit API: Rate Limits](https://docs.deribit.com/articles/rate-limits)
- [Gate API v4 documentation: frequency limit rules](https://www.gate.com/docs/developers/apiv4/en/)
- [Huobi (HTX) Spot API v1 documentation on GitHub](https://huobiapi.github.io/docs/spot/v1/en/)
- [Kraken API: Spot REST Rate Limits](https://docs.kraken.com/exchange/guides/rest/ratelimits)
- [KuCoin API: Rate Limit Rules (Classic)](https://www.kucoin.com/docs-new/rate-limit-rule-classic)
- [MEXC Spot V3 API: Introduction, rate limits](https://www.mexc.com/api-docs/spot-v3/introduction)
- [OKX API v5 documentation: Rate Limits and error codes](https://www.okx.com/docs-v5/en/)
- [Capital Markets Law No. 6362, Article 99/A (Turkish, consolidated text)](https://www.mevzuat.gov.tr/mevzuatmetin/1.5.6362.pdf)

> This guide is general information about software and markets, not investment, legal or tax advice. Automated trading can lose money, past or backtested performance does not guarantee future results, and the rules that apply depend on your jurisdiction and your exchange's terms. Sources, checks and corrections: see the [editorial policy](https://fincodelabs.com/en/editorial-policy).

---

Published by Fincode (Fincode Yazılım ve Teknoloji A.Ş.), a software company in Istanbul, Turkey: https://fincodelabs.com/en/blog/api-rate-limit-exceeded-crypto-exchanges

Cite as: Fincode, "API rate limit exceeded: fixes for 12 crypto exchanges", updated November 6, 2026, https://fincodelabs.com/en/blog/api-rate-limit-exceeded-crypto-exchanges
