Backend

ccxt-python

ccxt/ccxt · updated Apr 8, 2026

$npx skills add https://github.com/ccxt/ccxt --skill ccxt-python
summary

A comprehensive guide to using CCXT in Python projects for cryptocurrency exchange integration.

skill.md

CCXT for Python

A comprehensive guide to using CCXT in Python projects for cryptocurrency exchange integration.

Installation

REST API (Standard)

pip install ccxt

WebSocket API (Real-time, ccxt.pro)

pip install ccxt

Optional Performance Enhancements

pip install orjson      # Faster JSON parsing
pip install coincurve   # Faster ECDSA signing (45ms → 0.05ms)

Both REST and WebSocket APIs are included in the same package.

Quick Start

REST API - Synchronous

import ccxt

exchange = ccxt.binance()
exchange.load_markets()
ticker = exchange.fetch_ticker('BTC/USDT')
print(ticker)

REST API - Asynchronous

import asyncio
import ccxt.async_support as ccxt

async def main():
    exchange = ccxt.binance()
    await exchange.load_markets()
    ticker = await exchange.fetch_ticker('BTC/USDT')
    print(ticker)
    await exchange.close()  # Important!

asyncio.run(main())

WebSocket API - Real-time Updates

import asyncio
import ccxt.pro as ccxtpro

async def main():
    exchange = ccxtpro.binance()
    while True:
        ticker = await exchange.watch_ticker('BTC/USDT')
        print(ticker)  # Live updates!
    await exchange.close()

asyncio.run(main())

REST vs WebSocket

Import For REST For WebSocket
Sync import ccxt (WebSocket requires async)
Async import ccxt.async_support as ccxt import ccxt.pro as ccxtpro
Feature REST API WebSocket API
Use for One-time queries, placing orders Real-time monitoring, live price feeds
Method prefix fetch_* (fetch_ticker, fetch_order_book) watch_* (watch_ticker, watch_order_book)
Speed Slower (HTTP request/response) Faster (persistent connection)
Rate limits Strict (1-2 req/sec) More lenient (continuous stream)
Best for Trading, account management Price monitoring, arbitrage detection

When to use REST:

  • Placing orders
  • Fetching account balance
  • One-time data queries
  • Order management (cancel, fetch orders)

When to use WebSocket:

  • Real-time price monitoring
  • Live orderbook updates
  • Arbitrage detection
  • Portfolio tracking with live updates

Creating Exchange Instance

REST API - Synchronous

import ccxt

# Public API (no authentication)
exchange = ccxt.binance({
    'enableRateLimit': True  # Recommended!
})

# Private API (with authentication)
exchange = ccxt.binance({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_SECRET',
    'enableRateLimit': True
})

REST API - Asynchronous

import ccxt.async_support as ccxt

exchange = ccxt.binance({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_SECRET',
    'enableRateLimit': True
})

# Always close when done
await exchange.close()

WebSocket API

import ccxt.pro as ccxtpro

# Public WebSocket
exchange = ccxtpro.binance()

# Private WebSocket (with authentication)
exchange = ccxtpro.binance({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_SECRET'
})

# Always close when done
await exchange.close()

Common REST Operations

Loading Markets

# Load all available trading pairs
exchange.load_markets()

# Access market information
btc_market = exchange.market('BTC/USDT')
print(btc_market['limits']['amount']['min'])  # Minimum order amount

Fetching Ticker

# Single ticker
ticker = exchange.fetch_ticker('BTC/USDT')
print(ticker['last'])      # Last price
print(ticker['bid'])       # Best bid
print(ticker['ask'])       # Best ask
print(ticker['volume'])    # 24h volume

# Multiple tickers (if supported)
tickers = exchange.fetch_tickers(['BTC/USDT', 'ETH/USDT'])

Fetching Order Book

# Full orderbook
orderbook = exchange.fetch_order_book('BTC/USDT')
print(orderbook['bids'][0])  # [price, amount]
print(orderbook['asks'][0])  # [price, amount]

# Limited depth
orderbook = exchange.fetch_order_book('BTC/USDT', 5)  # Top 5 levels

Creating Orders

Limit Order

# Buy limit order
order = exchange.create_limit_buy_order('BTC/USDT', 0.01, 50000)
print(order['id'])

# Sell limit order
order = exchange.create_limit_sell_order('BTC/USDT', 0.01, 60000)

# Generic limit order
order = exchange.create_order('BTC/USDT', 'limit', 'buy', 0.01, 50000)

Market Order

# Buy market order
order = exchange.create_market_buy_order('BTC/USDT', 0.01)

# Sell market order
order = exchange.create_market_sell_order('BTC/USDT', 0.01)

# Generic market order
order = exchange.create_order('BTC/USDT', 'market', 'sell', 0.01)

Fetching Balance

balance = exchange.fetch_balance()
print(balance['BTC']['free'])   # Available balance
print(balance['BTC']['used'])   # Balance in orders
print(balance['BTC']['total'])  # Total balance

Fetching Orders

# Open orders
open_orders = exchange.fetch_open_orders('BTC/USDT')

# Closed orders
closed_orders = exchange.fetch_closed_orders('BTC/USDT')

# All orders (open + closed)
all_orders = exchange.fetch_orders('BTC/USDT')

# Single order by ID
order = exchange.fetch_order(order_id, 'BTC/USDT')

Fetching Trades

# Recent public trades
trades = exchange.fetch_trades('BTC/USDT', limit=10)

# Your trades (requires authentication)
my_trades = exchange.fetch_my_trades('BTC/USDT')

Canceling Orders

# Cancel single order
exchange.cancel_order(order_id, 'BTC/USDT')

# Cancel all orders for a symbol
exchange.cancel_all_orders('BTC/USDT')

WebSocket Operations (Real-time)

Watching Ticker (Live Price Updates)

import asyncio
import ccxt.pro as ccxtpro

async def main():
    exchange = ccxtpro.binance()
    while True:
        ticker = await exchange.watch_ticker('BTC/USDT')
        print(ticker['last'], ticker['timestamp'])
    await exchange.close()

asyncio.run(main())

Watching Order Book (Live Depth Updates)

async def main():
    exchange = ccxtpro.binance()
    while True:
        orderbook = await exchange.watch_order_book('BTC/USDT')
        print('Best bid:', orderbook['bids'][0])
        print('Best ask:', orderbook['asks'][0])
    await exchange.close()

asyncio.run(main())

Watching Trades (Live Trade Stream)

async def main():
    exchange = ccxtpro.binance()
    while True:
        trades = await exchange.watch_trades('BTC/USDT')
        for trade in trades:
            print(trade['price'], trade['amount'], trade['side'])
    await exchange.close()

asyncio.run(main())

Watching Your Orders (Live Order Updates)

async def main():
    exchange = ccxtpro.binance({
        'apiKey': 'YOUR_API_KEY',
        'secret': 'YOUR_SECRET'
    })
    while True:
        orders = await exchange.watch_orders('BTC/USDT')
        for order in orders:
            print(order['id'], order['status'], order['filled'])
    await exchange.close()

asyncio.run(main())

Watching Balance (Live Balance Updates)

async def main():
    exchange = ccxtpro.binance({
        'apiKey': 'YOUR_API_KEY',
        'secret': 'YOUR_SECRET'
    })
    while True:
        balance = await exchange.watch_balance()
        print('BTC:', balance['BTC'])
        print('USDT:', balance['USDT'])
    await exchange.close()

asyncio.run(main())

Watching Multiple Symbols

async def main():
    exchange = ccxtpro.binance()
    symbols = ['BTC/USDT', 'ETH/USDT', 'SOL/USDT']

    while True:
        # Watch all symbols concurrently
        tickers = await exchange.watch_tickers(symbols)
        for symbol, ticker in tickers.items():
            print(symbol, ticker['last'])
    await exchange.close()

asyncio.run(main())

Complete Method Reference

Market Data Methods

