Guides
Export Hyperliquid OHLCV Candles to CSV cover

Export Hyperliquid OHLCV Candles to CSV

Generate CSV files for a chosen Hyperliquid market and candle interval by iterating Dwellir's OHLCV endpoint.

LanguagePython
FormatCSV
ProtocolREST

If you want a flat file of Hyperliquid candles for backtesting, charting, or ad hoc analysis, the simplest approach is to iterate Dwellir's OHLCV REST endpoint and write each returned candle to CSV.

This guide shows how to export sparse 1s, 1m, or 5m candles for a single market into a .csv file.

Copy-Paste Prompt for Your Coding Tool

Paste this into Claude Code, Codex, Cursor, Windsurf, or another coding agent:

Text
Build me a small script that exports Hyperliquid OHLCV candles from Dwellir into a CSV file.

Requirements:
- First check whether the `dwellir` CLI is installed.
- If it is not installed, recommend installing it with one of these options:
  - `brew tap dwellir-public/homebrew-tap && brew install dwellir`
  - `curl -fsSL https://raw.githubusercontent.com/dwellir-public/cli/main/scripts/install.sh | sh`
- After installation, ask me to authenticate it by running `dwellir auth login`.
- Check authentication with `dwellir auth status`.
- Get an enabled API key with `dwellir keys list --toon`. If there are multiple good candidates, ask me which key to use.
- Use the Dwellir Hyperliquid OHLCV REST endpoint.
- Export one market and one interval at a time.
- Treat the data as sparse: if a bucket returns 404, skip it rather than fabricating a candle.
- The OHLCV archive starts at `2025-07-27T08:00:00Z`.
- Iterate bucket-open timestamps between a start and end time.
- Support `1s`, `1m`, and `5m`.
- Write a CSV with columns: market, interval, bucket_start, open, high, low, close, volume, trades_count, vwap.
- Show me how to run the script for BTC 1m candles over a chosen date range.

What This Guide Builds

By the end of this guide you will have:

  • a Python script that fetches candles from Dwellir's Hyperliquid OHLCV REST API
  • a clean .csv file for one market and one candle interval
  • a repeatable export workflow that respects sparse candles and bucket-open timestamps

Before You Start

  • Install Python 3.10+.
  • Install the required package:
Bash
pip install requests
  • Make sure you have a Dwellir API key. The easiest agent-friendly workflow is:
Bash
dwellir auth login
dwellir keys list --toon

If you do not have the CLI yet:

Bash
brew tap dwellir-public/homebrew-tap
brew install dwellir

How the Export Works

The OHLCV REST API returns exactly one candle per request:

Text
GET https://api-hyperliquid-ohlcv.n.dwellir.com/YOUR_API_KEY/v1/candles

You identify the candle with three parameters:

  • market, for example BTC
  • interval, one of 1s, 1m, 5m
  • time, the bucket-open timestamp for the exact candle you want

To export a range, you iterate the bucket-open timestamps you care about and request each one separately.

Because the candles are sparse:

  • a 404 means there were no trades in that bucket
  • you should skip that bucket instead of inventing a flat candle

Python Export Script

Save this as export_ohlcv_csv.py:

Python
import csv
import sys
from datetime import datetime, timedelta, timezone

import requests


STEP_BY_INTERVAL = {
    "1s": timedelta(seconds=1),
    "1m": timedelta(minutes=1),
    "5m": timedelta(minutes=5),
}


def parse_utc(value: str) -> datetime:
    return datetime.fromisoformat(value.replace("Z", "+00:00")).astimezone(timezone.utc)


def format_utc(value: datetime) -> str:
    return value.astimezone(timezone.utc).isoformat().replace("+00:00", "Z")


def iter_bucket_starts(start: datetime, end: datetime, step: timedelta):
    current = start
    while current <= end:
        yield current
        current += step


def fetch_candle(api_key: str, market: str, interval: str, bucket_start: datetime):
    response = requests.get(
        f"https://api-hyperliquid-ohlcv.n.dwellir.com/{api_key}/v1/candles",
        params={
            "market": market,
            "interval": interval,
            "time": format_utc(bucket_start),
        },
        timeout=30,
    )

    if response.status_code == 404:
        return None

    response.raise_for_status()
    return response.json()


def export_csv(api_key: str, market: str, interval: str, start: str, end: str, output_path: str):
    if interval not in STEP_BY_INTERVAL:
        raise ValueError(f"unsupported interval: {interval}")

    start_dt = parse_utc(start)
    end_dt = parse_utc(end)
    step = STEP_BY_INTERVAL[interval]

    with open(output_path, "w", newline="") as handle:
        writer = csv.DictWriter(
            handle,
            fieldnames=[
                "market",
                "interval",
                "bucket_start",
                "open",
                "high",
                "low",
                "close",
                "volume",
                "trades_count",
                "vwap",
            ],
        )
        writer.writeheader()

        for bucket_start in iter_bucket_starts(start_dt, end_dt, step):
            candle = fetch_candle(api_key, market, interval, bucket_start)
            if candle is None:
                continue
            writer.writerow(candle)


if __name__ == "__main__":
    if len(sys.argv) != 7:
        raise SystemExit(
            "usage: python export_ohlcv_csv.py <API_KEY> <MARKET> <INTERVAL> <START> <END> <OUT_CSV>"
        )

    _, api_key, market, interval, start, end, output_path = sys.argv
    export_csv(api_key, market, interval, start, end, output_path)

Run It

Example: export BTC 1m candles for one day:

Bash
python export_ohlcv_csv.py \
  YOUR_API_KEY \
  BTC \
  1m \
  2026-03-30T00:00:00Z \
  2026-03-30T23:59:00Z \
  btc-1m-2026-03-30.csv

Example: export ETH 5m candles for a week:

Bash
python export_ohlcv_csv.py \
  YOUR_API_KEY \
  ETH \
  5m \
  2026-03-01T00:00:00Z \
  2026-03-07T23:55:00Z \
  eth-5m-2026-03-01-to-2026-03-07.csv

Notes on Historical Coverage

  • The intended historical floor is 2025-07-27T08:00:00Z.
  • Use bucket-open timestamps that match the interval:
    • 1s on exact seconds
    • 1m on exact minutes
    • 5m on 00, 05, 10, and so on

When to Use CSV

CSV is a good fit when you want:

  • quick inspection in spreadsheets
  • simple ingest into pandas, DuckDB, or SQLite
  • plain-text exports for sharing and debugging

If you want a columnar analytics format instead, use the companion guide: