Binance API errors fixed: 429 rate limit, -1021 timestamp, -2015 key (Python)
Your bot ran fine in testing, then went live and started throwing -1021, 429, or -2015. Those three cover most Binance API failures. Here is what each one means and the exact fix.
-1021: Timestamp for this request is outside the recvWindow
Your server clock drifted from Binance's, so the signed request arrives "too old" and is rejected.
- Sync the clock: on Linux
sudo timedatectl set-ntp true(or run chrony/ntpd). - Widen the window: pass
recvWindow=10000(max 60000) on signed calls. - Best: let the client adjust for the time difference instead of trusting the OS clock.
import ccxt
ex = ccxt.binance({'apiKey': K, 'secret': S,
'options': {'recvWindow': 10000, 'adjustForTimeDifference': True}})
429 / 418: Too Many Requests (rate and weight limits)
Binance limits by request weight, not by count. A tight while True polling loop burns the weight budget and you get 429; ignore it and it escalates to 418 — an IP ban lasting minutes to days.
- Turn on the client limiter:
enableRateLimit: True. - On 429, back off exponentially and respect the
Retry-Afterheader. - Stop polling prices over REST — use WebSocket streams for quotes, REST only for orders.
ex = ccxt.binance({'apiKey': K, 'secret': S, 'enableRateLimit': True})
import time
for attempt in range(6):
try:
data = ex.fetch_ohlcv('BTC/USDT', '1m'); break
except ccxt.RateLimitExceeded:
time.sleep(2 ** attempt) # 1s, 2s, 4s, 8s...
-2015: Invalid API-key, IP, or permissions
The key reads public data fine but fails on private calls. It is almost always one of three things:
- IP allow-list: the key is locked to an IP that is not your server's. Add the server IP or remove the restriction.
- Permission: "Enable Spot/Futures Trading" was never ticked for that key.
- Wrong environment: a testnet key used on live (or the reverse) — the endpoints differ.
The real fix is architecture, not patches
These errors are symptoms of polling-style code. A reliable bot separates concerns: one task streams market data over WebSocket, another sends orders over REST with rate limiting and retries, the clock offset is handled centrally, and keys are scoped and IP-locked. Patch the three above to stop the bleeding — but if they keep coming back under load, the loop itself needs rebuilding.
Need this fixed fast? I debug Python and exchange-API bot issues — rate limits, timeouts, order errors — order a fix on Kwork. Building a fault-tolerant bot from scratch? start a project on FreelanceHunt.
I debug Python and exchange-API issues (rate limits, timeouts, order errors) and build fault-tolerant trading bots from scratch.