Binance Address Whitelist Endpoint: Complete API Guide
Learn how to use the Binance address whitelist endpoint to secure withdrawals, manage trusted addresses via API, and protect your trading accounts.
Learn how to use the Binance address whitelist endpoint to secure withdrawals, manage trusted addresses via API, and protect your trading accounts.
If you're running automated trading bots or managing funds across multiple wallets, the Binance address whitelist endpoint is one of the most underrated security tools in your arsenal. It lets you programmatically manage which withdrawal addresses are approved on your account — so even if your API keys are compromised, an attacker can't drain your funds to an unknown wallet. This is the kind of defense-in-depth that separates serious traders from people who learn security the hard way.
Binance's address whitelist (also called the withdrawal address book whitelist) is a security feature that restricts withdrawals exclusively to pre-approved wallet addresses. Once enabled, your account simply cannot send funds to any address that isn't on the list — regardless of how the withdrawal request is made, whether through the UI or via API.
The whitelist endpoint is part of Binance's Wallet API suite. Using it, you can fetch your saved withdrawal addresses, verify which ones have whitelist status enabled, and integrate that check into your bot logic. Platforms like Bybit and OKX have similar features, but Binance's implementation is particularly well-documented and reliable for production-grade automation.
Important: Enabling the whitelist in Binance account settings does NOT automatically whitelist existing addresses. Each address must be explicitly marked as trusted. Plan for a 24-hour waiting period after adding a new address before it becomes active for withdrawals.
Before hitting any Binance endpoint, you need a properly scoped API key. For reading the address whitelist, your key needs 'Read' permission at minimum. If you plan to trigger withdrawals programmatically, you also need 'Withdrawal' permission enabled — but do NOT enable 'Trading' unless your use case requires it. Least-privilege access is the principle here.
import hmac
import hashlib
import time
import requests
from urllib.parse import urlencode
API_KEY = 'your_api_key_here'
SECRET_KEY = 'your_secret_key_here'
BASE_URL = 'https://api.binance.com'
def generate_signature(params: dict, secret: str) -> str:
query_string = urlencode(params)
signature = hmac.new(
secret.encode('utf-8'),
query_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
return signature
def get_headers() -> dict:
return {
'X-MBX-APIKEY': API_KEY,
'Content-Type': 'application/json'
}
# Test connectivity first
def test_connection():
response = requests.get(f'{BASE_URL}/api/v3/ping')
if response.status_code == 200:
print('Connected to Binance API successfully')
else:
raise ConnectionError(f'API connection failed: {response.status_code}')
test_connection()
Keep your SECRET_KEY out of source code. Use environment variables or a secrets manager. This is not optional — exposed keys have drained accounts within minutes of being committed to public repositories. Store them in a .env file and load with python-dotenv, or use your system's keychain.
The primary endpoint for retrieving saved withdrawal addresses on Binance is GET /sapi/v1/capital/withdraw/address/list. This returns all addresses saved in your account's withdrawal address book, along with metadata including whether each address has whitelist status.
def get_withdrawal_address_list(coin: str = None) -> list:
"""
Fetch saved withdrawal addresses from Binance.
Optionally filter by coin symbol (e.g., 'BTC', 'ETH', 'USDT').
"""
endpoint = '/sapi/v1/capital/withdraw/address/list'
params = {
'timestamp': int(time.time() * 1000),
'recvWindow': 5000
}
if coin:
params['coin'] = coin.upper()
params['signature'] = generate_signature(params, SECRET_KEY)
try:
response = requests.get(
f'{BASE_URL}{endpoint}',
params=params,
headers=get_headers()
)
response.raise_for_status()
addresses = response.json()
return addresses
except requests.exceptions.HTTPError as e:
error_data = response.json()
print(f'HTTP Error {response.status_code}: {error_data.get("msg", str(e))}')
return []
except requests.exceptions.RequestException as e:
print(f'Request failed: {e}')
return []
# Usage example
addresses = get_withdrawal_address_list(coin='USDT')
for addr in addresses:
print(f"Label: {addr.get('name')}")
print(f"Address: {addr.get('address')}")
print(f"Network: {addr.get('networkList', 'N/A')}")
print(f"Whitelisted: {addr.get('isWhitelist', False)}")
print('---')
The response will include fields like 'address', 'coin', 'name' (the label you set), 'network', and critically 'isWhitelist' — a boolean that tells you whether this specific address is on the active whitelist. This is what your bot should check before attempting any withdrawal logic.
| Field | Type | Description |
|---|---|---|
| address | string | The wallet address |
| coin | string | Asset symbol (BTC, ETH, USDT, etc.) |
| name | string | User-defined label for the address |
| network | string | Blockchain network (ERC20, TRC20, BSC, etc.) |
| isWhitelist | boolean | Whether address is whitelisted for withdrawals |
The real power of this endpoint comes when you integrate it as a safety gate in your withdrawal automation. Before your bot executes any withdrawal — whether triggered by signals from VoiceOfChain, a rebalancing algorithm, or a take-profit rule — it should verify the destination address against the whitelist. This is a two-minute implementation that has saved accounts from catastrophic losses.
class BinanceWithdrawalGuard:
def __init__(self, api_key: str, secret_key: str):
self.api_key = api_key
self.secret_key = secret_key
self._whitelist_cache = {}
self._cache_timestamp = 0
self._cache_ttl = 300 # Refresh every 5 minutes
def _is_cache_valid(self) -> bool:
return (time.time() - self._cache_timestamp) < self._cache_ttl
def refresh_whitelist(self) -> dict:
"""Fetch and cache the current whitelist."""
addresses = get_withdrawal_address_list()
self._whitelist_cache = {
addr['address'].lower(): addr
for addr in addresses
if addr.get('isWhitelist', False)
}
self._cache_timestamp = time.time()
print(f'Whitelist refreshed: {len(self._whitelist_cache)} addresses loaded')
return self._whitelist_cache
def is_address_whitelisted(self, address: str, coin: str = None) -> bool:
"""Check if a given address is on the active whitelist."""
if not self._is_cache_valid():
self.refresh_whitelist()
addr_lower = address.lower()
if addr_lower not in self._whitelist_cache:
return False
if coin:
entry = self._whitelist_cache[addr_lower]
return entry.get('coin', '').upper() == coin.upper()
return True
def safe_withdraw(self, coin: str, address: str, amount: float, network: str):
"""Execute withdrawal only if address passes whitelist check."""
if not self.is_address_whitelisted(address, coin):
raise ValueError(
f'BLOCKED: {address} is not whitelisted for {coin} withdrawals. '
f'Add it in Binance account settings and wait 24h before retrying.'
)
print(f'Whitelist check passed. Proceeding with {amount} {coin} to {address}')
# Your actual withdrawal API call goes here
# POST /sapi/v1/capital/withdraw/apply
# Instantiate and use
guard = BinanceWithdrawalGuard(API_KEY, SECRET_KEY)
guard.refresh_whitelist()
# This will raise if address isn't whitelisted
try:
guard.safe_withdraw(
coin='USDT',
address='TYourTronAddress...',
amount=100.0,
network='TRC20'
)
except ValueError as e:
print(f'Withdrawal blocked: {e}')
Pro tip: Cache the whitelist locally and refresh every 5 minutes rather than fetching on every withdrawal attempt. Binance rate limits the /sapi/ endpoints — hammering them will get your IP temporarily blocked. The cache approach also makes your bot faster and more resilient to brief API outages.
Binance isn't the only exchange with whitelist functionality — but the implementation details vary enough that you can't just copy-paste your code. If you're running a multi-exchange operation, here's what you're dealing with.
On Bybit, address whitelisting is managed through the Withdrawal Address API under /v5/asset/withdraw/withdrawable-address/list. The authentication mechanism uses HMAC-SHA256 like Binance, but the parameter structure differs — Bybit uses a timestamp in the header rather than a query parameter. OKX handles this through /api/v5/asset/withdrawal-address, and requires an additional 'OK-ACCESS-PASSPHRASE' header that you set when creating the API key. Coinbase Advanced Trade doesn't expose a programmatic whitelist endpoint at all — whitelisting is UI-only, which is a significant limitation for bot developers. Gate.io and KuCoin both offer address management via API but with smaller rate limits, so aggressive polling will get you throttled faster.
| Exchange | API Endpoint | Auth Header | Notes |
|---|---|---|---|
| Binance | /sapi/v1/capital/withdraw/address/list | X-MBX-APIKEY | Most complete implementation |
| Bybit | /v5/asset/withdraw/withdrawable-address/list | X-BAPI-API-KEY | Timestamp in header |
| OKX | /api/v5/asset/withdrawal-address | OK-ACCESS-KEY | Requires passphrase header |
| KuCoin | /api/v2/addresses | KC-API-KEY | Lower rate limits |
| Coinbase | N/A | N/A | UI-only, no API access |
| Gate.io | /api/v4/withdrawal/addresses | KEY header | Aggressive throttling |
If you're using VoiceOfChain to receive real-time trading signals and routing execution across multiple exchanges, building a unified whitelist verification layer that abstracts these differences saves a lot of headaches. The core logic — fetch list, check address, block or proceed — is identical. Only the HTTP client configuration changes per exchange.
The Binance whitelist endpoint has a few failure modes that catch developers off guard. Understanding them upfront saves debugging time in production.
import time
import requests
BINANCE_ERROR_CODES = {
-1022: 'Invalid signature — sync your system clock',
-1003: 'Rate limit exceeded — add backoff logic',
-2014: 'Invalid API key format — check header construction',
-1100: 'Invalid parameter — check coin/network values',
-3044: 'Withdrawal not allowed — check account permissions'
}
def safe_api_call(url: str, params: dict, headers: dict, max_retries: int = 3) -> dict:
"""Wrapper with retry logic and error parsing for Binance API calls."""
for attempt in range(max_retries):
try:
response = requests.get(url, params=params, headers=headers, timeout=10)
if response.status_code == 200:
return response.json()
error_data = response.json()
error_code = error_data.get('code', 0)
error_msg = BINANCE_ERROR_CODES.get(
error_code,
error_data.get('msg', 'Unknown error')
)
# Rate limit: exponential backoff
if error_code == -1003:
wait_time = (2 ** attempt) * 5
print(f'Rate limited. Waiting {wait_time}s before retry {attempt + 1}/{max_retries}')
time.sleep(wait_time)
continue
# Timestamp drift: recalculate and retry once
if error_code == -1022 and attempt == 0:
print('Signature error — refreshing timestamp and retrying')
params['timestamp'] = int(time.time() * 1000)
params['signature'] = generate_signature(
{k: v for k, v in params.items() if k != 'signature'},
SECRET_KEY
)
continue
raise RuntimeError(f'Binance API error {error_code}: {error_msg}')
except requests.exceptions.Timeout:
print(f'Request timed out (attempt {attempt + 1}/{max_retries})')
if attempt == max_retries - 1:
raise
time.sleep(2)
raise RuntimeError('Max retries exceeded')
The Binance address whitelist endpoint is a relatively simple API surface, but using it correctly creates a meaningful security boundary around your automated trading operations. The pattern is straightforward: authenticate properly, fetch the list on startup and cache it, verify every withdrawal destination before execution, and handle errors gracefully with backoff logic. That's the whole recipe.
If you're trading with signal services like VoiceOfChain that generate real-time entry and exit signals, your withdrawal automation should always be the most hardened part of your stack. Signals drive trades — but when profits need to move to cold storage or another wallet, the whitelist verification layer is your last line of defense. The 20 minutes it takes to implement this properly is trivially small compared to what it protects.
For multi-exchange setups spanning Binance, Bybit, and OKX, build the abstraction once with exchange-specific adapters, then enforce the same whitelist-check-before-withdrawal rule across all of them. Security models that only exist on one exchange while leaving others unprotected are security theater. Treat every withdrawal path as a potential attack surface and lock them all down the same way.
Final reminder: Never store API keys in code or version control. Use environment variables, a secrets vault, or OS keychain. Rotate keys every 90 days. Enable IP whitelisting on your Binance API keys in addition to address whitelisting — the two features complement each other and together make your account substantially harder to compromise.