Hyperliquid liquidations: every liquidation, and where the next ones sit
Every Hyperliquid liquidation, live and in history; a liquidation heatmap of where each coin's open positions would be liquidated; the share of open interest close to liquidation; and an alert when a liquidation hits or a position nears its liquidation price.
“What were the biggest Hyperliquid liquidations in the last 24 hours?”
hl_liquidations“At what BTC prices would the most Hyperliquid positions get liquidated?”
hl_liquidationsExact since 2026-08-03, estimated before
Where every row comes from, and how far to trust it.
Since 2026-08-03, a liquidation is exact: it is the liquidated account's own fill, read from the node. A fill that closes a position by liquidation carries a liquidation object; the row is the fill whose wallet is that object's liquidatedUser, at the fill's millisecond (liq_ts), with the size it closed and the mark price the venue liquidated at (mark_price, from markPx). The counterparty's fill carries the same object and is not a liquidation. A row lands seconds after the fill.
Rows before 2026-08-03 are estimated (inferred): a position worth over $100 whose mark was within 5% of its liquidation price in one snapshot (about every 5 minutes) and that was gone from the next. Their liq_ts is that snapshot's time and their size and mark the last seen; a hand close that near liquidation counts, a partial liquidation is missed. On the hl.liquidations channel every event says inferred: false or inferred: true.
Hyperliquid liquidations, live and in history
Across the whole market, by coin, wallet, side and time, newest first.
Liquidations
Liquidation events, and each coin's open interest sitting close to liquidation.
- Route
/v1/hyperliquid/liquidations- Cadence
- Seconds after the liquidation fill; inferred between snapshots before 2026-08-03
- Coverage
- Liquidation events are exact, from the node's fills since 2026-08-03: the liquidated wallet's own fill, at its millisecond, with the venue's mark price. Older rows are inferred from position snapshots: a position that vanished between two snapshots while its last mark was within 5% of its liquidation price. Newest first (keyset-paged, limit up to 5,000; filter by symbol, wallet, direction, start, end), each with its point-in-time pnl cohort where the hourly label table covers that hour (pnl_cohort_basis says which). /liquidations/risk ranks coins by the share of notional within half its liquidation buffer;
/symbols/{symbol}/liquidation-heatmapbins where open positions would liquidate. - Rows
- MCP
hl_liquidations- Stream
hl.liquidations
Fields
| Field | Type | Description |
|---|---|---|
liq_ts | string | Liquidation time, ISO-8601 UTC |
wallet | string | Liquidated account |
symbol | string | Symbol; HIP-3 DEX symbols carry their DEX prefix, spot pairs are HL's @index |
side | string | long | short — the side that was closed |
size_token | number | Size liquidated, coin units |
size_usd | number | Notional liquidated, USD |
mark_price | number | Mark price at liquidation |
size_cohort | string | Account-value rung |
pnl_cohort | string | Realized-PnL rung at the liquidation's hour, or unknown |
pnl_cohort_basis | string | point_in_time | current — which label the row carries |
Live: the newest liquidations
Recent liquidations · /liquidations
/v1/hyperliquid/liquidations?limit=20Build a request
/v1/hyperliquid/liquidations?symbol={symbol}&direction={direction}&limit={limit}GET /v1/hyperliquid/liquidations · Every liquidation, newest first
- CLI
vike-data hl liquidations- MCP
hl_liquidations· 1 credit- Cost
- 1 request of the hourly limit
Liquidation events, newest first: exact, from the node's fills since 2026-08-03; older rows inferred from position snapshots.
Since 2026-08-03 a row is the liquidated account's own fill, as the venue marked it: liq_ts is the fill's millisecond time, size_token and size_usd the size it closed (fills of one liquidation in the same millisecond summed) and mark_price the mark price the venue liquidated at. An older row is a position worth over $100 whose mark was within 5% of its liquidation price in one snapshot (taken about every 5 minutes) and that is gone from the next: liq_ts is the time of that snapshot, size and mark are the last values seen, a position closed by hand that close to its liquidation price is counted and a partial liquidation is not.
Each row's pnl_cohort is point-in-time — the label as it stood at the liquidation's own hour — where the hourly label table covers it, and the query-time dictionary label where it cannot; pnl_cohort_basis says which per row, and the envelope's label_computed declares the provenance and the two windows with no point-in-time label (rows before 2026-04-07, and the newest hours the label job has not yet published).
Parameters
| Parameter | In | Description |
|---|---|---|
symbol | query | HL ticker |
wallet | query | One wallet |
start | query | ISO-8601 UTC bounds |
end | query | ISO-8601 UTC bounds |
direction | query | long | short |
limit | query | Default 100, max 5000 |
cursor | query | Keyset cursor |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/liquidations?symbol=BTC&direction=long&limit=50"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/liquidations",
params={"symbol": "BTC", "direction": "long", "limit": 50}, # longs liquidated: price fell
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
timeout=30,
)
r.raise_for_status()
for liq in r.json()["liquidations"]:
print(liq["liq_ts"], liq["symbol"], liq["side"], round(liq["size_usd"]), liq["mark_price"], liq["wallet"])
# older rows: send r.json()["nextCursor"] back as cursor=… until it is null
vike-data hl liquidations --symbol BTC --direction long --limit 50
# any MCP client; or from the terminal:
vike-data call hl_liquidations --args '{"view": "fills", "symbol": "BTC", "direction": "long", "limit": 50}'
How much open interest sits close to liquidation
Per coin, the share of open notional already most of the way to its liquidation price.
OI near liquidation · /liquidations/risk
/v1/hyperliquid/liquidations/riskOpen interest close to liquidation, per coin
- Route
GET /v1/hyperliquid/liquidations/risk- CLI
vike-data hl liquidations- MCP
hl_liquidations· 1 credit- Cost
- 1 request of the hourly limit
Share of each coin's open interest sitting close to liquidation.
Parameters
| Parameter | In | Description |
|---|---|---|
axis | query | size | pnl | pnl_abs. Default size |
cohort | query | One label on that axis |
limit | query | Default 100, max 500 |
min_value_usd | query | Smallest total open notional (USD) a coin needs to be ranked. Default 0 (no floor): the ranking is by percent_risk, so small markets with a few thousand dollars of interest lead it; raise this to keep only markets big enough for a cascade to matter. |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/liquidations/risk?limit=20&min_value_usd=1000000"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/liquidations/risk?limit=20&min_value_usd=1000000",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl liquidations --view risk --min-value-usd 1000000 --limit 20
# any MCP client; or from the terminal:
vike-data call hl_liquidations --args '{"view": "risk", "min_value_usd": 1000000, "limit": 20}'
Liquidation map: where a coin's positions would be liquidated
Open positions' own liquidation prices within ±50% of the mark, binned and weighted by notional: the price levels where size would be force-closed.
Liquidation heatmap: where one coin's positions would be liquidated
- Route
GET /v1/hyperliquid/symbols/{symbol}/liquidation-heatmap- CLI
vike-data hl liquidations- MCP
hl_liquidations· 1 credit- Cost
- 1 request of the hourly limit
Where liquidations would cluster if price moved — every open position's own liquidation price, binned and weighted by notional.
Parameters
| Parameter | In | Description |
|---|---|---|
symbolrequired | path | HL ticker |
bins | query | Number of price bins. Default 50, min 5, max 500 |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/symbols/BTC/liquidation-heatmap?bins=50"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/symbols/BTC/liquidation-heatmap?bins=50",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl liquidations --view heatmap --symbol BTC --bins 50
# any MCP client; or from the terminal:
vike-data call hl_liquidations --args '{"view": "heatmap", "symbol": "BTC", "bins": 50}'
Where stops and take-profits wait
The standing orders around the price, bucketed: a stop cluster is where a move can feed on itself.
Stop and take-profit clusters around the price
- Route
GET /v1/hyperliquid/symbols/{symbol}/order-clusters- CLI
vike-data hl orders- MCP
hl_orders· 1 credit- Cost
- 1 request of the hourly limit
One symbol's standing orders within range_pct of the mid of the best resting bid and ask, bucketed by price: bid / ask by limit price, tp / sl by trigger price.
Trailing stops are not bucketed. For an at with no complete 5-minute snapshot at that instant (before 2026-10-23 21:45 UTC, or inside an outage) the book is rebuilt from the sightings on both sides of it: short-lived orders can be missing and reference_price then reflects the long-lived orders only. A call without at is never rebuilt: it is the newest snapshot, or the newest checkpoint while the 5-minute feed is stalled. For a past at, sizes can be later, smaller remaining sizes.
Parameters
| Parameter | In | Description |
|---|---|---|
symbolrequired | path | HL perp ticker |
at | query | ISO-8601 UTC, floored to 5 minutes. Default: the newest snapshot |
step_bps | query | Bucket width in basis points of the reference price. Default 10 |
range_pct | query | Half-width of the price range, percent. Default 10 |
cohort_axis | query | size | pnl | pnl_abs. Default size |
cohort | query | One label on cohort_axis, by CURRENT labels: refused with at |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/symbols/BTC/order-clusters"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/symbols/BTC/order-clusters",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl orders --view clusters --symbol BTC
# any MCP client; or from the terminal:
vike-data call hl_orders --args '{"view": "clusters", "symbol": "BTC"}'
Stop clusters against book depth, live →
The standing stops and take-profits of a coin beside its order book, on vike.io: no key, no code.
Every resting order at an instant, and a wallet's order history: Order book →
Who just raised their leverage
Leverage is what moves a liquidation price: every position whose leverage or margin mode changed.
Leverage raised, cut or switched between cross and isolated
- Route
GET /v1/hyperliquid/leverage-changes- CLI
vike-data hl leverage-changes- MCP
hl_leverage_changes· 1 credit- Cost
- 1 request of the hourly limit
Positions whose leverage or margin mode differs between two consecutive complete position snapshots, newest first.
One row per wallet and symbol, with the previous and the new value of leverage, margin mode, side, size and entry price. ts is when the later snapshot was written, not when the venue changed the setting. Snapshots are stamped every 5 minutes, but the positions behind them are captured about every 12 minutes, so changes arrive in batches.
Parameters
| Parameter | In | Description |
|---|---|---|
wallet | query | One wallet, 0x plus 40 hex, any case |
symbol | query | HL ticker, e.g. BTC or xyz:TSLA |
change | query | up (leverage rose) | down (leverage fell) | mode (only the margin mode, cross or isolated, changed). Validated against this fixed set |
min_leverage | query | Minimum new leverage, 0 or more. Default 0: no floor |
start | query | ISO-8601 UTC. Default: the 24 hours before end (before now when end is empty), unless wallet is given. Resuming an order=asc cursor starts from the cursor instead; a desc cursor keeps the 24-hour floor |
end | query | ISO-8601 UTC. Default: now. A window wider than 31 days is a 400 unless wallet is given |
order | query | asc | desc. Default desc, newest first. order=asc returns the oldest events first and is the mode for following a feed: pass each nextCursor back verbatim. It orders by key, so a row the writer inserts late with an older key is not seen by a poller already past it: re-read a small overlap. An asc page with rows always carries a cursor; an empty one returns the cursor you sent, or on a first call with no start or wallet, a cursor at the lower bound of the default window (null when one of them already pins the place). So stop on an empty page, not on a null cursor. A desc page that comes back short carries no cursor. Anything else is a 400 |
limit | query | Default 100, max 5000 |
cursor | query | nextCursor from the previous page, verbatim. It pins the call that returned it: the feed, order, every filter and the start and end you sent. Changing or dropping any of them, start included, is a 400. Without wallet, an asc cursor more than 31 days before end (before now when end is empty) is a 400 too: restart with start |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/leverage-changes?change=up&min_leverage=20"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/leverage-changes?change=up&min_leverage=20",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl leverage-changes --change up --min-leverage 20
# any MCP client; or from the terminal:
vike-data call hl_leverage_changes --args '{"change": "up", "min_leverage": 20}'
Liquidations on a WebSocket
Three channels: liquidations as they happen, positions entering the liquidation zone, leverage changes.
- One URL,
wss://stream.vike.io/v1/stream/hl: send your key in theX-API-KEYheader, then one subscribe frame per channel. - The server pings every 15 s: answer with pong. 1 connection per key on this path, 100 subscriptions on one connection.
- Delivery is at least once: dedupe on event.event_id. Dropped? Subscribe again with your last
cursor: you get what you missed, up to 3 days back; without a socket,/v1/hyperliquid/stream-eventsreads the same events. - A channel runs while someone subscribes to it; on a quiet channel the first events come with the next pass.
hl.liquidations
Every liquidation, seconds after the liquidated account's fill: the rows of /liquidations, pushed.
- Path
- wss://stream.vike.io/v1/stream/hl
- Filters
- coin, direction, min_usd, pnl_cohort, size_cohort, wallet
Filters
| Field | Type | Description |
|---|---|---|
coin | list ≤ 200 | The symbol, e.g. BTC or xyz:TSLA; on hl.candles a spot token or its @index too. |
direction | one value | The side of the position: long or short. One of: long, short. |
min_usd | number | The event's dollar size is at least this. |
pnl_cohort | list ≤ 50 | The wallet's realized-PnL cohort; unknown also matches a wallet with no label. One of: 2x loser, 2x rekt, 2x smart, 2x winner, 3x loser, 3x rekt, 3x smart, 3x winner, loser, rekt, smart, unknown, winner. |
size_cohort | list ≤ 50 | The wallet's account-size cohort; unknown also matches a wallet with no label. One of: 2x dolphin, 2x fish, 2x shark, 2x shrimp, 2x whale, 3x whale, 4x whale, dolphin, fish, shark, shrimp, unknown, whale. |
wallet | list ≤ 1,000 | The event's wallet. |
Subscribe
import json, os
from websockets.sync.client import connect # websockets >= 14
with connect("wss://stream.vike.io/v1/stream/hl",
additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
ws.send(json.dumps({"action": "subscribe", "id": "liqs", "channel": "hl.liquidations",
"filter": {"coin": ["BTC", "ETH"], "min_usd": 100000}}))
for message in ws:
frame = json.loads(message)
if frame["type"] == "ping":
ws.send(json.dumps({"action": "pong"}))
elif frame["type"] == "event":
e = frame["event"]
print(json.dumps(e)) # keep frame["cursor"] to resume after a drop
vike-data stream hl --channel hl.liquidations --filter coin=BTC,ETH --filter min_usd=100000 # prints NDJSON, reconnects by itself
{
"action": "subscribe",
"id": "liqs",
"channel": "hl.liquidations",
"filter": {
"coin": [
"BTC",
"ETH"
],
"min_usd": 100000
}
}
hl.liq_risk
A position of $100,000 or more that has gone 80% of the way from entry to its liquidation price is announced once; it can be announced again after it falls back below 70% or closes.
- Path
- wss://stream.vike.io/v1/stream/hl
- Filters
- coin, direction, min_usd, pnl_cohort, size_cohort, wallet
Filters
| Field | Type | Description |
|---|---|---|
coin | list ≤ 200 | The symbol, e.g. BTC or xyz:TSLA; on hl.candles a spot token or its @index too. |
direction | one value | The side of the position: long or short. One of: long, short. |
min_usd | number | The event's dollar size is at least this. |
pnl_cohort | list ≤ 50 | The wallet's realized-PnL cohort; unknown also matches a wallet with no label. One of: 2x loser, 2x rekt, 2x smart, 2x winner, 3x loser, 3x rekt, 3x smart, 3x winner, loser, rekt, smart, unknown, winner. |
size_cohort | list ≤ 50 | The wallet's account-size cohort; unknown also matches a wallet with no label. One of: 2x dolphin, 2x fish, 2x shark, 2x shrimp, 2x whale, 3x whale, 4x whale, dolphin, fish, shark, shrimp, unknown, whale. |
wallet | list ≤ 1,000 | The event's wallet. |
Subscribe
import json, os
from websockets.sync.client import connect # websockets >= 14
with connect("wss://stream.vike.io/v1/stream/hl",
additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
ws.send(json.dumps({"action": "subscribe", "id": "near-liq", "channel": "hl.liq_risk",
"filter": {"coin": ["BTC"]}}))
for message in ws:
frame = json.loads(message)
if frame["type"] == "ping":
ws.send(json.dumps({"action": "pong"}))
elif frame["type"] == "event":
e = frame["event"]
print(json.dumps(e)) # keep frame["cursor"] to resume after a drop
vike-data stream hl --channel hl.liq_risk --filter coin=BTC # prints NDJSON, reconnects by itself
{
"action": "subscribe",
"id": "near-liq",
"channel": "hl.liq_risk",
"filter": {
"coin": [
"BTC"
]
}
}
hl.leverage
A wallet's leverage or margin mode changed between two position captures (about every 12 minutes, so changes come in batches): the rows of /leverage-changes, pushed.
- Path
- wss://stream.vike.io/v1/stream/hl
- Filters
- coin, direction, min_usd, pnl_cohort, size_cohort, wallet
Filters
| Field | Type | Description |
|---|---|---|
coin | list ≤ 200 | The symbol, e.g. BTC or xyz:TSLA; on hl.candles a spot token or its @index too. |
direction | one value | The side of the position: long or short. One of: long, short. |
min_usd | number | The event's dollar size is at least this. |
pnl_cohort | list ≤ 50 | The wallet's realized-PnL cohort; unknown also matches a wallet with no label. One of: 2x loser, 2x rekt, 2x smart, 2x winner, 3x loser, 3x rekt, 3x smart, 3x winner, loser, rekt, smart, unknown, winner. |
size_cohort | list ≤ 50 | The wallet's account-size cohort; unknown also matches a wallet with no label. One of: 2x dolphin, 2x fish, 2x shark, 2x shrimp, 2x whale, 3x whale, 4x whale, dolphin, fish, shark, shrimp, unknown, whale. |
wallet | list ≤ 1,000 | The event's wallet. |
Subscribe
import json, os
from websockets.sync.client import connect # websockets >= 14
with connect("wss://stream.vike.io/v1/stream/hl",
additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
ws.send(json.dumps({"action": "subscribe", "id": "leverage", "channel": "hl.leverage",
"filter": {"min_usd": 1000000}}))
for message in ws:
frame = json.loads(message)
if frame["type"] == "ping":
ws.send(json.dumps({"action": "pong"}))
elif frame["type"] == "event":
e = frame["event"]
print(json.dumps(e)) # keep frame["cursor"] to resume after a drop
vike-data stream hl --channel hl.leverage --filter min_usd=1000000 # prints NDJSON, reconnects by itself
{
"action": "subscribe",
"id": "leverage",
"channel": "hl.leverage",
"filter": {
"min_usd": 1000000
}
}
Liquidation alerts, no code
By e-mail or webhook. Sign in, and the form opens filled in.
Get an e-mail when a liquidation hits
Every liquidation, or only those of one wallet, coin or cohort, from a dollar size up. By e-mail or webhook, one message per event.
Get an e-mail before a position is liquidated
When a wallet's position has gone 80% of the way from entry to its liquidation price; it fires again only after it falls back by 10%. Pick the share on the form.
The same with code, or from your AI:
# hl_liquidation
vike-data alerts create --type hl_liquidation --label 'BTC liquidations over $100k' --token BTC --min-usd 100000 --channel email
# hl_liq_proximity
vike-data alerts create --type hl_liq_proximity --label 'Near liquidation' --wallet 0xfc667adba8d4837586078f4fdcdc29804337ca06 --threshold 0.8 --channel email
# any MCP client; or from the terminal:
vike-data call alerts_create --args '{"label": "BTC liquidations over $100k", "alert_type": "hl_liquidation", "token_symbol": "BTC", "min_value_usd": 100000, "channels": ["email"]}'
vike-data call alerts_create --args '{"label": "Near liquidation", "alert_type": "hl_liq_proximity", "wallet": "0xfc667adba8d4837586078f4fdcdc29804337ca06", "threshold": 0.8, "channels": ["email"]}'
The liquidation routes
Each one is a card above; every parameter of every route is also in the API reference.
| Route | What it answers | Reference |
|---|---|---|
GET /v1/hyperliquid/liquidations | Liquidation events, exact from the node's fills since 2026-08-03, older rows inferred from position snapshots; filter by symbol, wallet, direction and time, newest first, up to 5,000 a page. | API reference → |
GET /v1/hyperliquid/liquidations/risk | Open interest close to liquidation, per coin | API reference → |
GET /v1/hyperliquid/symbols/{symbol}/liquidation-heatmap | Liquidation heatmap: where one coin's positions would be liquidated | API reference → |
GET /v1/hyperliquid/symbols/{symbol}/order-clusters | Stop and take-profit clusters around the price | API reference → |
GET /v1/hyperliquid/leverage-changes | Leverage raised, cut or switched between cross and isolated | API reference → |
Liquidation questions, answered with code
Each with the sentence to ask your AI instead. Every block was run against the live API on 2026-11-03.
Was this wallet liquidated? Hyperliquid liquidation history by wallet
Pass the address to /liquidations as wallet and you get every liquidation recorded for it, newest first; an empty list means none was recorded.
- Uses
/liquidations,/positions- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# every liquidation recorded for one wallet, newest first
r = requests.get(
"https://data.vike.io/v1/hyperliquid/liquidations?wallet=0xbf342cf5d1e4a4bb91b171c15e3cdbe82da3fcff&limit=5",
headers={"X-API-Key": API_KEY},
)
print(len(r.json()["liquidations"]), "liquidations")
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# this wallet's BTC liquidations in September 2026
r = requests.get(
"https://data.vike.io/v1/hyperliquid/liquidations?wallet=0xbf342cf5d1e4a4bb91b171c15e3cdbe82da3fcff&symbol=BTC&start=2026-09-01T00:00:00Z&end=2026-10-01T00:00:00Z&limit=100",
headers={"X-API-Key": API_KEY},
)
print(len(r.json()["liquidations"]), "BTC liquidations in September")
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# only the long positions this wallet lost to liquidation
r = requests.get(
"https://data.vike.io/v1/hyperliquid/liquidations?wallet=0xbf342cf5d1e4a4bb91b171c15e3cdbe82da3fcff&direction=long&limit=100",
headers={"X-API-Key": API_KEY},
)
print(len(r.json()["liquidations"]), "long liquidations")
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the wallet's open positions with liquidation price and liq_progress
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?wallet=0xbf342cf5d1e4a4bb91b171c15e3cdbe82da3fcff&limit=200",
headers={"X-API-Key": API_KEY},
)
print(len(r.json()["positions"]), "open positions")
Live Hyperliquid liquidation feed with a rolling 1-hour total
Poll /liquidations with start set to one hour ago, follow nextCursor to the end, and sum size_usd by side; to have each one pushed instead, subscribe to the hl.liquidations channel or create an hl_liquidation alert.
- Uses
/liquidations- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
from datetime import datetime, timedelta, timezone
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
START = (datetime.now(timezone.utc) - timedelta(hours=1)).strftime("%Y-%m-%dT%H:%M:%SZ") # one hour ago
# every liquidation of the last hour, newest first
r = requests.get(
f"https://data.vike.io/v1/hyperliquid/liquidations?start={START}&limit=5",
headers={"X-API-Key": API_KEY},
)
import os
from datetime import datetime, timedelta, timezone
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
START = (datetime.now(timezone.utc) - timedelta(hours=1)).strftime("%Y-%m-%dT%H:%M:%SZ") # one hour ago
# long and short liquidation notional of the last hour, from one 5000-row page
r = requests.get(
f"https://data.vike.io/v1/hyperliquid/liquidations?start={START}&limit=5000",
headers={"X-API-Key": API_KEY},
)
# then: jq '{more: (.nextCursor != null), by_side: (.liquidations | group_by(.side) | map({side: .[0].side, n: length, usd: (map(.size_usd) | add)}))}'
import os
from datetime import datetime, timedelta, timezone
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
START = (datetime.now(timezone.utc) - timedelta(hours=1)).strftime("%Y-%m-%dT%H:%M:%SZ") # one hour ago
# every row of the hour: follow nextCursor until it is null
rows, cursor = [], ""
while True:
page = requests.get(
f"https://data.vike.io/v1/hyperliquid/liquidations?start={START}&limit=5000&cursor={cursor}",
headers={"X-API-Key": API_KEY},
).json()
rows += page["liquidations"]
cursor = page["nextCursor"]
if not cursor:
break
print(len(rows), "liquidations in the last hour")
import os
from datetime import datetime, timedelta, timezone
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
START = (datetime.now(timezone.utc) - timedelta(hours=24)).strftime("%Y-%m-%dT%H:%M:%SZ") # 24 hours ago
# BTC liquidations of the last 24 hours (a quiet hour can have none on one coin)
r = requests.get(
f"https://data.vike.io/v1/hyperliquid/liquidations?symbol=BTC&start={START}&limit=5000",
headers={"X-API-Key": API_KEY},
)
Hyperliquid liquidation history in Python (all wallets, per coin, any date range)
Find the biggest BTC hourly move of one day, then total the long and short Hyperliquid liquidations inside that hour.
- Uses
/liquidations,/ohlcv- Verified
- live API, 2026-11-03: 2 calls, all 200
The code
"""Find the biggest BTC hourly move of one day, then total the liquidations that landed in that hour.
Run: VIKE_API_KEY=... python hl-liquidations-around-move.py (--dry-run lists the requests and makes none)
"""
import os
import sys
from datetime import datetime, timezone
from urllib.parse import urlencode
NAME = "hl-liquidations-around-move"
BASE = "https://data.vike.io"
DRY = "--dry-run" in sys.argv
def fail(why):
sys.exit(f"{NAME}: {why}")
def call(path, method="GET", **params):
url = BASE + path + ("?" + urlencode(params) if params else "")
if DRY:
print(method, url)
return None
key = os.environ.get("VIKE_API_KEY") or fail("set VIKE_API_KEY")
import requests
r = requests.request(method, url, headers={"X-API-Key": key}, timeout=60)
if r.status_code != 200:
fail(f"{method} {path} answered HTTP {r.status_code}: {r.text[:200]}")
return r.json()
def iso(ms):
return datetime.fromtimestamp(ms / 1000, timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
def main():
# end is exclusive on /ohlcv: this is the 24 hourly bars of 2026-08-17.
day = call("/v1/hyperliquid/ohlcv", symbol="BTC", interval="1h", limit=24,
start="2026-08-17T00:00:00Z", end="2026-08-18T00:00:00Z")
move_ts = 1786924800000 # --dry-run has no response to read
if not DRY:
if not day["candles"]:
fail("no BTC candles for the day")
biggest = max(day["candles"], key=lambda c: abs(c["close"] / c["open"] - 1))
move_ts = biggest["ts"]
print(f"biggest hour: {iso(move_ts)} {biggest['close'] / biggest['open'] - 1:+.2%} ({biggest['open']:g} -> {biggest['close']:g})")
# /liquidations is newest-first, its bounds are whole seconds and its end is inclusive; 5000 is the most
# one page holds. The hour's own end is passed, and a fill stamped exactly on it is dropped below.
hour_end = move_ts + 3_600_000
liqs = call("/v1/hyperliquid/liquidations", symbol="BTC", limit=5000, start=iso(move_ts), end=iso(hour_end))
if DRY:
return
rows = [r for r in liqs["liquidations"] if datetime.fromisoformat(r["liq_ts"]).timestamp() * 1000 < hour_end]
if not rows:
fail("no BTC liquidations in the move's hour")
if liqs["nextCursor"]:
print(" (a full page: the totals below cover the newest 5000 rows of the hour only)")
# `side` is the side of the position that was closed: "long" means longs were liquidated.
for side in ("long", "short"):
hit = [r for r in rows if r["side"] == side]
print(f" {side:5} liquidated: {len(hit):5} fills ${sum(r['size_usd'] for r in hit):,.0f}")
if __name__ == "__main__":
try:
main()
except Exception as e: # a shape the example does not expect fails by name, not by traceback
fail(f"{type(e).__name__}: {e}")
Hyperliquid liquidation heatmap: where are BTC liquidation clusters?
Bin open BTC positions by liquidation price within ±50% of the mark, weighted by notional, to see where size would be force-closed.
- Uses
/liquidations,/symbols/{…}/liquidation-heatmap- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# where open BTC positions would be liquidated, in ten price bins around the mark
r = requests.get(
"https://data.vike.io/v1/hyperliquid/symbols/BTC/liquidation-heatmap?bins=10",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the five price bins with the most BTC notional to liquidate
r = requests.get(
"https://data.vike.io/v1/hyperliquid/symbols/BTC/liquidation-heatmap?bins=100",
headers={"X-API-Key": API_KEY},
)
# then: jq '.bins | sort_by(-.liquidation_value_usd) | .[:5] | map({price_bin_start, price_bin_end, liquidation_value_usd, long_value_usd, short_value_usd})'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the ETH heatmap at the default 50 bins
r = requests.get(
"https://data.vike.io/v1/hyperliquid/symbols/ETH/liquidation-heatmap",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the newest realized BTC liquidations
r = requests.get(
"https://data.vike.io/v1/hyperliquid/liquidations?symbol=BTC&limit=100",
headers={"X-API-Key": API_KEY},
)
Which Hyperliquid positions are closest to liquidation right now?
Rank positions by how much of their liquidation buffer is used up: /positions gives each position's liq_progress, and /liquidations/risk ranks markets by the share of open notional past half of its buffer.
- Uses
/liquidations/risk,/positions- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# markets ranked by the share of open notional close to liquidation
r = requests.get(
"https://data.vike.io/v1/hyperliquid/liquidations/risk?limit=5",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the same ranking restricted to markets with at least $50M open
r = requests.get(
"https://data.vike.io/v1/hyperliquid/liquidations/risk?limit=500",
headers={"X-API-Key": API_KEY},
)
# then: jq '[.[] | select(.total_value_usd >= 50000000)] | .[:10]'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the 500 biggest BTC positions, re-sorted by how much of the liquidation buffer is used up
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&sort=size&limit=500",
headers={"X-API-Key": API_KEY},
)
# then: jq '.positions | sort_by(-.liq_progress) | .[:10] | map({wallet, direction, size_usd, entry_price, mark_price, liquidation_price, liq_progress, leverage})'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the risk ranking for the largest accounts only
r = requests.get(
"https://data.vike.io/v1/hyperliquid/liquidations/risk?axis=size&cohort=4x_whale&limit=20",
headers={"X-API-Key": API_KEY},
)
Am I about to be liquidated? Hyperliquid wallet risk report
How far each of a wallet's open positions is from liquidation: /positions?wallet= returns each with its liquidation price, mark price and liq_progress, and /wallets/{address} adds account value and exposure.
- Uses
/positions,/wallets/{…}- Verified
- live API, 2026-11-03: 3 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# every open position of the wallet with its liquidation price
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?wallet=0xfc667adba8d4837586078f4fdcdc29804337ca06&limit=5",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# account value, unrealized PnL and exposure against equity
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xfc667adba8d4837586078f4fdcdc29804337ca06",
headers={"X-API-Key": API_KEY},
)
# then: jq '{equity, open_positions}'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# positions ranked by buffer used, with the distance to the liquidation price
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?wallet=0xfc667adba8d4837586078f4fdcdc29804337ca06&limit=200",
headers={"X-API-Key": API_KEY},
)
# then: jq '[.positions[] | select(.liquidation_price > 0) | {symbol, direction, size_usd, mark_price, liquidation_price, liq_progress, distance_pct: ((.mark_price - .liquidation_price) / .mark_price * 100 | fabs)}] | sort_by(-.liq_progress) | .[:10]'
Which Hyperliquid whales are over-leveraged against their own account value?
Divide each big position's size_usd by its wallet's account_value for the exposure and read liq_progress for how close it is to liquidation; /v1/hyperliquid/positions?symbol=BTC&sort=size returns the biggest open positions of a coin with both.
- Uses
/positions,/wallets/{…}- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the 100 biggest BTC positions, ranked by position size over account value
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&sort=size&limit=100",
headers={"X-API-Key": API_KEY},
)
# then: jq '[.positions[] | select(.account_value != null and .account_value > 0) | {wallet, direction, size_usd, account_value, exposure: (.size_usd / .account_value), leverage, liq_progress}] | sort_by(-.exposure)'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the most exposed wallet of the ranking: equity, open positions and exposure
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x60468ba27448f88b19f52ed02f1a8c52f7a0b21d",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the 500 biggest BTC positions, those nearest liquidation first
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&sort=size&limit=500",
headers={"X-API-Key": API_KEY},
)
# then: jq '[.positions[] | {wallet, direction, size_usd, account_value, liq_progress, liquidation_price, mark_price}] | sort_by(-.liq_progress) | .[:10]'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the 100 biggest ETH positions with account values
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=ETH&sort=size&limit=100",
headers={"X-API-Key": API_KEY},
)
Where was BTC open interest sitting an hour before a liquidation cascade?
Read the BTC positions of the hour before the move from /positions with start, end and resolution=1h, page through all of them, then group them by side and by liquidation price yourself.
- Uses
/liquidations,/positions- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# open BTC positions in the hour before the 2026-10-22 01:00 UTC move
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&start=2026-10-22T00:00:00Z&end=2026-10-22T00:59:59Z&resolution=1h&limit=5",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# long and short BTC notional in the hour before the move, one page
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&start=2026-10-22T00:00:00Z&end=2026-10-22T00:59:59Z&resolution=1h&limit=5000",
headers={"X-API-Key": API_KEY},
)
# then: jq '{more: (.nextCursor != null), by_side: (.positions | group_by(.direction) | map({direction: .[0].direction, positions: length, usd: (map(.size_usd) | add)}))}'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# BTC notional by $1,000 liquidation-price bin, the hour before the move
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&start=2026-10-22T00:00:00Z&end=2026-10-22T00:59:59Z&resolution=1h&limit=5000",
headers={"X-API-Key": API_KEY},
)
# then: jq '[.positions[] | select(.liquidation_price > 0)] | group_by((.liquidation_price / 1000 | floor)) | map({bin: (.[0].liquidation_price / 1000 | floor * 1000), usd: (map(.size_usd) | add)}) | sort_by(-.usd) | .[:10]'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# BTC liquidations between 01:00 and 02:00 UTC
r = requests.get(
"https://data.vike.io/v1/hyperliquid/liquidations?symbol=BTC&start=2026-10-22T01:00:00Z&end=2026-10-22T02:00:00Z&limit=5000",
headers={"X-API-Key": API_KEY},
)
Hyperliquid liquidations FAQ
Is there a free Hyperliquid liquidations API?
GET /v1/hyperliquid/liquidations returns liquidation events across the whole market, by coin, wallet, direction and time, with one free key; the same data is the hl_liquidations MCP tool, the vike-data hl liquidations command and the hl.liquidations WebSocket channel.How are liquidations detected?
liquidation object; the row is the fill whose wallet is that object's liquidatedUser, at the fill's millisecond (liq_ts), with the size it closed and the mark price the venue liquidated at (mark_price, from markPx). The counterparty's fill carries the same object and is not a liquidation. A row lands seconds after the fill. Rows before 2026-08-03 are estimated (inferred): a position worth over $100 whose mark was within 5% of its liquidation price in one snapshot (about every 5 minutes) and that was gone from the next. Their liq_ts is that snapshot's time and their size and mark the last seen; a hand close that near liquidation counts, a partial liquidation is missed. On the hl.liquidations channel every event says inferred: false or inferred: true.Is there a Hyperliquid liquidation heatmap or liquidation map?
/v1/hyperliquid/symbols/{symbol}/liquidation-heatmap bins one coin's open positions by their own liquidation price within ±50% of the mark, weighted by notional, so you see the price levels where size would be force-closed. /v1/hyperliquid/liquidations/risk ranks coins by the share of open interest already close to liquidation.How do I find a position's liquidation price?
/v1/hyperliquid/positions returns every open position with its liquidation_price, mark_price and liq_progress: how far the mark has moved from entry toward liquidation, 0 to 1. Give it a wallet for one account, or a symbol with sort=size for a coin's largest positions.Can I get an alert when a liquidation happens?
hl_liquidation alert for every liquidation (of one wallet, coin or cohort, above a dollar floor if you like), and an hl_liq_proximity alert when one wallet's position nears its liquidation price.