Official DexPaprika Python SDK: Pythonic access to cross-chain DEX data, prices, and pools with type hints and caching.
DexPaprika Python SDK
A Python client for the DexPaprika API. This SDK provides easy access to real-time data from decentralized exchanges across multiple blockchain networks.
Features
- Access data from 36 blockchain networks
- Query information about DEXes, liquidity pools, and tokens
- Get detailed price information, trading volume, and transactions
- Filter pools and tokens by volume, liquidity, FDV, transactions, and creation date
- Get top tokens on any network ranked by volume or other metrics
- Batch price lookups for up to 10 tokens in a single request
- Search across the entire DexPaprika ecosystem
- Automatic parameter validation with clear error messages
- Type-safe response objects using Pydantic models
- Built-in retry with exponential backoff for API failures
- Intelligent caching system with TTL-based expiration
Installation
# Install via pip
pip install dexpaprika-sdk
Or install from source
git clone https://github.com/coinpaprika/dexpaprika-sdk-python.git
cd dexpaprika-sdk-python
pip install -e .
Migration Guide (v0.6.0)
Important: DexPaprika removed GET /networks/{network}/tokens/{address}/pools (it now returns 410 Gone). tokens.get_pools() was repointed to /networks/{network}/pools/search with its new token_address parameter:
- The method signature is unchanged; the response is now the cursor-paginated
results, .pools remains a backward-compatible
alias). page is accepted but ignored; pass cursor=... to page.
- The token filter is network-scoped only. The cross-network
/pools/search
tokenaddress but silently ignores it, so getpools()
still requires a network.
- The
address(pair queries) andreorder(pair-perspective flip) parameters
/pools/search equivalent. They are deprecated, warn, and are not
sent. Repeating token_address on the API side is last-wins, not a pair
filter, so filter the returned pools client-side to match a pair.
- An unknown token address returns an empty result set, not an error.
pools = client.tokens.get_pools("ethereum", "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", limit=5)
for p in pools.results:
print(p.id, p.volumeusd24h)
if pools.hasnextpage:
more = client.tokens.get_pools(
"ethereum", "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
limit=5, cursor=pools.next_cursor,
)
Migration Guide (v0.5.0)
Important: DexPaprika removed four REST endpoints (they now return 410 Gone) and replaced them with unified search endpoints. The SDK was repointed accordingly:
pools.listbynetwork()andpools.filter()now call/networks/{network}/pools/searchtokens.get_top()andtokens.filter()now call/networks/{network}/tokens/search
orderby / sortby / sort_dir
values keep working; legacy sort fields and filter names are mapped to the new
canonical ones automatically). What changed is the response shape:
- Responses now expose rows under
results(withhasnextpageandnext_cursor)
pools / tokens / page_info. The old .pools / .tokens
attributes remain as backward-compatible aliases for .results.
- Pagination is cursor-based.
pageis still accepted for backward compatibility
cursor=... to page through results.
- Pool items:
idis the pool address, volume is split into
volumeusd24h / volumeusd7d / volumeusd30d, transactions are
transactions24h, and price moves are pricechangepercentage5m/1h/6h/24h.
- Token items are flat and identified by
address(noname/symbol, no nested
priceusd, volumeusd24h/7d/30d, liquidityusd,
fdvusd, txns24h, pricechangepercentage_24h.
# Before:
pools = client.pools.listbynetwork("ethereum")
for p in pools.pools:
print(p.volume_usd)
After:
pools = client.pools.listbynetwork("ethereum")
for p in pools.results: # .pools still works as an alias
print(p.volumeusd24h)
Migration Guide (v0.3.0)
Important: Version 0.3.0 includes breaking changes due to DexPaprika API v1.3.0 updates.
Global Pools Endpoint Deprecation
The global /pools endpoint has been removed. If you were using client.pools.list(), you need to update your code:
Before (deprecated):
# This method is deprecated and will show warnings pools = client.pools.list(limit=10)
After (recommended):
# Use network-specific methods instead ethpools = client.pools.listby_network("ethereum", limit=10) solanapools = client.pools.listby_network("solana", limit=10)
Backward Compatibility
For backward compatibility, the deprecated pools.list() method will:
- Show deprecation warnings
- Automatically fall back to Ethereum network
- Continue working until a future version
Usage
Basic Example
from dexpaprika_sdk import DexPaprikaClient
Create a new client
client = DexPaprikaClient()
Get a list of supported networks
networks = client.networks.list()
for network in networks:
print(f"- {network.display_name} ({network.id})")
Get stats about the DexPaprika ecosystem
stats = client.utils.get_stats()
print(f"DexPaprika stats: {stats.chains} chains, {stats.pools} pools")
Get top pools by volume (network-specific)
pools = client.pools.listbynetwork(
network_id="ethereum",
limit=5,
orderby="volumeusd_24h",
sort="desc"
)
for pool in pools.results:
token_pair = f"{pool.tokens[0].symbol}/{pool.tokens[1].symbol}" if len(pool.tokens) >= 2 else "Unknown Pair"
print(f"- {tokenpair} on {pool.dexname} ({pool.chain}): ${pool.volumeusd24h or 0:,.2f} volume")
Advanced Examples
Get pools for a specific network
# Get top Ethereum pools
ethpools = client.pools.listby_network(
network_id="ethereum",
limit=5,
orderby="volumeusd_24h",
sort="desc"
)
Rows are under results; pagination is cursor-based (hasnextpage / next_cursor)
Get pools for a specific DEX
# Get top Uniswap V3 pools on Ethereum
uniswappools = client.pools.listby_dex(
network_id="ethereum",
dexid="uniswapv3",
limit=5,
orderby="volumeusd",
sort="desc"
)
Get details for a specific pool
# Get details for a specific pool
pooldetails = client.pools.getdetails(
network_id="ethereum",
pool_address="0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640" # USDC/WETH Uniswap v3 pool
)
Get OHLCV data for a pool
from datetime import datetime, timedelta
Get OHLCV data for the last 7 days
end_date = datetime.now()
startdate = enddate - timedelta(days=7)
ohlcvdata = client.pools.getohlcv(
network_id="ethereum",
pool_address="0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640",
start=start_date.strftime("%Y-%m-%d"),
end=end_date.strftime("%Y-%m-%d"),
interval="24h",
limit=7
)
Filter pools by metrics
# Find high-volume Ethereum pools
filtered = client.pools.filter(
network_id="ethereum",
volume24hmin=100000,
txns24hmin=50,
sortby="volume24h",
sort_dir="desc",
limit=10
)
for pool in filtered.results:
token_pair = f"{pool.tokens[0].symbol}/{pool.tokens[1].symbol}" if len(pool.tokens) >= 2 else "Unknown"
print(f"- {tokenpair}: ${pool.volumeusd_24h or 0:,.0f} volume")
Sort and filter by price move
Pools can be sorted and filtered on four price-change windows: 24h, 6h, 1h and 5m. Pass the window to sortby / orderby, or bound it with the matching min / max filter. Tokens support the 24h window only; the table further down has the exact split.
# Biggest 5-minute movers on Ethereum
movers = client.pools.listbynetwork(
network_id="ethereum",
orderby="pricechangepercentage5m",
sort="desc",
limit=10
)
for pool in movers.results:
print(f"- {pool.id}: {pool.pricechangepercentage_5m or 0:+.2f}% in 5m")
Pools down at least 20% on the day, with real liquidity behind them.
Bounds are percentages, so a drop is a negative *_max.
dumping = client.pools.filter(
network_id="ethereum",
pricechangepercentage24hmax=-20,
liquidityusdmin=50000,
limit=10
)
for pool in dumping.results:
print(f"- {pool.id}: {pool.pricechangepercentage_24h or 0:.2f}% 24h")
Combine bounds to find a short spike that has not yet shown up in the day
spiking = client.pools.filter(
network_id="ethereum",
pricechangepercentage1hmin=50,
pricechangepercentage24hmax=10,
limit=10
)
Available bounds on pools.filter(): pricechangepercentage24hmin / max, pricechangepercentage6hmin / max, pricechangepercentage1hmin / max, pricechangepercentage5m_min / _max.
The token side is narrower, and the line falls in a different place for sorting than for filtering:
| | pools | tokens | |---|---|---| | sort by pricechangepercentage_24h | yes | yes | | sort by 6h, 1h, _5m | yes | no, HTTP 400 | | filter on pricechangepercentage24hmin / _max | yes | yes | | filter on 6h, 1h, _5m bounds | yes | 200, then ignored |
So tokens.get_top() and tokens.filter() take the 24h window and nothing shorter. /networks/{network}/tokens/search rejects the short windows as sort fields with HTTP 400, and token rows carry no 5m field at all. A short window handed to a token method as orderby falls back to volumeusd_24h rather than failing.
The short bounds are a nastier case on the filter side. /tokens/search answers 200 to pricechangepercentage6hmin and then ignores it, returning a full unfiltered page that looks filtered, so tokens.filter() does not accept those three at all. Passing one raises TypeError in your process instead of handing you wrong rows.
# Tokens up at least 20% on the day, ordered by volume
movers = client.tokens.filter(
network_id="ethereum",
pricechangepercentage24hmin=20,
limit=10
)
for token in movers.results:
print(f"- {token.address}: {token.pricechangepercentage_24h or 0:+.2f}% 24h")
Get top tokens on a network
# Get top tokens by volume on Ethereum
The flat search shape identifies a token by address (no name/symbol); rows
are under results.
top = client.tokens.gettop("ethereum", orderby="volume_24h", limit=5)
for token in top.results:
print(f"- {token.address}: ${token.priceusd or 0:.4f} (24h vol: ${token.volumeusd_24h or 0:,.0f})")
Filter tokens by criteria
# Find tokens with high volume and FDV
filtered = client.tokens.filter(
network_id="ethereum",
volume24hmin=100000,
fdv_min=1000000,
limit=10
)
for token in filtered.results:
print(f"- {token.address}: ${token.volumeusd24h or 0:,.0f} vol, ${token.fdv_usd or 0:,.0f} FDV")
Get batch prices for multiple tokens
# Get prices for WETH and USDC in one request
prices = client.tokens.getmultiprices(
network_id="ethereum",
tokens=[
"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", # WETH
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", # USDC
]
)
for p in prices:
print(f"- {p.id}: ${p.price_usd:.4f}")
Get tokens and pools by search query
# Search for "bitcoin" across the ecosystem
search_results = client.search.search("bitcoin")
print(f"Found {len(searchresults.tokens)} tokens and {len(searchresults.pools)} pools")
Caching System
The SDK includes an intelligent caching system that helps reduce API calls and improve performance:
# Caching is enabled by default for all GET requests
First request will be fetched from the API
networks = client.networks.list()
Subsequent requests will use the cached data (faster)
cached_networks = client.networks.list()
You can skip the cache when you need fresh data
freshnetworks = client.networks.get("/networks", skip_cache=True)
Clear the entire cache
client.clear_cache()
Clear cache only for specific endpoints
client.clearcache(endpointprefix="/networks")
Different types of data have different cache durations:
- Network data: 24 hours
- Pool data: 5 minutes
- Token data: 10 minutes
- Statistics: 15 minutes
- Other data: 5 minutes (default)
Retry with Backoff
The SDK automatically retries failed API requests with exponential backoff:
# Create a client with custom retry settings
client = DexPaprikaClient(
max_retries=4, # Number of retry attempts (default: 4)
backoff_times=[0.1, 0.5, 1.0, 5.0] # Backoff times in seconds
)
All API requests will now use these retry settings
The SDK will retry automatically on connection errors and server errors (5xx)
Default retry behavior:
- Retries up to 4 times on connection errors, timeouts, and server errors (5xx)
- Uses backoff intervals of 100ms, 500ms, 1s, and 5s with random jitter
- Does not retry on client errors (4xx) like 404 or 403
Parameter Validation
The SDK automatically validates parameters before making API requests to help you avoid errors:
# Invalid parameter examples will raise helpful error messages
try:
# Invalid network ID
client.pools.listbynetwork(network_id="", limit=5)
except ValueError as e:
print(e) # "network_id is required"
try:
# Invalid sort parameter
client.pools.list(sort="invalid_sort")
except ValueError as e:
print(e) # "sort must be one of: asc, desc"
try:
# Invalid limit parameter
client.pools.list(limit=500)
except ValueError as e:
print(e) # "limit must be at most 100"
Error Handling
Handle API errors gracefully by using try/except blocks:
try:
# Try to fetch pool details
pooldetails = client.pools.getdetails(
network_id="ethereum",
pool_address="0xInvalidAddress"
)
except Exception as e:
if "404" in str(e):
print("Pool not found")
elif "429" in str(e):
print("Rate limit exceeded")
else:
print(f"An error occurred: {e}")
Working with Models
All API responses are converted to typed Pydantic models for easier access and better code reliability:
# Get pool details
pool = client.pools.get_details(
network_id="ethereum",
pool_address="0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640"
)
Access pool properties
print(f"Pool: {pool.tokens[0].symbol}/{pool.tokens[1].symbol}")
print(f"Volume (24h): ${pool.day.volume_usd:.2f}")
print(f"Transactions (24h): {pool.day.txns}")
print(f"Price: ${pool.lastpriceusd:.4f}")
Time interval data is available for multiple timeframes
print(f"1h price change: {pool.hour1.lastpriceusd_change:.2f}%")
print(f"24h price change: {pool.day.lastpriceusd_change:.2f}%")
API Reference
The SDK provides the following main components:
NetworksAPI: Access information about supported blockchain networksPoolsAPI: Query data about liquidity pools across networks, filter pools by metricsTokensAPI: Access token information, top tokens, filter tokens, batch price lookupsDexesAPI: Get information about decentralized exchangesSearchAPI: Search for tokens, pools, and DEXesUtilsAPI: Utility endpoints like global statistics
Publishing
For developers contributing to this package, here's how to publish a new version:
- Update the version in
dexpaprika_sdk/init.py - Update the
CHANGELOG.md - Create a new release in GitHub
- GitHub Actions will automatically build and publish to PyPI
Development Setup
# Clone the repository
git clone https://github.com/coinpaprika/dexpaprika-sdk-python.git
cd dexpaprika-sdk-python
Create a virtual environment (optional)
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
Install dev dependencies
pip install -e ".[dev]"
Running Tests
# Run tests with pytest
pytest
Run with coverage
pytest --cov=dexpaprika_sdk tests/
Resources
- Official Documentation - Comprehensive API reference
- DexPaprika Website - Main product website
- CoinPaprika - Related cryptocurrency data platform
- Discord Community - Get support and connect with other developers
- PyPI Package - Python package details
License
MIT License