Tickers & Prices

  • fetchTicker(symbol) - Fetch ticker for one symbol
  • fetchTickers([symbols]) - Fetch multiple tickers at once
  • fetchBidsAsks([symbols]) - Fetch best bid/ask for multiple symbols
  • fetchLastPrices([symbols]) - Fetch last prices
  • fetchMarkPrices([symbols]) - Fetch mark prices (derivatives)

Order Books

  • fetchOrderBook(symbol, limit) - Fetch order book
  • fetchOrderBooks([symbols]) - Fetch multiple order books
  • fetchL2OrderBook(symbol) - Fetch level 2 order book
  • fetchL3OrderBook(symbol) - Fetch level 3 order book (if supported)

Trades

  • fetchTrades(symbol, since, limit) - Fetch public trades
  • fetchMyTrades(symbol, since, limit) - Fetch your trades (auth required)
  • fetchOrderTrades(orderId, symbol) - Fetch trades for specific order

OHLCV (Candlesticks)

  • fetchOHLCV(symbol, timeframe, since, limit) - Fetch candlestick data
  • fetchIndexOHLCV(symbol, timeframe) - Fetch index price OHLCV
  • fetchMarkOHLCV(symbol, timeframe) - Fetch mark price OHLCV
  • fetchPremiumIndexOHLCV(symbol, timeframe) - Fetch premium index OHLCV

Account & Balance

  • fetchBalance() - Fetch account balance (auth required)
  • fetchAccounts() - Fetch sub-accounts
  • fetchLedger(code, since, limit) - Fetch ledger history
  • fetchLedgerEntry(id, code) - Fetch specific ledger entry
  • fetchTransactions(code, since, limit) - Fetch transactions
  • fetchDeposits(code, since, limit) - Fetch deposit history
  • fetchWithdrawals(code, since, limit) - Fetch withdrawal history
  • fetchDepositsWithdrawals(code, since, limit) - Fetch both deposits and withdrawals

Trading Methods

Creating Orders

  • createOrder(symbol, type, side, amount, price, params) - Create order (generic)
  • createLimitOrder(symbol, side, amount, price) - Create limit order
  • createMarketOrder(symbol, side, amount) - Create market order
  • createLimitBuyOrder(symbol, amount, price) - Buy limit order
  • createLimitSellOrder(symbol, amount, price) - Sell limit order
  • createMarketBuyOrder(symbol, amount) - Buy market order
  • createMarketSellOrder(symbol, amount) - Sell market order
  • createMarketBuyOrderWithCost(symbol, cost) - Buy with specific cost
  • createStopLimitOrder(symbol, side, amount, price, stopPrice) - Stop-limit order
  • createStopMarketOrder(symbol, side, amount, stopPrice) - Stop-market order
  • createStopLossOrder(symbol, side, amount, stopPrice) - Stop-loss order
  • createTakeProfitOrder(symbol, side, amount, takeProfitPrice) - Take-profit order
  • createTrailingAmountOrder(symbol, side, amount, trailingAmount) - Trailing stop
  • createTrailingPercentOrder(symbol, side, amount, trailingPercent) - Trailing stop %
  • createTriggerOrder(symbol, side, amount, triggerPrice) - Trigger order
  • createPostOnlyOrder(symbol, side, amount, price) - Post-only order
  • createReduceOnlyOrder(symbol, side, amount, price) - Reduce-only order
  • createOrders([orders]) - Create multiple orders at once
  • createOrderWithTakeProfitAndStopLoss(symbol, type, side, amount, price, tpPrice, slPrice) - OCO order

Managing Orders

  • fetchOrder(orderId, symbol) - Fetch single order
  • fetchOrders(symbol, since, limit) - Fetch all orders
  • fetchOpenOrders(symbol, since, limit) - Fetch open orders
  • fetchClosedOrders(symbol, since, limit) - Fetch closed orders
  • fetchCanceledOrders(symbol, since, limit) - Fetch canceled orders
  • fetchOpenOrder(orderId, symbol) - Fetch specific open order
  • fetchOrdersByStatus(status, symbol) - Fetch orders by status
  • cancelOrder(orderId, symbol) - Cancel single order
  • cancelOrders([orderIds], symbol) - Cancel multiple orders
  • cancelAllOrders(symbol) - Cancel all orders for symbol
  • editOrder(orderId, symbol, type, side, amount, price) - Modify order

