Fetching Historical Trades with CCXT: Limits and Alternatives
CCXT is the standard Python library for connecting to crypto exchange APIs. When it comes to historical tick data, it has hard limits that most developers hit quickly.
What fetch_trades Actually Returns
import ccxt
exchange = ccxt.binance()
trades = exchange.fetch_trades("BTC/USDT", limit=1000)
print(f"Got {len(trades)} trades")
print(f"Oldest: {trades[0]['datetime']}")
Maximum 1,000 recent trades. For BTC/USDT on a busy exchange, that is roughly 10-30 seconds of activity. Most exchanges limit REST API historical access to 24-72 hours.
Paginating with since — The Practical Limit
import ccxt, time
exchange = ccxt.binance()
all_trades, since = [], exchange.parse8601("2026-01-01T00:00:00Z")
while True:
trades = exchange.fetch_trades("BTC/USDT", since=since, limit=1000)
if not trades: break
all_trades.extend(trades)
since = trades[-1]["timestamp"] + 1
time.sleep(exchange.rateLimit / 1000)
Fetching one full year via this loop requires ~2-3 million API calls and takes weeks. Most exchanges cut off historical access after a certain date anyway.
The Alternative: Bulk Archives
For any project requiring more than a few days of data, bulk archives are the only practical option — complete history in compressed files, downloadable in hours, no rate limiting. The tradeoff: you need to verify data quality, or use a dataset that has already been audited.
Summary
CCXT’s fetch_trades is excellent for live trading and very recent data. For historical research spanning months or years, bulk archives are the correct approach. Once you have the data in Parquet, converting it to any format your tools expect is a short script.