Binance API IP Ban Duration: What Traders Need to Know
Learn how long Binance API IP bans last, what triggers them, and how to avoid rate limit violations that disrupt your trading bots.
Learn how long Binance API IP bans last, what triggers them, and how to avoid rate limit violations that disrupt your trading bots.
Your trading bot stops responding. Orders aren't going through. You check the logs and see a wall of 418 or 429 errors from Binance. Congratulations — you've been IP banned. It happens to almost every serious algo trader at least once, and the frustrating part is that it's almost always preventable. Understanding exactly how Binance's rate limiting works, how long bans actually last, and how to build your code defensively will save you from blown trades, missed signals, and hours of debugging.
Binance uses a weight-based system rather than a simple requests-per-second cap. Every API endpoint has a assigned weight value — a lightweight endpoint like GET /api/v3/ping costs 1 weight unit, while something like GET /api/v3/depth with a large limit parameter can cost 50 or more. Your account and IP are each allowed a rolling window of weight before Binance starts pushing back.
There are three separate limit buckets you need to track simultaneously: request weight per minute (default 1200 for spot), order count per second, and order count per day. Hitting any one of them triggers a different response. Most bot developers only watch one and get blindsided by another. Platforms like Bybit and OKX use similar tiered rate limiting, but Binance's weight system is more granular and easier to accidentally abuse.
| Limit Type | Default Limit | Window | Error When Exceeded |
|---|---|---|---|
| Request Weight | 1200 | 1 minute | HTTP 429 |
| Raw Requests | 6100 | 5 minutes | HTTP 429 |
| Orders | 10 | 1 second | HTTP 429 |
| Orders | 100000 | 1 day | HTTP 429 |
Here's where most guides get it wrong — there are actually two different ban mechanisms, and they behave very differently.
When you hit a rate limit, Binance first sends an HTTP 429 (Too Many Requests). The response header includes a Retry-After value telling you exactly how many seconds to wait. If you respect this and back off, the ban is temporary — typically 30 seconds to a few minutes depending on how aggressively you exceeded the limit. The 429 is Binance giving you a warning and a grace period.
The HTTP 418 is the real problem. Binance uses 418 (I'm a Teapot — yes, that's a real HTTP status) specifically for IP bans triggered by continuing to send requests after receiving 429s. In other words, if your bot doesn't handle 429 errors and keeps hammering the API, Binance escalates to a full IP ban. These bans follow an exponential backoff schedule: the first offense is typically 2 minutes, repeat violations scale to 30 minutes, then hours, and persistent violations can result in permanent bans that require contacting Binance support directly.
Critical: The 418 ban duration escalates with each violation. First ban: ~2 minutes. Second: ~30 minutes. Third+: up to several hours or permanent. Your bot MUST handle 429 responses and stop sending requests immediately when it receives one.
Every Binance API response includes headers showing your current weight usage. Reading these in real time is the only reliable way to stay under the limits. Here's a Python implementation that checks headers and backs off correctly:
import time
import requests
from typing import Optional
BASE_URL = "https://api.binance.com"
def binance_request(
endpoint: str,
params: dict,
api_key: str,
weight_used: list, # mutable container to track rolling weight
max_weight: int = 1100 # stay 100 below the 1200 limit
) -> Optional[dict]:
headers = {"X-MBX-APIKEY": api_key}
try:
response = requests.get(
f"{BASE_URL}{endpoint}",
params=params,
headers=headers,
timeout=10
)
# Always read current weight from headers
used = int(response.headers.get("X-MBX-USED-WEIGHT-1M", 0))
weight_used[0] = used
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 60))
print(f"[RATE LIMIT] 429 received. Sleeping {retry_after}s")
time.sleep(retry_after)
return None
if response.status_code == 418:
# IP banned — do NOT retry immediately
retry_after = int(response.headers.get("Retry-After", 120))
print(f"[IP BAN] 418 received. Banned for {retry_after}s. Halting.")
time.sleep(retry_after + 10) # add buffer
return None
response.raise_for_status()
# Proactive throttle: if approaching limit, sleep preemptively
if used > max_weight:
print(f"[THROTTLE] Weight {used}/{max_weight+100} — sleeping 5s")
time.sleep(5)
return response.json()
except requests.exceptions.Timeout:
print("[ERROR] Request timed out")
return None
except requests.exceptions.RequestException as e:
print(f"[ERROR] Request failed: {e}")
return None
# Usage example
weight_tracker = [0]
result = binance_request(
endpoint="/api/v3/ticker/price",
params={"symbol": "BTCUSDT"},
api_key="your_api_key_here",
weight_used=weight_tracker
)
print(f"BTC price: {result}, Current weight: {weight_tracker[0]}")
The key points in this implementation: always read the X-MBX-USED-WEIGHT-1M header, treat 429 as a pause signal (not an error to retry immediately), and treat 418 as a hard stop with a mandatory wait period. Most production bots also want to log these events to a monitoring system so you can spot patterns before they become bans.
Before you start a trading session or spin up a bot, you can check your current rate limit status. Binance exposes this through a lightweight endpoint that costs only 1 weight unit:
import requests
import hmac
import hashlib
import time
from urllib.parse import urlencode
API_KEY = "your_api_key"
SECRET_KEY = "your_secret_key"
BASE_URL = "https://api.binance.com"
def get_signed_params(params: dict, secret: str) -> dict:
query_string = urlencode(params)
signature = hmac.new(
secret.encode("utf-8"),
query_string.encode("utf-8"),
hashlib.sha256
).hexdigest()
params["signature"] = signature
return params
def check_api_status():
"""Check current rate limit usage via account endpoint."""
params = {"timestamp": int(time.time() * 1000)}
signed = get_signed_params(params, SECRET_KEY)
response = requests.get(
f"{BASE_URL}/api/v3/account",
params=signed,
headers={"X-MBX-APIKEY": API_KEY}
)
used_weight = response.headers.get("X-MBX-USED-WEIGHT-1M", "N/A")
order_count = response.headers.get("X-MBX-ORDER-COUNT-1S", "N/A")
print(f"Weight used (1m window): {used_weight}/1200")
print(f"Order count (1s window): {order_count}/10")
print(f"HTTP Status: {response.status_code}")
if response.status_code == 200:
print("API connection healthy")
elif response.status_code == 418:
print("IP BANNED — check Retry-After header")
print(f"Ban duration: {response.headers.get('Retry-After', 'unknown')}s")
return response.status_code
check_api_status()
Run this check at bot startup to verify you're not already in a ban state from a previous session. On Coinbase Advanced Trade API, a similar healthcheck approach works but the header names differ — always read the exchange-specific documentation for header formats.
Prevention is dramatically easier than recovery. A few architectural decisions in your bot can eliminate ban risk almost entirely.
import websocket
import json
import threading
# Using WebSocket instead of REST polling — zero weight cost
price_cache = {}
def on_message(ws, message):
data = json.loads(message)
symbol = data["s"] # e.g. "BTCUSDT"
price = float(data["c"]) # current close price
price_cache[symbol] = price
def on_error(ws, error):
print(f"WebSocket error: {error}")
def on_close(ws, close_status_code, close_msg):
print("WebSocket closed — reconnecting in 5s")
threading.Timer(5, start_stream).start()
def on_open(ws):
print("WebSocket connected")
# Subscribe to multiple streams in one connection
subscribe_msg = {
"method": "SUBSCRIBE",
"params": [
"btcusdt@miniTicker",
"ethusdt@miniTicker",
"solusdt@miniTicker"
],
"id": 1
}
ws.send(json.dumps(subscribe_msg))
def start_stream():
ws = websocket.WebSocketApp(
"wss://stream.binance.com:9443/ws",
on_message=on_message,
on_error=on_error,
on_close=on_close,
on_open=on_open
)
ws.run_forever()
# Start in background thread
stream_thread = threading.Thread(target=start_stream, daemon=True)
stream_thread.start()
# Now your bot reads price_cache["BTCUSDT"] with NO rate limit cost
print("Listening for prices via WebSocket (0 weight cost)...")
The WebSocket approach is particularly valuable for signal-following bots. If you're using VoiceOfChain to receive trading signals, your bot only needs to execute trades when signals arrive — not continuously scan the market. This can reduce your API weight consumption by 90% or more compared to a polling architecture.
If you're currently hitting 418s, the most important thing is to stop all requests immediately. Every additional request during a ban period can extend it. Shut down all bot instances, wait out the full Retry-After period, then diagnose before restarting.
While waiting out a ban on Binance, you can often continue trading on other platforms. Bitget and Gate.io have similar spot APIs with comparable rate limits, and KuCoin's API uses a slightly different credit-based system that some traders find more forgiving. Diversifying execution across exchanges is good practice regardless of ban risk.
If you use a VPN or shared hosting for your bot, the IP ban affects everyone sharing that IP. A bot on a $5 VPS with a shared IP can get the entire IP range flagged. Use a dedicated IP for production trading bots.
IP bans aren't bad luck — they're almost always the result of missing error handling or polling patterns that seemed fine during testing but fall apart under real market conditions. The traders who never deal with bans aren't doing anything exotic: they read response headers, use WebSocket streams for market data, and treat 429 as a hard stop rather than a minor inconvenience.
If you're building a signal-following bot, pairing it with a service like VoiceOfChain reduces your API pressure significantly. Instead of continuously scanning order books and price feeds across multiple pairs, your bot sits idle until a signal arrives and then executes a targeted set of API calls — a fraction of the weight consumption of a scanning bot.
The code patterns in this guide — reading weight headers, handling 429 and 418 separately, using WebSocket streams — are the baseline for any production-grade Binance integration. Get these right and IP bans become a thing you read about in forum posts rather than something you debug at 3am during a volatile market.