How to Use the Binance API: Complete Beginner Guide (2025)
Everything you need to start using the Binance API โ authentication, fetching prices, placing orders, websockets for live data, and rate limit handling. Python code throughout.
Builder of AI agents, crypto trading bots, and open-source automation tools. Sharing practical guides on how to build, deploy, and profit from AI and DeFi technology.
The Binance API is the most-used exchange API in crypto. Over 1,000 different bots, tools, and platforms connect to it daily. This guide teaches you everything from your first API call to handling live price streams โ with working Python code.
Setting Up Binance API Access
1. Create Your API Keys
- Log in to binance.com
- Go to Profile โ API Management
- Click Create API โ System Generated
- Name it "My Trading Bot"
- Enable: Read Info, Enable Spot & Margin Trading
- Disable: Enable Withdrawals (NEVER enable this on a bot key)
- Restrict to your IP address if possible
2. Install the Library
pip install python-binance python-dotenv
3. Store Keys Securely
# .env file (never commit this!)
BINANCE_API_KEY=your_key_here
BINANCE_SECRET=your_secret_here
import os
from dotenv import load_dotenv
from binance.client import Client
load_dotenv()
client = Client(
api_key=os.getenv("BINANCE_API_KEY"),
api_secret=os.getenv("BINANCE_SECRET")
)
# Test connection
info = client.get_account()
print(f"Account type: {info['accountType']}")
print(f"Can trade: {info['canTrade']}")
Part 1: Getting Market Data
Current Price
# Single price
price = client.get_symbol_ticker(symbol="BTCUSDT")
print(f"BTC Price: ${float(price['price']):,.2f}")
# All prices
all_prices = client.get_all_tickers()
# Convert to dict for easy lookup
price_dict = {p['symbol']: float(p['price']) for p in all_prices}
print(f"ETH Price: ${price_dict['ETHUSDT']:,.2f}")
Order Book
order_book = client.get_order_book(symbol="BTCUSDT", limit=10)
print("Top 5 asks (sell orders):")
for price, qty in order_book['asks'][:5]:
print(f" ${float(price):>12,.2f} | {float(qty):.4f} BTC")
print("\nTop 5 bids (buy orders):")
for price, qty in order_book['bids'][:5]:
print(f" ${float(price):>12,.2f} | {float(qty):.4f} BTC")
# Bid-ask spread
best_bid = float(order_book['bids'][0][0])
best_ask = float(order_book['asks'][0][0])
spread = best_ask - best_bid
spread_pct = spread / best_bid * 100
print(f"\nSpread: ${spread:.2f} ({spread_pct:.4f}%)")
Candlestick Data (OHLCV)
import pandas as pd
def get_klines(symbol: str, interval: str = "1h", limit: int = 100) -> pd.DataFrame:
"""Fetch OHLCV data as a clean DataFrame."""
klines = client.get_klines(symbol=symbol, interval=interval, limit=limit)
df = pd.DataFrame(klines, columns=[
'open_time', 'open', 'high', 'low', 'close', 'volume',
'close_time', 'quote_volume', 'trades', 'taker_buy_base',
'taker_buy_quote', 'ignore'
])
# Convert types
numeric_cols = ['open', 'high', 'low', 'close', 'volume']
df[numeric_cols] = df[numeric_cols].astype(float)
df['open_time'] = pd.to_datetime(df['open_time'], unit='ms')
df.set_index('open_time', inplace=True)
return df[['open', 'high', 'low', 'close', 'volume']]
# Get 100 hours of BTC data
btc = get_klines("BTCUSDT", "1h", 100)
print(btc.tail())
print(f"\nLatest close: ${btc['close'].iloc[-1]:,.2f}")
print(f"24h volume: {btc['volume'].iloc[-24:].sum():,.0f} BTC")
24-Hour Statistics
stats = client.get_ticker(symbol="ETHUSDT")
print(f"ETH 24h Stats:")
print(f" Open: ${float(stats['openPrice']):,.2f}")
print(f" High: ${float(stats['highPrice']):,.2f}")
print(f" Low: ${float(stats['lowPrice']):,.2f}")
print(f" Close: ${float(stats['lastPrice']):,.2f}")
print(f" Change: {float(stats['priceChangePercent']):+.2f}%")
print(f" Volume: {float(stats['volume']):,.0f} ETH")
print(f" Quote Volume:${float(stats['quoteVolume']):,.0f}")
Part 2: Account and Orders
Check Your Balances
def get_balances(min_value_usd=1.0) -> dict:
"""Get all non-zero balances with USD value."""
account = client.get_account()
balances = {}
prices = {p['symbol']: float(p['price']) for p in client.get_all_tickers()}
for asset in account['balances']:
total = float(asset['free']) + float(asset['locked'])
if total < 0.00001:
continue
symbol = asset['asset'] + 'USDT'
usd_price = prices.get(symbol, 1.0 if asset['asset'] == 'USDT' else 0)
usd_value = total * usd_price
if usd_value >= min_value_usd:
balances[asset['asset']] = {
'free': float(asset['free']),
'locked': float(asset['locked']),
'total': total,
'usd_value': usd_value,
}
return dict(sorted(balances.items(), key=lambda x: x[1]['usd_value'], reverse=True))
balances = get_balances()
total_usd = sum(b['usd_value'] for b in balances.values())
print(f"Portfolio (Total: ${total_usd:,.2f})")
for asset, data in balances.items():
print(f" {asset:<8} {data['total']:>12.4f} = ${data['usd_value']:>10,.2f}")
Placing Orders
from binance.enums import *
# Market buy (execute immediately at current price)
def market_buy(symbol: str, quote_amount: float):
"""Buy using a specific USDT amount."""
order = client.order_market_buy(
symbol=symbol,
quoteOrderQty=quote_amount # Spend exactly this much USDT
)
print(f"Market BUY: {order['executedQty']} {symbol.replace('USDT','')} @ avg ${float(order['cummulativeQuoteQty'])/float(order['executedQty']):,.2f}")
return order
# Market sell
def market_sell(symbol: str, base_amount: float):
"""Sell a specific amount of the base asset."""
order = client.order_market_sell(
symbol=symbol,
quantity=base_amount
)
print(f"Market SELL: {base_amount} {symbol.replace('USDT','')} @ avg ${float(order['cummulativeQuoteQty'])/float(order['executedQty']):,.2f}")
return order
# Limit buy
def limit_buy(symbol: str, quantity: float, price: float):
"""Buy at a specific price (passive order)."""
order = client.order_limit_buy(
symbol=symbol,
quantity=client.round_quantity(symbol, quantity),
price=client.round_price(symbol, price),
timeInForce=TIME_IN_FORCE_GTC, # Good Till Cancelled
)
print(f"Limit BUY placed: {quantity} {symbol.replace('USDT','')} @ ${price:,.2f}")
return order
# Stop-loss order
def stop_loss_sell(symbol: str, quantity: float, stop_price: float):
"""Sell when price drops to stop_price."""
order = client.create_order(
symbol=symbol,
side=SIDE_SELL,
type=ORDER_TYPE_STOP_LOSS_LIMIT,
quantity=client.round_quantity(symbol, quantity),
stopPrice=client.round_price(symbol, stop_price),
price=client.round_price(symbol, stop_price * 0.999), # Limit slightly below stop
timeInForce=TIME_IN_FORCE_GTC,
)
print(f"Stop-loss SET: {quantity} {symbol.replace('USDT','')} at ${stop_price:,.2f}")
return order
Order Management
# Check all open orders
open_orders = client.get_open_orders(symbol="BTCUSDT")
print(f"Open orders: {len(open_orders)}")
for order in open_orders:
print(f" {order['side']} {order['origQty']} @ ${float(order['price']):,.2f} ({order['status']})")
# Cancel specific order
# client.cancel_order(symbol="BTCUSDT", orderId=12345678)
# Cancel all open orders for a symbol
def cancel_all(symbol: str):
orders = client.get_open_orders(symbol=symbol)
for order in orders:
client.cancel_order(symbol=symbol, orderId=order['orderId'])
print(f"Cancelled {len(orders)} orders for {symbol}")
# Get trade history
trades = client.get_my_trades(symbol="BTCUSDT", limit=10)
for trade in trades:
side = "BUY" if trade['isBuyer'] else "SELL"
print(f"{side} {trade['qty']} BTC @ ${float(trade['price']):,.2f} (fee: {trade['commission']} {trade['commissionAsset']})")
Part 3: WebSockets for Live Data
REST API is for historical data. For live prices, use WebSockets:
from binance import ThreadedWebsocketManager
import time
# Real-time price ticker
def handle_ticker(msg):
if msg['e'] == 'error':
print(f"Error: {msg['m']}")
return
symbol = msg['s']
price = float(msg['c'])
change = float(msg['P'])
print(f"{symbol}: ${price:,.2f} ({change:+.2f}%)")
twm = ThreadedWebsocketManager()
twm.start()
# Subscribe to BTC and ETH tickers
twm.start_symbol_ticker_socket(callback=handle_ticker, symbol='BTCUSDT')
twm.start_symbol_ticker_socket(callback=handle_ticker, symbol='ETHUSDT')
time.sleep(10) # Run for 10 seconds
twm.stop()
Live Candlestick Data
def handle_kline(msg):
"""Process live kline/candlestick data."""
if msg['e'] == 'error':
return
k = msg['k']
# k['x'] is True when the candle is closed (complete)
is_closed = k['x']
symbol = k['s']
interval = k['i']
open_price = float(k['o'])
close_price = float(k['c'])
high = float(k['h'])
low = float(k['l'])
volume = float(k['v'])
status = "CLOSED" if is_closed else "OPEN"
print(f"[{status}] {symbol} {interval}: O={open_price:.2f} H={high:.2f} L={low:.2f} C={close_price:.2f} V={volume:.2f}")
# Only act on closed candles
if is_closed:
process_closed_candle(symbol, interval, open_price, high, low, close_price, volume)
def process_closed_candle(symbol, interval, o, h, l, c, v):
"""Your strategy logic goes here."""
# Check your signals on the newly completed candle
pass
twm = ThreadedWebsocketManager()
twm.start()
twm.start_kline_socket(callback=handle_kline, symbol='BTCUSDT', interval='1m')
Part 4: Rate Limits and Error Handling
Binance has strict rate limits. Violate them and you get banned.
Limits:
- 1200 requests/minute for REST
- 10 orders/second per symbol
- 100,000 orders/day per account
import time
from binance.exceptions import BinanceAPIException, BinanceRequestException
def safe_api_call(func, *args, max_retries=3, **kwargs):
"""Wrap any Binance API call with retry logic."""
for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except BinanceAPIException as e:
if e.code == -1003: # TOO_MANY_REQUESTS
wait_time = 60 if attempt == 0 else 300
print(f"Rate limited. Waiting {wait_time}s...")
time.sleep(wait_time)
elif e.code == -2010: # INSUFFICIENT_BALANCE
print(f"Insufficient balance: {e.message}")
return None
elif e.code == -1013: # MIN_NOTIONAL
print(f"Order too small (below minimum notional)")
return None
else:
print(f"Binance API Error [{e.code}]: {e.message}")
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # Exponential backoff
else:
raise
except BinanceRequestException as e:
print(f"Network error: {e}")
time.sleep(5)
return None
# Usage
order = safe_api_call(client.order_market_buy, symbol="BTCUSDT", quoteOrderQty=100)
Part 5: Exchange Filters
Every trading pair has filters that your orders must respect. Ignore them and your orders will be rejected.
def get_symbol_filters(symbol: str) -> dict:
"""Get all trading filters for a symbol."""
info = client.get_symbol_info(symbol)
filters = {}
for f in info['filters']:
if f['filterType'] == 'LOT_SIZE':
filters['min_qty'] = float(f['minQty'])
filters['max_qty'] = float(f['maxQty'])
filters['step_size'] = float(f['stepSize'])
elif f['filterType'] == 'PRICE_FILTER':
filters['min_price'] = float(f['minPrice'])
filters['tick_size'] = float(f['tickSize'])
elif f['filterType'] == 'MIN_NOTIONAL':
filters['min_notional'] = float(f['minNotional']) # Min order value in USDT
return filters
btc_filters = get_symbol_filters("BTCUSDT")
print(f"BTC/USDT filters: {btc_filters}")
# Output: {'min_qty': 0.00001, 'step_size': 0.00001, 'min_notional': 5.0, ...}
def round_qty(symbol: str, qty: float) -> float:
"""Round quantity to exchange's step size."""
f = get_symbol_filters(symbol)
step = f['step_size']
return round(qty - (qty % step), 8)
Complete Trading Bot Template
Putting it all together:
import time
import os
import logging
import pandas as pd
from binance.client import Client
from binance.exceptions import BinanceAPIException
from dotenv import load_dotenv
load_dotenv()
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
log = logging.getLogger(__name__)
client = Client(os.getenv("BINANCE_API_KEY"), os.getenv("BINANCE_SECRET"))
def get_signal(symbol: str, fast: int = 9, slow: int = 21) -> int:
"""Return 1 (buy), -1 (sell), 0 (hold)."""
klines = client.get_klines(symbol=symbol, interval='1h', limit=slow + 5)
closes = [float(k[4]) for k in klines]
def ema(data, period):
if len(data) < period:
return sum(data) / len(data)
k = 2 / (period + 1)
ema_val = data[0]
for price in data[1:]:
ema_val = price * k + ema_val * (1 - k)
return ema_val
fast_ema = ema(closes, fast)
slow_ema = ema(closes, slow)
if fast_ema > slow_ema * 1.001: # 0.1% buffer
return 1
elif fast_ema < slow_ema * 0.999:
return -1
return 0
def run_bot(symbol='BTCUSDT', size_usdt=100):
log.info(f"Bot starting: {symbol}, size=${size_usdt}")
last_signal = 0
while True:
try:
signal = get_signal(symbol)
balance = client.get_asset_balance(asset='USDT')
btc_balance = client.get_asset_balance(asset='BTC')
usdt = float(balance['free'])
btc = float(btc_balance['free'])
price = float(client.get_symbol_ticker(symbol=symbol)['price'])
log.info(f"{symbol}: ${price:,.2f} | Signal:{signal} | USDT:{usdt:.2f} | BTC:{btc:.5f}")
if signal == 1 and last_signal != 1 and usdt >= size_usdt:
order = client.order_market_buy(symbol=symbol, quoteOrderQty=size_usdt)
log.info(f"BUY executed: {order['executedQty']} BTC")
elif signal == -1 and last_signal != -1 and btc > 0.0001:
order = client.order_market_sell(symbol=symbol, quantity=round(btc - btc % 0.00001, 5))
log.info(f"SELL executed: {order['executedQty']} BTC")
last_signal = signal
except BinanceAPIException as e:
log.error(f"API error: {e}")
except Exception as e:
log.error(f"Unexpected error: {e}")
time.sleep(60)
if __name__ == '__main__':
run_bot()
Next Steps
Now that you can connect to Binance and trade:
- Add technical indicators (pandas-ta library makes this easy)
- Add Telegram notifications for order fills
- Deploy to a VPS for 24/7 operation
- Read about backtesting your strategy before going live with real money
- Consider multiple exchange arbitrage for market-neutral strategies
The Binance API is powerful and well-documented. The official docs are comprehensive โ bookmark them.
Related Articles
How to Write a Python Script That Trades Crypto Automatically
7 min read
Crypto BotsGrid Trading Bot: Complete Setup Guide for Binance
6 min read
Crypto BotsPython for Crypto: The Complete Developer's Toolkit (2025)
5 min read
Crypto BotsHow to Set Up a Free Crypto Price Alert System in Python
4 min read