Margin & Leverage

  • fetchBorrowRate(code) - Fetch borrow rate for margin
  • fetchBorrowRates([codes]) - Fetch multiple borrow rates
  • fetchBorrowRateHistory(code, since, limit) - Historical borrow rates
  • fetchCrossBorrowRate(code) - Cross margin borrow rate
  • fetchIsolatedBorrowRate(symbol, code) - Isolated margin borrow rate
  • borrowMargin(code, amount, symbol) - Borrow margin
  • repayMargin(code, amount, symbol) - Repay margin
  • fetchLeverage(symbol) - Fetch leverage
  • setLeverage(leverage, symbol) - Set leverage
  • fetchLeverageTiers(symbols) - Fetch leverage tiers
  • fetchMarketLeverageTiers(symbol) - Leverage tiers for market
  • setMarginMode(marginMode, symbol) - Set margin mode (cross/isolated)
  • fetchMarginMode(symbol) - Fetch margin mode

Derivatives & Futures

Positions

  • fetchPosition(symbol) - Fetch single position
  • fetchPositions([symbols]) - Fetch all positions
  • fetchPositionsForSymbol(symbol) - Fetch positions for symbol
  • fetchPositionHistory(symbol, since, limit) - Position history
  • fetchPositionsHistory(symbols, since, limit) - Multiple position history
  • fetchPositionMode(symbol) - Fetch position mode (one-way/hedge)
  • setPositionMode(hedged, symbol) - Set position mode
  • closePosition(symbol, side) - Close position
  • closeAllPositions() - Close all positions

Funding & Settlement

  • fetchFundingRate(symbol) - Current funding rate
  • fetchFundingRates([symbols]) - Multiple funding rates
  • fetchFundingRateHistory(symbol, since, limit) - Funding rate history
  • fetchFundingHistory(symbol, since, limit) - Your funding payments
  • fetchFundingInterval(symbol) - Funding interval
  • fetchSettlementHistory(symbol, since, limit) - Settlement history
  • fetchMySettlementHistory(symbol, since, limit) - Your settlement history

Open Interest & Liquidations

  • fetchOpenInterest(symbol) - Open interest for symbol
  • fetchOpenInterests([symbols]) - Multiple open interests
  • fetchOpenInterestHistory(symbol, timeframe, since, limit) - OI history
  • fetchLiquidations(symbol, since, limit) - Public liquidations
  • fetchMyLiquidations(symbol, since, limit) - Your liquidations

Options

  • fetchOption(symbol) - Fetch option info
  • fetchOptionChain(code) - Fetch option chain
  • fetchGreeks(symbol) - Fetch option greeks
  • fetchVolatilityHistory(code, since, limit) - Volatility history
  • fetchUnderlyingAssets() - Fetch underlying assets

Fees & Limits

  • fetchTradingFee(symbol) - Trading fee for symbol
  • fetchTradingFees([symbols]) - Trading fees for multiple symbols
  • fetchTradingLimits([symbols]) - Trading limits
  • fetchTransactionFee(code) - Transaction/withdrawal fee
  • fetchTransactionFees([codes]) - Multiple transaction fees
  • fetchDepositWithdrawFee(code) - Deposit/withdrawal fee
  • fetchDepositWithdrawFees([codes]) - Multiple deposit/withdraw fees

Deposits & Withdrawals

  • fetchDepositAddress(code, params) - Get deposit address
  • fetchDepositAddresses([codes]) - Multiple deposit addresses
  • fetchDepositAddressesByNetwork(code) - Addresses by network
  • createDepositAddress(code, params) - Create new deposit address
  • fetchDeposit(id, code) - Fetch single deposit
  • fetchWithdrawal(id, code) - Fetch single withdrawal
  • fetchWithdrawAddresses(code) - Fetch withdrawal addresses
  • fetchWithdrawalWhitelist(code) - Fetch whitelist
  • withdraw(code, amount, address, tag, params) - Withdraw funds
  • deposit(code, amount, params) - Deposit funds (if supported)

