Browse our curated market data catalog across exchanges and asset types, and the raw trades, quotes and derivatives data behind it.
Preview data — no subscription. Try it free withDEMO-KEYRaw L2 order books aren't offered yet. Ask us.
A fixed slice of every dataset is free to download: the shared key DEMO-KEY over cURL, --preview in the CLI or preview=True in Python. Pick one for a command you can paste and run. A subscription unlocks full history and every exchange, symbol, interval and parameter; extended trials are available on request.
The 2025-06 file of each venue's BTC perpetual, for every dataset the venue serves.
| Dataset | Binanceperpetual-BTC-USDT:USDT | OKXperpetual-BTC-USDT:USDT | Hyperliquidperpetual-BTC-USDC:USDC |
|---|---|---|---|
| trades | |||
| quotes | |||
| mark_price | |||
| index_price | |||
| funding_rate | |||
| open_interest |
Every metric, over one slice: binance-futures · perpetual-BTC-USDT:USDT · 5m · exchange timestamps · 2025-05-01 → 2025-05-31
Trades
Derivatives
Market Data
L1 (Top of Book)
L2 (Order Book)
trades · binance-futures · perpetual-BTC-USDT:USDT · 2025-06
Open dataset# Install the Aperiodic CLI into ~/.local/bin
mkdir -p "$HOME/.local/bin"
curl -fsSL https://raw.githubusercontent.com/aperiodic-io/cli/main/install.sh | INSTALL_DIR="$HOME/.local/bin" bash
export PATH="$HOME/.local/bin:$PATH"
# Download the 2025-06 trades file into ./raw — no API key needed
aperiodic raw trades --preview \
--exchange binance-futures \
--symbol perpetual-BTC-USDT:USDT \
--output-dir ./raw && echo "Saved to $PWD/raw"The venue’s mark price, one row each time it changes.
/api/v1/data/raw/mark_price
exchange_timestamptimestampWhen the venue says the event happened (UTC, µs). Exact, except modelled on Hyperliquid, whose feed carries no exchange time: there the file has an exchange_timestamp_kind column ("modelled") right after it.local_timestamptimestampWhen the event reached the capture machine (UTC, µs). Measured by our capture, or modelled as exchange_timestamp plus a latency drawn from our measured distribution; see local_timestamp_kind.local_timestamp_kindstring"measured" or "modelled". Don't use modelled rows for latency research.mark_pricefloat64Mark priceLive coverage is unavailable right now; every symbol's coverage is at /api/v1/metadata/raw.
One file per calendar month before 2026-08-01, one per day from then on, in the aperiodic-raw-derivatives bucket. Example key:
v1/mark_price/exchange=binance-futures/symbol=perpetual-BTC-USDT:USDT/year=2025/month=06/data.parquet
The shared DEMO-KEY gets the 2025-06 file of each venue's BTC perpetual. No account needed.
# Install the Aperiodic CLI into ~/.local/bin
mkdir -p "$HOME/.local/bin"
curl -fsSL https://raw.githubusercontent.com/aperiodic-io/cli/main/install.sh | INSTALL_DIR="$HOME/.local/bin" bash
export PATH="$HOME/.local/bin:$PATH"
# Download the 2025-06 mark_price file into ./raw — no API key needed
aperiodic raw mark_price --preview \
--exchange binance-futures \
--symbol perpetual-BTC-USDT:USDT \
--output-dir ./raw && echo "Saved to $PWD/raw"pip install "aperiodic[polars]"from datetime import date
import aperiodic as ap
# Into one DataFrame (monthly files are trimmed to your range)
df = ap.get_raw(api_key="YOUR_KEY", dataset="mark_price",
exchange="binance-futures", symbol="perpetual-BTC-USDT:USDT",
start_date=date(2025, 6, 1), end_date=date(2025, 6, 30))
print(df.head())
# Or stream the files to disk, skipping ones you already have
ap.download_raw(api_key="YOUR_KEY", dataset="mark_price",
exchange="binance-futures", symbol="perpetual-BTC-USDT:USDT",
start_date=date(2025, 1, 1), end_date=date(2025, 12, 31),
output_dir="raw")Read the folder back one dataset at a time, with a glob:
# DuckDB, from the folder that holds ./raw
duckdb -c "SELECT * FROM read_parquet('raw/mark_price/**/data.parquet')
WHERE exchange_timestamp >= '2025-06-01' LIMIT 10"from datetime import datetime, timezone
import polars as pl
df = (
pl.scan_parquet("raw/mark_price/**/data.parquet")
.filter(pl.col("exchange_timestamp") >= datetime(2025, 6, 1, tzinfo=timezone.utc))
.collect()
)
print(df.head())exchange_timestamp is the venue's own time. local_timestamp is measured on days we captured ourselves and modelled from our measured latency before that; local_timestamp_kind says which. Don't use modelled days for latency research.exchange_timestamp is modelled; those files say so in an exchange_timestamp_kind column.The venue’s mark price, one row each time it changes.
/api/v1/data/raw/mark_price
exchange_timestamptimestampWhen the venue says the event happened (UTC, µs). Exact, except modelled on Hyperliquid, whose feed carries no exchange time: there the file has an exchange_timestamp_kind column ("modelled") right after it.local_timestamptimestampWhen the event reached the capture machine (UTC, µs). Measured by our capture, or modelled as exchange_timestamp plus a latency drawn from our measured distribution; see local_timestamp_kind.local_timestamp_kindstring"measured" or "modelled". Don't use modelled rows for latency research.mark_pricefloat64Mark price| Venue | Symbols | From |
|---|---|---|
| Binance | 984 | Mar 2020 |
| OKX | 700 | Oct 2019 |
| Hyperliquid | 529 | Mar 2025 |
One file per calendar month before 2026-08-01, one per day from then on, in the aperiodic-raw-derivatives bucket. Example key:
v1/mark_price/exchange=binance-futures/symbol=perpetual-BTC-USDT:USDT/year=2025/month=06/data.parquet
The shared DEMO-KEY gets the 2025-06 file of each venue's BTC perpetual. No account needed.
# Install the Aperiodic CLI into ~/.local/bin
mkdir -p "$HOME/.local/bin"
curl -fsSL https://raw.githubusercontent.com/aperiodic-io/cli/main/install.sh | INSTALL_DIR="$HOME/.local/bin" bash
export PATH="$HOME/.local/bin:$PATH"
# Download the 2025-06 mark_price file into ./raw — no API key needed
aperiodic raw mark_price --preview \
--exchange binance-futures \
--symbol perpetual-BTC-USDT:USDT \
--output-dir ./raw && echo "Saved to $PWD/raw"pip install "aperiodic[polars]"from datetime import date
import aperiodic as ap
# Into one DataFrame (monthly files are trimmed to your range)
df = ap.get_raw(api_key="YOUR_KEY", dataset="mark_price",
exchange="binance-futures", symbol="perpetual-BTC-USDT:USDT",
start_date=date(2025, 6, 1), end_date=date(2025, 6, 30))
print(df.head())
# Or stream the files to disk, skipping ones you already have
ap.download_raw(api_key="YOUR_KEY", dataset="mark_price",
exchange="binance-futures", symbol="perpetual-BTC-USDT:USDT",
start_date=date(2025, 1, 1), end_date=date(2025, 12, 31),
output_dir="raw")Read the folder back one dataset at a time, with a glob:
# DuckDB, from the folder that holds ./raw
duckdb -c "SELECT * FROM read_parquet('raw/mark_price/**/data.parquet')
WHERE exchange_timestamp >= '2025-06-01' LIMIT 10"from datetime import datetime, timezone
import polars as pl
df = (
pl.scan_parquet("raw/mark_price/**/data.parquet")
.filter(pl.col("exchange_timestamp") >= datetime(2025, 6, 1, tzinfo=timezone.utc))
.collect()
)
print(df.head())exchange_timestamp is the venue's own time. local_timestamp is measured on days we captured ourselves and modelled from our measured latency before that; local_timestamp_kind says which. Don't use modelled days for latency research.exchange_timestamp is modelled; those files say so in an exchange_timestamp_kind column.