Mempool Streaming API
Monitor pending transactions in real-time via WebSocket or REST API. The mempool API provides transaction classification, MEV opportunity detection, and flexible filtering for trading bots.
Key Features
- Real-time streaming - WebSocket connection for instant updates
- Transaction classification - Automatic categorization (swap, liquidation, transfer, etc.)
- MEV detection - Identifies arbitrage, sandwich, and backrun opportunities
- Flexible filtering - Filter by type, value, gas price, or DEX protocol
- DEX decoding - Extracts swap details from Uniswap, SushiSwap, etc.
Supported Chains
WebSocket Streaming
Connect
wss://api.axol.io/api/v1/mempool/{chain}/stream
Requires authentication via X-API-Key header.
Subscribe
After connecting, send a subscription message:
{
"action": "subscribe",
"filter": {
"tx_types": ["swap", "liquidation"],
"min_value_eth": 1.0,
"min_gas_price_gwei": 20,
"dex_protocols": ["uniswap_v3", "uniswap_v2"],
"include_mev": true
}
}
Filter Options
| Field | Type | Description |
|---|---|---|
tx_types | string[] | Filter by transaction type |
min_value_eth | float | Minimum transaction value in ETH |
min_gas_price_gwei | float | Minimum gas price |
max_gas_price_gwei | float | Maximum gas price |
dex_protocols | string[] | Filter by DEX (uniswap_v2, uniswap_v3, sushiswap) |
addresses | string[] | Filter by from/to addresses |
include_mev | boolean | Only include txs with MEV opportunities |
Transaction Types
| Type | Description |
|---|---|
swap | DEX swap transactions |
liquidation | Lending protocol liquidations |
transfer | Token transfers |
flashloan | Flash loan operations |
bridge | Cross-chain bridge transactions |
nft | NFT trades and mints |
contract_deploy | Contract deployments |
other | Unclassified |
Message Format
Connected
{
"type": "connected",
"chain": "ethereum",
"pending_count": 5432
}
Subscribed
{
"type": "subscribed",
"subscription_id": "sub_abc123",
"filter": {...}
}
Transaction
{
"type": "transaction",
"data": {
"hash": "0xabc...",
"from": "0x123...",
"to": "0x456...",
"value_eth": 10.5,
"gas_price_gwei": 25.0,
"gas_limit": 250000,
"nonce": 42,
"input_data": "0x...",
"tx_type": "swap",
"timestamp": "2026-01-15T10:30:00Z",
"priority_score": 85,
"swap_details": {
"dex": "uniswap_v3",
"token_in": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"token_out": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"amount_in": "10.5",
"amount_out_min": "25000.0",
"path": ["WETH", "USDC"]
},
"mev_opportunity": {
"type": "sandwich",
"estimated_profit_eth": 0.05,
"confidence": 0.8
}
}
}
REST Endpoints
Get Mempool Status
GET /v1/mempool/{chain}/status
curl -H "X-API-Key: YOUR_KEY" \
https://api.axol.io/api/v1/mempool/ethereum/status
Response:
{
"chain": "ethereum",
"connected": true,
"subscriber_count": 42,
"pending_count": 5432
}
Get Mempool Statistics
GET /v1/mempool/{chain}/stats
Returns aggregate statistics about the current mempool state.
{
"chain": "ethereum",
"timestamp": "2026-01-15T10:30:00Z",
"total_pending": 5432,
"gas_prices": {
"min_gwei": 10,
"avg_gwei": 25,
"max_gwei": 150,
"median_gwei": 22
},
"tx_counts": {
"swap": 1245,
"transfer": 2567,
"liquidation": 23,
"other": 1597
},
"mev_opportunities": {
"arbitrage": 12,
"sandwich": 5,
"liquidation": 8
},
"total_value_eth": 15432.5
}
Get Pending Transactions
GET /v1/mempool/{chain}/pending
Query parameters:
limit(int, 1-1000): Maximum transactions to returntx_type(string): Filter by typemin_value_eth(float): Minimum valuemin_gas_price_gwei(float): Minimum gas pricemev_only(boolean): Only MEV opportunities
curl -H "X-API-Key: YOUR_KEY" \
"https://api.axol.io/api/v1/mempool/ethereum/pending?limit=50&tx_type=swap&min_value_eth=5"
Get Pending Swaps
GET /v1/mempool/{chain}/swaps
Convenience endpoint for DEX swap transactions.
Query parameters:
limit(int, 1-500): Maximum swapsmin_value_eth(float): Minimum valuedex(string): Filter by DEX (uniswap_v2, uniswap_v3, sushiswap)
Get Pending Liquidations
GET /v1/mempool/{chain}/liquidations
Returns pending liquidation transactions from lending protocols.
Code Examples
Python - WebSocket Streaming
import asyncio
import websockets
import json
import os
API_KEY = os.getenv("AXOL_API_KEY")
async def stream_mempool():
uri = "wss://api.axol.io/api/v1/mempool/ethereum/stream"
headers = {"X-API-Key": API_KEY}
async with websockets.connect(uri, extra_headers=headers) as ws:
# Subscribe with filters
await ws.send(json.dumps({
"action": "subscribe",
"filter": {
"tx_types": ["swap"],
"min_value_eth": 5.0,
"dex_protocols": ["uniswap_v3"]
}
}))
async for message in ws:
data = json.loads(message)
if data["type"] == "connected":
print(f"Connected! Pending: {data['pending_count']}")
elif data["type"] == "subscribed":
print(f"Subscribed: {data['subscription_id']}")
elif data["type"] == "transaction":
tx = data["data"]
print(f"\nNew swap detected:")
print(f" Hash: {tx['hash'][:20]}...")
print(f" Value: {tx['value_eth']} ETH")
print(f" Gas: {tx['gas_price_gwei']} gwei")
if tx.get("swap_details"):
swap = tx["swap_details"]
print(f" DEX: {swap['dex']}")
print(f" Path: {' -> '.join(swap['path'])}")
if tx.get("mev_opportunity"):
mev = tx["mev_opportunity"]
print(f" MEV: {mev['type']} ({mev['estimated_profit_eth']} ETH)")
asyncio.run(stream_mempool())
TypeScript - WebSocket Streaming
import WebSocket from 'ws';
interface MempoolTransaction {
hash: string;
from: string;
to: string;
value_eth: number;
gas_price_gwei: number;
tx_type: string;
swap_details?: {
dex: string;
token_in: string;
token_out: string;
path: string[];
};
mev_opportunity?: {
type: string;
estimated_profit_eth: number;
};
}
const API_KEY = process.env.AXOL_API_KEY!;
function streamMempool() {
const ws = new WebSocket('wss://api.axol.io/api/v1/mempool/ethereum/stream', {
headers: { 'X-API-Key': API_KEY }
});
ws.on('open', () => {
ws.send(JSON.stringify({
action: 'subscribe',
filter: {
tx_types: ['swap'],
min_value_eth: 5.0
}
}));
});
ws.on('message', (data) => {
const msg = JSON.parse(data.toString());
if (msg.type === 'transaction') {
const tx: MempoolTransaction = msg.data;
console.log(`Swap: ${tx.hash.slice(0, 20)}... | ${tx.value_eth} ETH`);
if (tx.mev_opportunity) {
console.log(` MEV: ${tx.mev_opportunity.type}`);
}
}
});
ws.on('error', (error) => {
console.error('WebSocket error:', error);
});
ws.on('close', () => {
console.log('Connection closed, reconnecting...');
setTimeout(streamMempool, 5000);
});
}
streamMempool();
Python - MEV Opportunity Handler
import asyncio
import websockets
import json
class MempoolMonitor:
def __init__(self, api_key: str, chain: str = "ethereum"):
self.api_key = api_key
self.chain = chain
self.uri = f"wss://api.axol.io/api/v1/mempool/{chain}/stream"
async def on_mev_opportunity(self, tx: dict) -> None:
"""Handle detected MEV opportunity."""
mev = tx["mev_opportunity"]
print(f"MEV Detected: {mev['type']}")
print(f" Profit: {mev['estimated_profit_eth']} ETH")
print(f" Confidence: {mev['confidence']}")
if mev["type"] == "sandwich":
await self.handle_sandwich(tx)
elif mev["type"] == "arbitrage":
await self.handle_arbitrage(tx)
elif mev["type"] == "liquidation":
await self.handle_liquidation(tx)
async def handle_sandwich(self, tx: dict) -> None:
"""Handle sandwich opportunity."""
# Your sandwich logic here
pass
async def handle_arbitrage(self, tx: dict) -> None:
"""Handle arbitrage opportunity."""
# Your arbitrage logic here
pass
async def handle_liquidation(self, tx: dict) -> None:
"""Handle liquidation opportunity."""
# Your liquidation logic here
pass
async def run(self) -> None:
"""Run the mempool monitor."""
headers = {"X-API-Key": self.api_key}
while True:
try:
async with websockets.connect(
self.uri,
extra_headers=headers,
ping_interval=30
) as ws:
await ws.send(json.dumps({
"action": "subscribe",
"filter": {"include_mev": True}
}))
async for message in ws:
data = json.loads(message)
if data["type"] == "transaction":
tx = data["data"]
if tx.get("mev_opportunity"):
await self.on_mev_opportunity(tx)
except Exception as e:
print(f"Connection error: {e}, reconnecting...")
await asyncio.sleep(5)
# Usage
monitor = MempoolMonitor(api_key=os.getenv("AXOL_API_KEY"))
asyncio.run(monitor.run())
MEV Opportunity Types
Arbitrage
Price discrepancy detected across DEXes:
{
"type": "arbitrage",
"estimated_profit_eth": 0.1,
"confidence": 0.9,
"details": {
"dex_buy": "uniswap_v2",
"dex_sell": "sushiswap",
"token": "USDC",
"spread_percent": 0.5
}
}
Sandwich
Large swap that can be sandwiched:
{
"type": "sandwich",
"estimated_profit_eth": 0.05,
"confidence": 0.7,
"details": {
"victim_value_eth": 50.0,
"slippage_tolerance": 0.5
}
}
Liquidation
Profitable liquidation opportunity:
{
"type": "liquidation",
"estimated_profit_eth": 0.2,
"confidence": 0.95,
"details": {
"protocol": "aave_v3",
"collateral": "WETH",
"debt": "USDC",
"bonus_percent": 5
}
}
Best Practices
1. Filter Aggressively
Reduce noise by setting appropriate filters:
# Bad - too much data
filter = {}
# Good - focused on opportunities
filter = {
"tx_types": ["swap"],
"min_value_eth": 10.0,
"dex_protocols": ["uniswap_v3"],
"include_mev": True
}
2. Handle Reconnection
WebSocket connections can drop. Implement reconnection logic:
async def resilient_stream():
while True:
try:
async with websockets.connect(uri, extra_headers=headers) as ws:
# ... stream handling
pass
except websockets.ConnectionClosed:
print("Connection closed, reconnecting...")
await asyncio.sleep(1)
except Exception as e:
print(f"Error: {e}")
await asyncio.sleep(5)
3. Process Quickly
Don't block the message handler with slow operations:
# Bad - blocks the stream
async for message in ws:
tx = json.loads(message)
await slow_database_operation(tx) # Blocks!
# Good - queue for async processing
queue = asyncio.Queue()
async for message in ws:
await queue.put(json.loads(message))
# Separate worker processes queue
async def worker():
while True:
tx = await queue.get()
await process_transaction(tx)
Rate Limits
| Tier | WebSocket Connections | REST Requests/min |
|---|---|---|
| Free | 1 | 60 |
| Pro | 5 | 600 |
| Enterprise | 20 | Unlimited |
See Also
- Gas Oracle - Gas prices for transaction timing
- DeFi Liquidations - Liquidation monitoring
- Building a Trading Bot - Complete tutorial