Transfer & Convert

  • transfer(code, amount, fromAccount, toAccount) - Internal transfer
  • fetchTransfer(id, code) - Fetch transfer info
  • fetchTransfers(code, since, limit) - Fetch transfer history
  • fetchConvertCurrencies() - Currencies available for convert
  • fetchConvertQuote(fromCode, toCode, amount) - Get conversion quote
  • createConvertTrade(fromCode, toCode, amount) - Execute conversion
  • fetchConvertTrade(id) - Fetch convert trade
  • fetchConvertTradeHistory(code, since, limit) - Convert history

Market Info

  • fetchMarkets() - Fetch all markets
  • fetchCurrencies() - Fetch all currencies
  • fetchTime() - Fetch exchange server time
  • fetchStatus() - Fetch exchange status
  • fetchBorrowInterest(code, symbol, since, limit) - Borrow interest paid
  • fetchLongShortRatio(symbol, timeframe, since, limit) - Long/short ratio
  • fetchLongShortRatioHistory(symbol, timeframe, since, limit) - L/S ratio history

WebSocket Methods (ccxt.pro)

All REST methods have WebSocket equivalents with watch* prefix:

Real-time Market Data

  • watchTicker(symbol) - Watch single ticker
  • watchTickers([symbols]) - Watch multiple tickers
  • watchOrderBook(symbol) - Watch order book updates
  • watchOrderBookForSymbols([symbols]) - Watch multiple order books
  • watchTrades(symbol) - Watch public trades
  • watchOHLCV(symbol, timeframe) - Watch candlestick updates
  • watchBidsAsks([symbols]) - Watch best bid/ask

Real-time Account Data (Auth Required)

  • watchBalance() - Watch balance updates
  • watchOrders(symbol) - Watch your order updates
  • watchMyTrades(symbol) - Watch your trade updates
  • watchPositions([symbols]) - Watch position updates
  • watchPositionsForSymbol(symbol) - Watch positions for symbol

Authentication Required

Methods marked with 🔒 require API credentials:

  • All create* methods (creating orders, addresses)
  • All cancel* methods (canceling orders)
  • All edit* methods (modifying orders)
  • All fetchMy* methods (your trades, orders)
  • fetchBalance, fetchLedger, fetchAccounts
  • withdraw, transfer, deposit
  • Margin/leverage methods
  • Position methods
  • watchBalance, watchOrders, watchMyTrades, watchPositions

Checking Method Availability

Not all exchanges support all methods. Check before using:

// Check if method is supported
if (exchange.has['fetchOHLCV']) {
    const candles = await exchange.fetchOHLCV('BTC/USDT', '1h')
}

// Check multiple capabilities
console.log(exchange.has)
// {
//   fetchTicker: true,
//   fetchOHLCV: true,
//   fetchMyTrades: true,
//   fetchPositions: false,
//   ...
// }

Method Naming Convention

  • fetch* - REST API methods (HTTP requests)
  • watch* - WebSocket methods (real-time streams)
  • create* - Create new resources (orders, addresses)
  • cancel* - Cancel existing resources
  • edit* - Modify existing resources
  • set* - Configure settings (leverage, margin mode)
  • *Ws suffix - WebSocket variant (some exchanges)

Proxy Configuration

CCXT supports HTTP, HTTPS, and SOCKS proxies for both REST and WebSocket connections.

Setting Proxy

// HTTP Proxy
exchange.httpProxy = 'http://your-proxy-host:port'

// HTTPS Proxy  
exchange.httpsProxy = 'https://your-proxy-host:port'

// SOCKS Proxy
exchange.socksProxy = 'socks://your-proxy-host:port'

// Proxy with authentication
exchange.httpProxy = 'http://user:pass@proxy-host:port'

Proxy for WebSocket

WebSocket connections also respect proxy settings:

exchange.httpsProxy = 'https://proxy:8080'
// WebSocket connections will use this proxy

Testing Proxy Connection

exchange.httpProxy = 'http://localhost:8080'
try {
    await exchange.fetchTicker('BTC/USDT')
    console.log('Proxy working!')
} catch (error) {
    console.error('Proxy connection failed:', error)
}

