Is the Hyperliquid candles history limit a page cap or retention?
Search for the hyperliquid candles history limit and you find two incompatible answers. One vendor's docs describe candleSnapshot as returning "the 5,000 most recent candles", which reads like retention. Other guides treat 5,000 as a page size and tell you to step startTime backwards to collect more. Only one of these can be right, and it matters: if it is a page cap, a loop gets you a year of 1-minute bars; if it is retention, no loop will ever get you more than a few days.
It is retention. We run a range reader on top of candleSnapshot and watched it fail in exactly the way a retention limit predicts. Our changelog entry for 2026-10-18 records what happened: Hyperliquid keeps only its most recent ~5,000 bars of each interval, and our endpoint kept asking for the older part of a 7-day 1-minute range, retrying each empty reply, making about 15 upstream calls and hitting the 60-second gateway timeout. Stepping startTime back does not return older bars. It returns nothing.
What ~5,000 bars means per interval, as documented on /api/v1/hyperliquid/candles:
| Interval | Bars kept | How far back that reaches |
|---|---|---|
1m | ~5,000 | about 3.5 days |
5m | ~5,000 | about 17 days |
1h | ~5,000 | about 7 months |
The same arithmetic puts 15m at roughly 52 days and 4h at a little over two years, which for Hyperliquid is most of the venue's life. On 1d the cap is not binding at all. So the problem is specifically the intraday intervals that a scalping or execution backtest needs most.
What a range request returns past the cutoff
The failure mode is silent on the native API. Ask for a window that starts before the retained bars and the reply is simply shorter than you asked for, with no error and no marker saying where the data stopped. A backtest that assumes its window is full will quietly run on the last few days.
On /api/v1/hyperliquid/candles the behaviour is now explicit and bounded. With start and end set, the trailing limit is ignored and the window is paginated up to 15,000 bars per call; wider than that is a 400 range_too_large. Since the 2026-10-18 fix, the part of a range older than Hyperliquid keeps is skipped instead of retried, so a 7-day 1-minute request comes back in one upstream call with the ~3.5 days that exist. The response echoes start and end in milliseconds for a range request and null for a trailing pull, so you can compare what you asked for with the first bar you got.
curl "https://cryptodataapi.com/api/v1/hyperliquid/candles?coin=SOL&interval=1m&start=2026-10-17T00:00:00Z&end=2026-10-24T00:00:00Z" \
-H "X-API-Key: cdk_live_your_key"
Each bar carries timestamp (bar open, ms), open, high, low, close and volume. Two details worth knowing before you build on it:
- Range requests bypass the 60-second response cache and spend live Hyperliquid rate-limit weight. Poll them sparingly; a trailing
limitpull is cached. - Coin names resolve case-insensitively against the live universe, and
symbolis an alias forcoin(SOLUSDTis tolerated). A coin Hyperliquid does not list is a400 unknown_coin, and an unrecognised query parameter is a400 unknown_parameter, never a silent default to BTC.
The endpoint is available on every tier, including a free key.
How do I get Hyperliquid 1-minute candles older than 4 days?
From an archive that was sampling the venue before the bars aged out. We store closed 1-minute Hyperliquid bars for the whole perp universe, and GET /api/v1/backtesting/klines?exchange=hyperliquid serves them. Local 1m depth starts 2026-05-09 on both exchanges we archive (Binance spot and Hyperliquid). Nothing about this is a second price source: it is the same venue's own bars, kept past the point where the venue stops serving them.
curl "https://cryptodataapi.com/api/v1/backtesting/klines?symbol=SOL&exchange=hyperliquid&interval=1m&start=2026-06-01&end=2026-06-02&limit=1440" \
-H "X-API-Key: cdk_live_your_key"
An abridged response, with the row shape as served (illustrative values):
{
"symbol": "SOL", "exchange": "hyperliquid", "interval": "1m", "count": 1440,
"klines": [
{ "t": 1780272000000, "o": 142.31, "h": 142.40, "l": 142.18, "c": 142.22, "v": 1860.4, "qv": 264712.9, "n": null },
...
],
"grain": { "kind": "bar", "cadence": "1m", "sum_ok": true, ... },
"coverage": { "local_first": 1778284800000, "local_last": 1792972740000, "archive_hint": null },
"next_cursor": null, "has_more": false
}
Three things the response tells you that the native API cannot:
coverage.local_firstandlocal_lastare the real retention bounds for that symbol. If yourstartis earlier thanlocal_first,coverage.archive_hintnames the archive tier that holds the older bars. An emptydatais never silent.intervalis honoured (1mdefault, or5m,15m,30m,1h,4h,1d), aggregated from the stored 1m bars on the UTC grid. This was a breaking fix on 2026-10-10: before it, the parameter was never read and every call returned 1-minute bars. On aggregated rowsnis the number of 1m bars inside the bar, so a bar with an archive gap, or one still forming, is visible;nisnullon 1m rows.- Paging is keyset. Pass
next_cursorback ascursorwith the samestartandend. One aggregated page scans at most about 278 days of 1m rows, so a long1drequest pages early even whenlimitis not reached.
The endpoint is Pro Plus and served from an isolated container with its own limits: 2 requests per second per key sustained, 10,000 rows per page, and format=csv if you would rather not parse JSON. Send Accept-Encoding: gzip; pages compress about 10x.
Deeper still: monthly klines_deep files back to 2023
Before 2026-05-09 there is no 1-minute Hyperliquid series anywhere, on any source, ours included. What does exist is coarser. The klines_deep archive tier holds one Parquet per symbol per month at 1h, 4h or 1d, and for exchange=hyperliquid it reaches:
1dback to Hyperliquid's 2023 launch4hto about 20241hto about 7 months, which is the native retention, because that is where the files were seeded from
Columns are time, open, high, low, close, volume, quote_volume; on the Hyperliquid files quote_volume is 0. List the files, then fetch pre-signed links:
curl "https://cryptodataapi.com/api/v1/backtesting/archives?data_type=klines_deep&exchange=hyperliquid&symbol=SOL&interval=1d&start=2024-01" \
-H "X-API-Key: cdk_live_your_key"
curl "https://cryptodataapi.com/api/v1/backtesting/archives/download?data_type=klines_deep&exchange=hyperliquid&symbol=SOL&interval=1d&start=2024-01&end=2026-04" \
-H "X-API-Key: cdk_live_your_key"
Between the two sits the daily klines tier: one file per exchange per day of 1-minute bars, back to about 2026-03-30, which predates the local database by five or six weeks. Archive listing and download are Pro Plus. An agent without a subscription can buy a single object over x402: /backtesting/archives/purchase quotes a 402 with the exact price first (a missing file is a 404 before any quote, so you cannot pay for a file that is not there), and klines_deep is priced at $3.00 per object.
The fallback chain: which source for which bars
Put together, the decision is a function of interval and age. This is the table we point agents at:
| You need | Use | Coverage | Tier |
|---|---|---|---|
| Live and recent bars, any interval, within ~5,000 bars | /hyperliquid/candles | Hyperliquid's own retention | Any key |
| 1m to 1d bars older than that, since May 2026 | /backtesting/klines?exchange=hyperliquid | 1m from 2026-05-09, interval aggregates | Pro Plus |
| 1m bars from late March to early May 2026 | archives data_type=klines | daily files to about 2026-03-30 | Pro Plus or x402 |
| Daily or 4h bars for years | archives data_type=klines_deep | 1d to 2023, 4h to ~2024 | Pro Plus or x402 |
| 1m bars before 2026-03-30 | nothing | does not exist on any source | - |
A small Python router that follows it, using the server's own coverage block rather than hard-coded dates:
import httpx, time
API = "https://cryptodataapi.com/api/v1"
H = {"X-API-Key": "cdk_live_your_key", "Accept-Encoding": "gzip"}
def hl_bars(coin, interval, start_ms, end_ms):
# 1. Native retention first: cheap, execution truth, any tier.
r = httpx.get(f"{API}/hyperliquid/candles", headers=H, timeout=60,
params={"coin": coin, "interval": interval, "start": start_ms, "end": end_ms})
live = r.json().get("candles", []) if r.status_code == 200 else []
if live and live[0]["timestamp"] <= start_ms:
return live # the window was inside HL's retention
# 2. Our archive of the same venue's 1m bars, aggregated server-side.
out, cursor = [], None
while True:
p = {"symbol": coin, "exchange": "hyperliquid", "interval": interval,
"start": start_ms, "end": end_ms, "limit": 10000}
if cursor: p["cursor"] = cursor
j = httpx.get(f"{API}/backtesting/klines", headers=H, params=p, timeout=60).json()
out += j["klines"]
if j.get("coverage", {}).get("archive_hint"):
print("older bars:", j["coverage"]["archive_hint"]) # -> klines / klines_deep
if not j.get("has_more"):
return out
cursor = j["next_cursor"]
time.sleep(0.5) # 2 req/s per key on the bulkhead
Note the check on the first live bar: if candles[0].timestamp is later than the start you asked for, the native reply was clipped and the archive has to fill the front of the window.
Execution truth vs archive: which series to trade from
Having two readers for one venue invites a mistake: treating them as two price sources and averaging, or signalling off one and marking off the other. They are the same bars. The rule we document on both endpoints is:
- Signal, size and mark a live Hyperliquid position from
/hyperliquid/candles. Those are the venue's owncandleSnapshotbars, refreshed on the live budget. Useforming_bar_timestampto drop the bar that has not closed yet, andatr=14if you want a Wilder ATR on every bar without computing it yourself. - Backtest and warm indicators from
/backtesting/klines. It is an archive of the same 1m bars for depth, withntelling you when an aggregated bar is incomplete. - Join on the open time.
timestampon the live series andton the archive are both the bar open in milliseconds on the same UTC grid, so a strategy can be developed on one and run on the other with no re-alignment.
If you need funding or open interest on that same bar grid, /backtesting/hl-funding-bars serves one row per closed bar whose time equals the candle's timestamp. That lets a funding condition be tested against the exact 4h bar a price signal fired on, which is the whole reason to keep the clocks aligned.
When to use this (and when not to)
Use the native endpoint when your lookback fits inside ~5,000 bars. For a 1h strategy that is seven months, which covers most live indicator warm-ups, and it costs nothing beyond a free key.
Use the archive when you are backtesting intraday behaviour across more than a few days: slippage models on 1m bars, session effects, anything that needs May 2026 onwards at minute resolution. Expect to page, expect the bulkhead's 2 requests per second, and read coverage rather than assuming your window is full.
Do not expect 1-minute Hyperliquid bars from before 2026-03-30 from anyone. The venue never retained them and we were not sampling yet. If a provider claims multi-year 1m Hyperliquid history, ask where it was captured, because the native API cannot be the answer.
Do not loop startTime backwards on candleSnapshot hoping for more. Each call past the cutoff is an empty reply that spends rate-limit weight and, before our 2026-10-18 fix, was enough to time out a gateway. Step the interval up instead: the same 7 days that are out of reach on 1m are well inside retention on 5m.
The full endpoint reference is at /docs, and the deep archive tiers are described under the backtesting section there. If you are reading this from an agent, the MCP connect line is claude mcp add --transport http cryptodataapi https://cryptodataapi.com/mcp.
Frequently asked questions
Is Hyperliquid's 5,000-candle limit a page size or retention?
Retention. Hyperliquid keeps only its most recent ~5,000 bars of each interval, about 3.5 days of 1m, 17 days of 5m and 7 months of 1h. Stepping startTime backwards returns nothing older.
How do I get Hyperliquid 1-minute candles older than a few days?
From an archive. GET /api/v1/backtesting/klines?exchange=hyperliquid serves closed 1-minute Hyperliquid bars from 2026-05-09, with interval aggregation to 5m through 1d, keyset paging and a coverage block that says where local retention starts.
How far back does Hyperliquid OHLCV history go?
Daily bars reach Hyperliquid's 2023 launch and 4h bars about 2024 via the klines_deep archive tier. 1-minute bars exist from about 2026-03-30 in the daily klines files and from 2026-05-09 in the queryable archive. No 1m history exists before that on any source.
Which series should a Hyperliquid bot trade from?
The live /api/v1/hyperliquid/candles series, which is Hyperliquid's own candleSnapshot output. /backtesting/klines is an archive of the same venue's bars for depth, not a second price source; both key bars by open time on the same UTC grid.



