Skip to main content

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

EthereumGnosisOptimismArbitrum

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

FieldTypeDescription
tx_typesstring[]Filter by transaction type
min_value_ethfloatMinimum transaction value in ETH
min_gas_price_gweifloatMinimum gas price
max_gas_price_gweifloatMaximum gas price
dex_protocolsstring[]Filter by DEX (uniswap_v2, uniswap_v3, sushiswap)
addressesstring[]Filter by from/to addresses
include_mevbooleanOnly include txs with MEV opportunities

Transaction Types

TypeDescription
swapDEX swap transactions
liquidationLending protocol liquidations
transferToken transfers
flashloanFlash loan operations
bridgeCross-chain bridge transactions
nftNFT trades and mints
contract_deployContract deployments
otherUnclassified

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 return
  • tx_type (string): Filter by type
  • min_value_eth (float): Minimum value
  • min_gas_price_gwei (float): Minimum gas price
  • mev_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 swaps
  • min_value_eth (float): Minimum value
  • dex (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

TierWebSocket ConnectionsREST Requests/min
Free160
Pro5600
Enterprise20Unlimited

See Also