WebSocket-Specific Methods

Some exchanges provide WebSocket variants of REST methods for faster order placement and management. These use the *Ws suffix:

Trading via WebSocket

Creating Orders:

  • createOrderWs - Create order via WebSocket (faster than REST)
  • createLimitOrderWs - Create limit order via WebSocket
  • createMarketOrderWs - Create market order via WebSocket
  • createLimitBuyOrderWs - Buy limit order via WebSocket
  • createLimitSellOrderWs - Sell limit order via WebSocket
  • createMarketBuyOrderWs - Buy market order via WebSocket
  • createMarketSellOrderWs - Sell market order via WebSocket
  • createStopLimitOrderWs - Stop-limit order via WebSocket
  • createStopMarketOrderWs - Stop-market order via WebSocket
  • createStopLossOrderWs - Stop-loss order via WebSocket
  • createTakeProfitOrderWs - Take-profit order via WebSocket
  • createTrailingAmountOrderWs - Trailing stop via WebSocket
  • createTrailingPercentOrderWs - Trailing stop % via WebSocket
  • createPostOnlyOrderWs - Post-only order via WebSocket
  • createReduceOnlyOrderWs - Reduce-only order via WebSocket

Managing Orders:

  • editOrderWs - Edit order via WebSocket
  • cancelOrderWs - Cancel order via WebSocket (faster than REST)
  • cancelOrdersWs - Cancel multiple orders via WebSocket
  • cancelAllOrdersWs - Cancel all orders via WebSocket

Fetching Data:

  • fetchOrderWs - Fetch order via WebSocket
  • fetchOrdersWs - Fetch orders via WebSocket
  • fetchOpenOrdersWs - Fetch open orders via WebSocket
  • fetchClosedOrdersWs - Fetch closed orders via WebSocket
  • fetchMyTradesWs - Fetch your trades via WebSocket
  • fetchBalanceWs - Fetch balance via WebSocket
  • fetchPositionWs - Fetch position via WebSocket
  • fetchPositionsWs - Fetch positions via WebSocket
  • fetchPositionsForSymbolWs - Fetch positions for symbol via WebSocket
  • fetchTradingFeesWs - Fetch trading fees via WebSocket

When to Use WebSocket Methods

Use *Ws methods when:

  • You need faster order placement (lower latency)
  • You're already connected via WebSocket
  • You want to reduce REST API rate limit usage
  • Trading strategies require sub-100ms latency

Use REST methods when:

  • You need guaranteed execution confirmation
  • You're making one-off requests
  • The exchange doesn't support the WebSocket variant
  • You need detailed error responses

Example: Order Placement Comparison

REST API (slower, more reliable):

const order = await exchange.createOrder('BTC/USDT', 'limit', 'buy', 0.01, 50000)

WebSocket API (faster, lower latency):

const order = await exchange.createOrderWs('BTC/USDT', 'limit', 'buy', 0.01, 50000)

Checking WebSocket Method Availability

Not all exchanges support WebSocket trading methods:

if (exchange.has['createOrderWs']) {
    // Exchange supports WebSocket order creation
    const order = await exchange.createOrderWs('BTC/USDT', 'limit', 'buy', 0.01, 50000)
} else {
    // Fall back to REST
    const order = await exchange.createOrder('BTC/USDT', 'limit', 'buy', 0.01, 50000)
}

Authentication

Setting API Keys

import os

# During instantiation (recommended)
exchange = ccxt.binance({
    'apiKey': os.environ.get('BINANCE_API_KEY'),
    'secret': os.environ.get('BINANCE_SECRET'),
    'enableRateLimit': True
})

# After instantiation
exchange.apiKey = os.environ.get('BINANCE_API_KEY')
exchange.secret = os.environ.get('BINANCE_SECRET')

Testing Authentication

try:
    balance = exchange.fetch_balance()
    print('Authentication successful!')
except ccxt.AuthenticationError:
    print('Invalid API credentials')

Error Handling

Exception Hierarchy

