Skip to main content

Download Hyperliquid OHLCV Candles: Full History to CSV and Parquet

Hyperliquid's API keeps 5,000 candles per interval. Download every one-minute candle since March 2025 to CSV and Parquet, check gaps, and know where they differ.

9 min read
Explore with your agent

Key findings

  1. Step 1: download the full history to CSV864,356One-minute BTC candles since March 2025, in 87 requests and 36 seconds.
  2. Side by side: Hyperliquid's API and 0xArchive3.5 daysHow far back Hyperliquid's own one-minute candles reach.
  3. Step 4: compare with Hyperliquid's own candles100%Minutes where volume and trade count match Hyperliquid's own candles.
  4. Step 3: check for gaps0.042%Minutes with no candle, mostly minutes with no trades.

Candles, also called OHLCV bars, summarize trading in fixed intervals: the open, high, low and close price, plus volume. They are the input to most backtests and charts. Hyperliquid, an onchain crypto exchange, serves candles through its API, but only the most recent 5,000 per interval, so one-minute bars reach back about three and a half days. This guide downloads every one-minute BTC candle since March 2025 to CSV and Parquet in 87 requests, checks it for gaps, and shows where 0xArchive candles differ from Hyperliquid's own. All code ran on 13 November 2026.

Short answer

  • Hyperliquid's API keeps 5,000 candles per interval. One-minute candles went back to 10 November, hourly to 19 April. Older one-minute bars are not available from Hyperliquid at all, including its S3 archive, which carries no candles.
  • 0xArchive serves every interval from 22 March 2025. 864,356 one-minute BTC candles took 87 requests and 36 seconds, 81 MB as CSV and 24 MB as Parquet.
  • Our highs and lows include liquidation fills. Hyperliquid's own candles leave them out of the price range while still counting them in volume. Volume and trade counts matched on 100% of the minutes we compared.
  • For daily BTC bars before March 2025, use Hyperliquid's API. Its daily candles start on 26 February 2023.

What you need

  • Python 3 with requests, and pyarrow for the Parquet step. The snippets are short prototypes without retry logic.
  • A 0xArchive API key in OXARCHIVE_API_KEY. The Free plan includes candles with a rolling 30 days of history. Full history from March 2025 needs a paid plan; see pricing.

Step 1: download the full history to CSV

The candle route returns up to 10,000 candles per request and a cursor for the next page. Eight intervals are served: 1m, 5m, 15m, 30m, 1h, 4h, 1d and 1w. This pulls every one-minute BTC candle and writes a CSV:

import os, time, requests
from datetime import datetime, timezone
import csv
H = {"X-API-Key": os.environ["OXARCHIVE_API_KEY"]}
B = "https://api.0xarchive.io/v1"

def candles(path, symbol, interval, start, end):
    """Every candle from start to end, 10,000 per request, following the cursor."""
    rows, cursor, calls = [], None, 0
    while True:
        p = {"interval": interval, "start": start, "end": end, "limit": 10000}
        if cursor:
            p["cursor"] = cursor
        j = requests.get(f"{B}{path}/candles/{symbol}", headers=H, params=p, timeout=120).json()
        rows += j["data"]
        calls += 1
        cursor = j["meta"].get("next_cursor")
        if not j["meta"].get("has_more"):
            return rows, calls

t0 = time.time()
rows, calls = candles("/hyperliquid", "BTC", "1m", "2025-03-22T00:00:00Z", "2026-11-13T00:00:00Z")
FIELDS = ["timestamp", "open", "high", "low", "close", "volume", "quote_volume", "trade_count"]
with open("btc_1m.csv", "w", newline="") as fh:
    w = csv.DictWriter(fh, fieldnames=FIELDS, extrasaction="ignore")
    w.writeheader()
    w.writerows(rows)
print(len(rows), "candles in", calls, "requests, %.1f s" % (time.time() - t0),
      "| first", rows[0]["timestamp"], "| last", rows[-1]["timestamp"],
      "| %.1f MB" % (os.path.getsize("btc_1m.csv") / 1e6))
864356 candles in 87 requests, 36.1 s | first 2025-03-22T12:00:00Z | last 2026-11-13T00:00:00Z | 81.1 MB

The first candle is 22 March 2025 at 12:00 UTC, the start of the served history. Each row has open, high, low, close, volume in coins, quote_volume in dollars, and trade_count.

Step 2: write Parquet

Parquet stores the same table in columns, compressed, with types. It is what pandas, Polars, DuckDB and most backtesting stacks read fastest:

import pyarrow as pa, pyarrow.parquet as pq
table = pa.table({
    "timestamp": pa.array([r["timestamp"] for r in rows]).cast(pa.timestamp("ms", tz="UTC")),
    **{k: pa.array([float(r[k]) for r in rows]) for k in FIELDS[1:7]},
    "trade_count": pa.array([int(r["trade_count"]) for r in rows]),
})
pq.write_table(table, "btc_1m.parquet", compression="zstd")
print("parquet %.1f MB" % (os.path.getsize("btc_1m.parquet") / 1e6), "| rows", table.num_rows)
parquet 24.4 MB | rows 864356

The same 864,356 rows took 24.4 MB with ZSTD compression, against 81.1 MB as CSV. Timestamps are stored as UTC times rather than text, so a reader does not have to parse them.

Step 3: check for gaps

A minute with no trades has no candle. Before you backtest, count what is missing and look at the longest gaps:

ts = [datetime.fromisoformat(r["timestamp"].replace("Z", "+00:00")) for r in rows]
gaps = [(a, int((b - a).total_seconds() // 60) - 1) for a, b in zip(ts, ts[1:]) if (b - a).total_seconds() > 60]
expected = int((ts[-1] - ts[0]).total_seconds() // 60) + 1
print("missing minutes", expected - len(rows), "in", len(gaps), "gaps | longest",
      max(gaps, key=lambda g: g[1])[1], "min from", max(gaps, key=lambda g: g[1])[0].isoformat())
missing minutes 365 in 113 gaps | longest 42 min from 2025-06-08T09:44:00+00:00

365 of about 864,700 minutes are absent, 0.042%, in 113 gaps. The longest is 42 minutes on 8 June 2025. We checked the two longest gaps against Hyperliquid's own 4-hour candles for the same periods: the trade counts matched exactly, so those minutes had no trades on Hyperliquid either. Decide before you backtest whether to forward-fill empty minutes or leave them out, because the choice changes indicators such as moving averages and volatility.

Step 4: compare with Hyperliquid's own candles

Hyperliquid's candleSnapshot call is free and needs no key. Ask it for everything since 1970 and see where it stops:

N = "https://api.hyperliquid.xyz/info"
for iv in ("1m", "1h", "1d"):
    snap = requests.post(N, json={"type": "candleSnapshot", "req": {
        "coin": "BTC", "interval": iv, "startTime": 0, "endTime": int(time.time() * 1000)}}, timeout=60).json()
    first = next(c for c in snap if int(c["n"]) > 0)
    print("native", iv, len(snap), "candles, earliest with trades",
          datetime.fromtimestamp(first["t"] / 1000, timezone.utc).strftime("%Y-%m-%d %H:%M"))
native 1m 5024 candles, earliest with trades 2026-11-10 08:14
native 1h 5000 candles, earliest with trades 2026-04-19 12:00
native 1d 2278 candles, earliest with trades 2023-02-26 00:00

One-minute candles reached back to the morning of 10 November and hourly candles to 19 April. The documentation says "Only the most recent 5000 candles are available". We got 5,024 one-minute candles and 5,000 hourly ones. The limit is on how far back you can go, not on one response: a one-hour window ending four days ago returned nothing.

Daily candles are the exception. Hyperliquid's daily candles with trades went back to 26 February 2023, before the 0xArchive candle history starts. The earlier rows it returned had no trades. If you need daily or 4-hour BTC bars from 2023 or 2024, take them from Hyperliquid. For anything shorter than a day older than a few weeks, Hyperliquid has nothing to give.

Why some highs and lows differ

We compared the 5,035 one-minute BTC candles both sources had. Volume and trade count matched on all 5,035. Open, high, low and close matched on 4,998, and 37 differed. Here is one of them, rebuilt from the trades:

m = "2026-11-10T13:30:00Z"
ours = requests.get(f"{B}/hyperliquid/candles/BTC", headers=H, timeout=60, params={
    "interval": "1m", "start": m, "end": "2026-11-10T13:31:00Z"}).json()["data"][0]
trades = requests.get(f"{B}/hyperliquid/trades/BTC", headers=H, timeout=120, params={
    "start": m, "end": "2026-11-10T13:31:00Z", "limit": 50000}).json()["data"]
uniq = {t["trade_id"]: t for t in trades}.values()      # each trade appears once per side
liq = [t for t in uniq if t.get("is_liquidation")]
rest = [float(t["price"]) for t in uniq if not t.get("is_liquidation")]
print("candle low", ours["low"], "| trades", len(uniq), "| liquidation fills", len(liq),
      "| low without liquidations", min(rest))
candle low 73292.0 | trades 11421 | liquidation fills 1951 | low without liquidations 73444.0

At 13:30 UTC on 10 November, 1,951 of the minute's 11,421 trades were liquidations. Our candle's low, 73,292, came from a liquidation fill. Hyperliquid's candle showed a low of 73,444, which is the lowest price of the trades that were not liquidations. In 29 of the 37 differing minutes, the same rule explained both candles exactly. Hyperliquid's documentation does not describe this; we measured it.

The effect grows with the interval, because one liquidation wick is enough to change a bar. Hourly bars over 30 days matched on 94.6%, daily bars since March 2025 on 72.2%. If your strategy uses stops or liquidation levels, the wick is a price that traded. If you want candles that match Hyperliquid's chart, rebuild them from trades without the is_liquidation fills.

Step 5: other markets

The same route shape serves HIP-3 markets such as stock perps, spot pairs, HIP-4 outcome markets and Lighter, another onchain crypto exchange. Each has its own start:

for path, sym in [("/hyperliquid/hip3", "xyz:NVDA"), ("/hyperliquid/spot", "HYPE-USDC"),
                  ("/lighter", "BTC"), ("/hyperliquid/hip4", "0")]:
    r = requests.get(f"{B}{path}/candles/{sym}", headers=H, timeout=60, params={
        "interval": "1d", "start": "2025-01-01T00:00:00Z", "end": "2026-11-13T00:00:00Z", "limit": 1}).json()
    print(path, sym, "first daily candle", r["data"][0]["timestamp"] if r["data"] else None)
/hyperliquid/hip3 xyz:NVDA first daily candle 2025-12-22T00:00:00Z
/hyperliquid/spot HYPE-USDC first daily candle 2025-03-23T00:00:00Z
/lighter BTC first daily candle 2025-08-01T00:00:00Z
/hyperliquid/hip4 0 first daily candle 2026-05-03T00:00:00Z
Market familyRouteFirst candle
Hyperliquid perps/v1/hyperliquid/candles/{symbol}22 March 2025
Hyperliquid spot/v1/hyperliquid/spot/candles/{pair}22 March 2025
HIP-3, such as xyz:NVDA/v1/hyperliquid/hip3/candles/{symbol}22 December 2025
HIP-4 outcome markets/v1/hyperliquid/hip4/candles/{id}3 May 2026
Lighter/v1/lighter/candles/{symbol}1 August 2025

HIP-4 candle prices are probabilities between 0 and 1. For anything older than these dates, or for a candle rule of your own, build bars from the trades dataset.

Side by side: Hyperliquid's API and 0xArchive

We ran the same jobs against each source on 13 November 2026.

JobHyperliquid candleSnapshot0xArchive
One-minute BTC historyLatest 5,024 candles, 3.5 days864,356 candles from 22 March 2025, 87 requests, 36 s
Hourly BTC historyFrom 19 April 2026From 22 March 2025
Daily BTC historyFrom 26 February 2023From 22 March 2025
Liquidation fills in high and lowLeft outIncluded
Weekly bars startThursdaySunday 00:00 UTC
Key neededNoYes

Hyperliquid's API is enough for a live chart, a bot that only looks at the last few days, or daily bars back to 2023. For intraday history, a backtest longer than a few days, or HIP-3 and Lighter markets in the same shape, use the full archive. See Hyperliquid's native API vs 0xArchive for every dataset.

What to know before you build

  • Weekly bars do not line up. Ours start Sunday 00:00 UTC. Hyperliquid's start Thursday.
  • A window entirely before the start fails. On Hyperliquid perps it returns HTTP 400 with the start date. On other families it returns no rows and a coverage_from field. A window that crosses the start is served from the start.
  • Volume is per side, once. volume counts each trade once, in coins. Do not add maker and taker volume from the trades route and expect it to match.
  • Hyperliquid's own daily candle can disagree with itself. On 20 April 2025 its daily BTC candle counted 91,765 trades while its six 4-hour candles added up to 126,393.
  • Close prices can differ by a tick. In 8 of the 37 differing minutes the close was a few dollars apart, likely from the order of trades inside the same millisecond.

FAQ

How do I download Hyperliquid historical candles?

Page the 0xArchive candle route from 22 March 2025, 10,000 candles per request, as in Step 1. Hyperliquid's own API only keeps the latest 5,000 candles per interval.

How far back does Hyperliquid's candleSnapshot go?

5,000 candles per interval: about 3.5 days of one-minute bars, 208 days of hourly bars, and daily bars back to February 2023.

Can I get Hyperliquid OHLCV as Parquet?

Yes. Write the downloaded candles with pyarrow as in Step 2. Full BTC one-minute history is about 24 MB with ZSTD compression.

Why does my candle high not match the Hyperliquid chart?

Hyperliquid's candles leave liquidation fills out of the high and low. 0xArchive candles include them, because they traded.

Do you have Lighter candles?

Yes, from 1 August 2025, on /v1/lighter/candles/{symbol} with the same intervals and fields.

Next steps