BaseError
├─ NetworkError (recoverable - retry)
│  ├─ RequestTimeout
│  ├─ ExchangeNotAvailable
│  ├─ RateLimitExceeded
│  └─ DDoSProtection
└─ ExchangeError (non-recoverable - don't retry)
   ├─ AuthenticationError
   ├─ InsufficientFunds
   ├─ InvalidOrder
   └─ NotSupported

Basic Error Handling

import ccxt

try:
    ticker = exchange.fetch_ticker('BTC/USDT')
except ccxt.NetworkError as e:
    print('Network error - retry:', str(e))
except ccxt.ExchangeError as e:
    print('Exchange error - do not retry:', str(e))
except Exception as e:
    print('Unknown error:', str(e))

Specific Exception Handling

try:
    order = exchange.create_order('BTC/USDT', 'limit', 'buy', 0.01, 50000)
except ccxt.InsufficientFunds:
    print('Not enough balance')
except ccxt.InvalidOrder:
    print('Invalid order parameters')
except ccxt.RateLimitExceeded:
    print('Rate limit hit - wait before retrying')
    exchange.sleep(1000)  # Wait 1 second
except ccxt.AuthenticationError:
    print('Check your API credentials')

Retry Logic for Network Errors

def fetch_with_retry(max_retries=3):
    for i in range(max_retries):
        try:
            return exchange.fetch_ticker('BTC/USDT')
        except ccxt.NetworkError:
            if i < max_retries - 1:
                print(f'Retry {i + 1}/{max_retries}')
                exchange.sleep(1000 * (i + 1))  # Exponential backoff
            else:
                raise

Async vs Sync

When to Use Sync

  • Simple scripts
  • Single exchange operations
  • Jupyter notebooks
  • Quick testing

When to Use Async

  • Multiple concurrent operations
  • WebSocket connections (required)
  • High-performance trading bots
  • Multiple exchange monitoring

Sync Example

import ccxt

exchange = ccxt.binance({'enableRateLimit': True})
ticker = exchange.fetch_ticker('BTC/USDT')
print(ticker['last'])

Async Example

import asyncio
import ccxt.async_support as ccxt

async def main():
    exchange = ccxt.binance({'enableRateLimit': True})
    ticker = await exchange.fetch_ticker('BTC/USDT')
    print(ticker['last'])
    await exchange.close()

asyncio.run(main())

Multiple Exchanges Async

async def fetch_all():
    exchanges = [
        ccxt.binance({'enableRateLimit': True}),
        ccxt.coinbase({'enableRateLimit': True}),
        ccxt.kraken({'enableRateLimit': True})
    ]

    # Fetch concurrently
    tasks = [ex.fetch_ticker('BTC/USDT') for ex in exchanges]
    tickers = await asyncio.gather(*tasks, return_exceptions=True)

    for ex, ticker in zip(exchanges, tickers):
        if isinstance(ticker, Exception):
            print(f'{ex.id}: ERROR - {ticker}')
        else:
            print(f'{ex.id}: ${ticker["last"]}')
        await ex.close()

asyncio.run(fetch_all())

Rate Limiting

Built-in Rate Limiter (Recommended)

exchange = ccxt.binance({
    'enableRateLimit': True  # Automatically throttles requests
})

Manual Delays

exchange.fetch_ticker('BTC/USDT')
exchange.sleep(1000)  # Wait 1 second (milliseconds)
exchange.fetch_ticker('ETH/USDT')

Checking Rate Limit

print(exchange.rateLimit)  # Milliseconds between requests

Common Pitfalls

Forgetting await in Async Mode

# Wrong - returns coroutine, not data
async def wrong():
    ticker = exchange.fetch_ticker('BTC/USDT')  # Missing await!
    print(ticker['last'])  # ERROR

# Correct
async def correct():
    ticker = await exchange.fetch_ticker('BTC/USDT')
    print(ticker['last'])  # Works!

Using Sync for WebSocket

# Wrong - WebSocket requires async
import ccxt.pro as ccxtpro
exchange = ccxtpro.binance()
ticker = exchange.watch_ticker('BTC/USDT')  # ERROR: Need await!

# Correct
import asyncio
import ccxt.pro as ccxtpro

async def main():
    exchange = ccxtpro.binance()
    ticker = await exchange.watch_ticker('BTC/USDT')
    await exchange.close()

asyncio.run(main())

Not Closing Async Exchange

# Wrong - resource leak
async def wrong():
    exchange = ccxt.binance()
    await exchange.fetch_ticker('BTC/USDT')
    # Forgot to close!

# Correct
async def correct():
    exchange = ccxt.binance()
    try:
        await exchange.fetch_ticker('BTC/USDT')
    finally:
        await exchange.close()

Using Sync in Async Code

# Wrong - blocks event loop
async def wrong():
    exchange = ccxt.binance()  # Sync import!
    ticker = exchange.fetch_ticker('BTC/USDT')  # Blocking!

# Correct
import ccxt.async_support as ccxt

async def correct():
    exchange = ccxt.binance()
    ticker = await exchange.fetch_ticker('BTC/USDT')
    await exchange.close()

Using REST for Real-time Monitoring

# Wrong - wastes rate limits
while True:
    ticker = exchange.fetch_ticker('BTC/USDT')  # REST
    print(ticker['last'])
    exchange.sleep(1000)

# Correct - use WebSocket
import ccxt.pro as ccxtpro

async def correct():
    exchange = ccxtpro.binance()
    while True:
        ticker = await exchange.watch_ticker('BTC/USDT')  # WebSocket
        print(ticker['last'])
    await exchange.close()

Troubleshooting

Common Issues

1. "ModuleNotFoundError: No module named 'ccxt'"

  • Solution: Run pip install ccxt

2. "RateLimitExceeded"

  • Solution: Enable rate limiter: 'enableRateLimit': True
  • Or add manual delays between requests

3. "AuthenticationError"

  • Solution: Check API key and secret
  • Verify API key permissions on exchange
  • Check system clock is synced (use NTP)

4. "InvalidNonce"

  • Solution: Sync system clock
  • Use only one exchange instance per API key

5. "InsufficientFunds"

  • Solution: Check available balance (balance['BTC']['free'])
  • Account for trading fees

6. "ExchangeNotAvailable"

  • Solution: Check exchange status/maintenance
  • Retry after a delay

7. SSL/Certificate errors

  • Solution: Update certifi: pip install --upgrade certifi

8. Slow performance

  • Solution: Install performance enhancements:
    • pip install orjson (faster JSON)
    • pip install coincurve (faster signing)

Debugging

# Enable verbose logging
exchange.verbose = True

# Check exchange capabilities
print(exchange.has)
# {
#   'fetchTicker': True,
#   'fetchOrderBook': True,
#   'createOrder': True,
#   ...
# }

# Check market information
print(exchange.markets['BTC/USDT'])

# Check last request/response
print(exchange.last_http_response)
print(exchange.last_json_response)

Learn More

general reviews

Ratings

4.510 reviews
  • Shikha Mishra· Oct 10, 2024

    ccxt-python is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.

  • Piyush G· Sep 9, 2024

    Keeps context tight: ccxt-python is the kind of skill you can hand to a new teammate without a long onboarding doc.

  • Chaitanya Patil· Aug 8, 2024

    Registry listing for ccxt-python matched our evaluation — installs cleanly and behaves as described in the markdown.

  • Sakshi Patil· Jul 7, 2024

    ccxt-python reduced setup friction for our internal harness; good balance of opinion and flexibility.

  • Ganesh Mohane· Jun 6, 2024

    I recommend ccxt-python for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.

  • Oshnikdeep· May 5, 2024

    Useful defaults in ccxt-python — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.

  • Dhruvi Jain· Apr 4, 2024

    ccxt-python has been reliable in day-to-day use. Documentation quality is above average for community skills.

  • Rahul Santra· Mar 3, 2024

    Solid pick for teams standardizing on skills: ccxt-python is focused, and the summary matches what you get after install.

  • Pratham Ware· Feb 2, 2024

    We added ccxt-python from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.

  • Yash Thakker· Jan 1, 2024

    ccxt-python fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.