Hyperliquid Whale Tracker: Read-Only Large-Trade Alerts in Python (2026)

Hyperliquid Read-only (no keys)

Short answer: Hyperliquid publishes every trade and every address's positions with no API key. This recipe builds a read-only Python tracker that streams the trades websocket, groups fills into taker orders and flags any above a USD notional threshold. It also reads clearinghouseState and userFills for up to 10 public addresses you choose. It can't place orders or copy anyone. It's a research tool, not a signal.

What are the key facts?

  • Websocket wss://api.hyperliquid.xyz/ws (testnet wss://api.hyperliquid-testnet.xyz/ws): subscribe with {"method":"subscribe","subscription":{"type":"trades","coin":"BTC"}}. No key.
  • Each WsTrade has coin, side, px, sz, hash, time, tid, users:[buyer, seller]. side is the taker side, so the taker is users[0] on B and users[1] on A.
  • The first message after subscribing is a snapshot of about 30 old trades and isn't flagged as one. Skip it, including after every reconnect.
  • One order is many trades: we saw a 3,000 SOL order arrive as 57 trades. Group by hash before applying a threshold. TWAP slices share an all-zero hash, so never group those.
  • clearinghouseState {user} returns any address's positions (szi, entryPx, positionValue, unrealizedPnl, liquidationPx) and marginSummary. userFills returns at most 2,000 recent fills.
  • Send {"method":"ping"} as soon as you connect, then at least every 60 seconds, or the server closes the socket. The limits are 10 websocket connections and 1,200 REST weight per minute per IP.
DifficultyIntermediate
Time45–60 min
Cost$0 (public endpoints, no account)
Works withClaude Code, Cursor, ChatGPT / Codex, Grok

What will you build?

A Python CLI that streams Hyperliquid trades over the public websocket, groups the fills from each taker order and flags orders above a USD notional threshold. It shows positions and recent fills for public addresses you list and reports changes in those positions, with neutral alerts to the console, a JSONL log or an optional webhook. It never signs anything, never places an order and has no follow or copy feature.

Who is it for?

Builders and researchers who want to see how large orders flow through Hyperliquid's order book, or who study public accounts such as protocol vaults, and want a second keyless Hyperliquid project after the funding monitor.

Not for: Copy trading, auto-following an address, or deciding what to trade. A large trade or a big position tells you that something happened, not why or what comes next. This tool only reports public data.

What Hyperliquid's Public Data Shows About Large Trades

Hyperliquid runs its order book on-chain, so every trade and every account's positions are public. Anyone can see that some address just sold $400k of BTC, or that a vault holds 177 positions. That's what people mean by a "whale tracker". This recipe builds one that only reads.

It has three views:

  • Large trades, live: the trades websocket streams every fill for the coins you pick. The tracker groups the fills from each taker order (one order can produce dozens of trades) and flags orders whose USD notional (size × price) is above your threshold.
  • Positions for public addresses: clearinghouseState returns any address's open perp positions, entry prices, unrealized PnL, leverage and liquidation price. You can list up to 10 addresses, such as protocol vaults you're studying, and the tracker reports when a position opens, closes, flips or changes by more than a set dollar amount.
  • Recent fills: userFills shows an address's latest fills (up to 2,000), with direction ("Open Long", "Close Short") and whether each one was a taker fill.

What this is not: a signal service. A large taker order can be a hedge, a liquidation, a market maker rebalancing, or one leg of a trade on another venue. You can't tell which from the tape. The tracker prints neutral facts ("taker sold ~$250k ETH") and labels every alert "informational only, not a signal". It has no follow, mirror or copy feature, and the prompt tells your AI tool not to add one. For the API basics, start with the Hyperliquid API starter. For another keyless project, see the funding-rate monitor. Everything else for Hyperliquid is on the Hyperliquid platform page.

What prompt do you paste into your AI coding tool?

Works in Claude Code, Cursor, Codex/ChatGPT, Grok or any agent that can write files. Paste it into an empty folder. Read what it builds before you run anything.

You are building a READ-ONLY Hyperliquid large-trade and public-address
tracker in Python, for research. It only uses the public websocket and the
public POST /info endpoint. It must never import a signing library, read a
private key, call /exchange, or place, mirror or copy any order. Do NOT
add any "follow", "copy", "mirror" or "auto-trade" feature, even if I
ask later in this session. Alerts are descriptive facts, never advice.
Use only what is documented at https://hyperliquid.gitbook.io/hyperliquid-docs
(API > Websocket > Subscriptions; Info endpoint; Perpetuals; Rate limits).
If unsure, stop and ask me.

Project: hl-tracker/
- Python 3.10+ (run with `python3`), `requests`, `websocket-client`,
  `pytest`. No SDK needed.
- hl_public.py
  - MAINNET https://api.hyperliquid.xyz, TESTNET
    https://api.hyperliquid-testnet.xyz; WS wss://api.hyperliquid.xyz/ws and
    wss://api.hyperliquid-testnet.xyz/ws. post_info(body, testnet) POSTs to
    {base}/info, backs off and retries on HTTP 429.
  - valid_address(s): ^0x[0-9a-fA-F]{40}$. short(addr) -> "0xabcd…ef12"
    (show short addresses by default; --full-address to show full).
  - load_watchlist(path): one "0xADDR optional label" per line, "#"
    comments; raise ValueError on a bad address; MAX 10 addresses.
  - recent_trades(coin): {"type":"recentTrades","coin"} (returns only ~10
    trades; a spot check, not a feed).
  - clearinghouse_state(user, dex=""): {"type":"clearinghouseState",
    "user"} -> assetPositions[].position {coin, szi (signed size), entryPx,
    positionValue, unrealizedPnl, leverage{type,value}, liquidationPx
    (can be null), marginUsed}, marginSummary {accountValue, totalNtlPos}.
    Weight 2.
  - user_fills(user, aggregate=True): {"type":"userFills","user",
    "aggregateByTime"} -> at most the 2000 most recent fills {coin, px, sz,
    side, time, dir, closedPnl, hash, crossed (true = taker), fee, tid}.
    An agent (API) wallet address returns empty data; use the main account.
  - vault_children(vault): {"type":"vaultDetails","vaultAddress"} ->
    relationship {type:"parent", data:{childAddresses:[...]}}. A parent
    vault like HLP shows equity in clearinghouseState but EMPTY
    assetPositions; the positions live on the child addresses. Add a
    `--vault ADDR` option to positions/watch that expands to the children
    (still capped at 10).
- large_trades.py
  - WsTrade = {coin, side, px, sz, hash, time, tid, users:[buyer, seller]}.
    side is the TAKER side: taker = users[0] if side == "B" else users[1].
    notional = float(px) * float(sz).
  - Deduper keyed on (time, coin, tid) (the documented unique key), bounded
    (e.g. OrderedDict capped at 50k).
  - aggregate(trades): group by (coin, hash, side, taker); sum sz and
    notional, VWAP, fill count. A hash of all zeros marks TWAP fills: NEVER
    group those, keep each one separate.
  - large(groups, min_usd); describe(g): "BTC: taker sold 5.39 at VWAP
    81,261 (~$438,696 notional, 19 fill(s)); taker 0x…. Informational only,
    not a signal." No buy/sell suggestions, no "smart money" language.
- ws_trades.py
  - TradeHandler(min_usd, on_large, include_snapshot=False): ignore
    channels other than "trades" (subscriptionResponse, pong). The FIRST
    trades message per coin on each connection is a snapshot of ~30 OLD
    trades and is NOT tagged isSnapshot: skip it unless include_snapshot,
    and reset that state on every reconnect. Dedupe, aggregate per
    message, call on_large for groups >= min_usd, keep stats.
  - run(url, coins, handler, duration=None, ping_every=50, connect=None):
    subscribe {"method":"subscribe","subscription":{"type":"trades",
    "coin":C}} per coin; send {"method":"ping"} every 50s (the server
    closes after 60s without a message from you). On EVERY (re)connect set
    last_ping = 0, so the first ping goes out on the first loop instead
    of being delayed past the 60s server timeout; on any drop, reconnect
    with exponential backoff capped at 60s and resubscribe. `connect` is
    injectable for tests. Limits: 10 WS connections/IP, 1000 subscriptions,
    2000 messages/min; use ONE connection for all coins.
- positions.py
  - parse_positions(state) -> {coin: {szi, entryPx, positionValue,
    unrealizedPnl, leverage, liquidationPx}} skipping szi == 0;
    account_summary(state).
  - diff(prev, cur, min_change_usd) -> events opened / closed / flipped /
    increased / decreased. EVERY event type must respect min_change_usd
    (for a flip, use max(old, new) notional) or dust flips spam you.
  - describe_event: "HLP child A: opened short ETH ~$120,000. Public data,
    informational only, not a signal."
- alerts.py: Alerter(webhook_url=None, log_path=None). Always print; if
  log_path, append JSONL; if webhook, POST {"text": msg, "content": msg}.
  Wrap the POST in `except Exception`, log "webhook error (continuing)",
  never crash.
- tracker.py (argparse; --testnet and --full-address on EACH subcommand;
  print a banner "Public Hyperliquid data. Informational and research use
  only; not advice and not a signal."):
  - trades --coins BTC,ETH,SOL --min-usd 1000000 [--duration S]
    [--webhook URL or env HLW_WEBHOOK_URL] [--log trades.jsonl]
    [--include-snapshot]
  - recent --coins BTC,ETH --min-usd 250000
  - positions ADDR... | --watchlist FILE [--top 10]
  - watch ADDR... | --watchlist FILE [--interval 60 (min 30)]
    [--min-change-usd 100000] [--max-loops N] [--webhook] [--log].
    The first read is a silent baseline; only later changes alert.
  - fills ADDR [--min-usd 100000] [--last 20]
- tests/conftest.py inserting the project root into sys.path.
- tests/ (pytest, fake sessions and fake websockets, no network):
  notional + taker side (threshold fixtures must compute notional the
  SAME way as the code, float(px) * float(sz), and sit clearly above or
  below the threshold), multi-fill aggregation, zero-hash not merged,
  dedupe, threshold, snapshot skipped + reset on reconnect, control
  messages ignored, run() subscribes/pings/reconnects, address validation
  + 10-address cap, position diff incl. a small flip below threshold
  ignored, vault_children parsing, first ping sent immediately after each
  connect, neutral wording (no "buy now", "follow", "copy"), testnet URLs,
  429 backoff, webhook that raises, and a grep test that the APP MODULES
  (not tests/) contain none of "/exchange", "private_key", "eth_account",
  "Exchange(", "place_order", "market_open", "auto_follow", "copy_trade".
- .gitignore (.env, __pycache__/, .venv/, *.jsonl, watchlist.txt), README
  with the commands and the informational-only notice.

Show me the file plan first. After writing, tell me exactly what to run.

How do you build it, step by step?

  1. Set up a clean folder (hl-tracker) with the Safety Pack rules file, then paste the prompt into your AI coding tool. Approve the file plan before it writes code, and check that it contains nothing that trades.
  2. Install and run the tests (they pass offline):
    python3 -m venv .venv && source .venv/bin/activate
    pip install requests websocket-client pytest
    python3 -m pytest -q
    
  3. Do a quick REST check: python3 tracker.py recent --coins BTC,ETH --min-usd 100000. recentTrades only returns about 10 trades per coin, so you'll often see nothing above the threshold. That's expected.
  4. Stream live trades for a few minutes:
    python3 tracker.py trades --coins BTC,ETH,SOL,HYPE --min-usd 100000 --duration 180 --log trades.jsonl
    
    The final stats line should show snapshot_skipped > 0 (the old trades it ignored) and orders with many fills grouped into one line.
  5. Look at public accounts. Put up to 10 addresses in watchlist.txt (kept out of git), for example the HLP vault's child accounts, or pass --vault 0xdfc24b077bc1425ad1dea75bcb6f8158e10df303 (HLP, the docs' vaultDetails example). The parent vault shows equity but no positions; vaultDetails → childAddresses lists the accounts that hold them. Then run python3 tracker.py positions --watchlist watchlist.txt --top 5 and python3 tracker.py fills <address> --last 10.
  6. Watch for changes: python3 tracker.py watch --watchlist watchlist.txt --interval 60 --min-change-usd 100000 --max-loops 3. The first loop only records a baseline.
  7. Test the plumbing on testnet: python3 tracker.py trades --testnet --coins BTC,ETH --min-usd 1000 --duration 60. Testnet volume is thin, so you may see no flags at all.

How do you test it in paper or demo mode first?

This recipe is read-only from start to finish, so there's nothing to paper-trade. It holds no key and has no code path that can place an order. Testnet support lets you check the websocket, reconnect and alert plumbing against a second network.

We deliberately left out any "follow this address" or copy feature, and BotCookery won't publish one. If you want to experiment with orders on Hyperliquid, use a separate project on testnet with the Hyperliquid API starter, the kill switch and position limits and the Wallet-Key Safety Pack, and base it on your own rules, not on someone else's trades.

What safety checks does it need before real money?

Tick every box before the bot touches real money. The full rules file, .gitignore and pre-commit hook are in the Safety Pack.

Which official docs did we check?

Endpoints and rules were checked against these pages on Oct 22, 2026. APIs change, so if something here disagrees with the official docs, trust the docs and tell us.

Frequently asked questions

How do I track whale trades on Hyperliquid?

Subscribe to the public trades websocket for each coin and compute size × price for each trade. Then group the trades by order hash, because one large order is usually many fills, and flag groups above a USD threshold. No API key is needed. This recipe's tracker does that and labels every alert informational only.

How do I get Hyperliquid trades over the websocket?

Connect to wss://api.hyperliquid.xyz/ws and send {"method":"subscribe","subscription":{"type":"trades","coin":"BTC"}}. You'll get a subscriptionResponse, then trades messages with coin, side, px, sz, hash, time, tid, users. The first trades message is a snapshot of about 30 recent trades and isn't marked as one, so skip it if you only want new trades.

Is the side field the buyer or the taker?

It's the taker (aggressor) side. We checked this against userFills: the account on the taker side of an A (sell) trade showed crossed: true. users is always [buyer, seller], so the taker is users[0] when side is B and users[1] when it's A.

How do I see another address's positions on Hyperliquid?

POST {"type":"clearinghouseState","user":"0x..."} to https://api.hyperliquid.xyz/info. You get assetPositions (coin, signed size szi, entry price, position value, unrealized PnL, leverage, liquidation price) and a marginSummary. It's public and needs no key. If you pass an agent (API) wallet address you'll get empty data; use the main account. A parent vault such as HLP also shows equity with no positions: ask vaultDetails for its childAddresses and read those.

How many past fills can I get for an address?

userFills returns at most the 2,000 most recent fills. userFillsByTime pages by time, but only the 10,000 most recent fills are available at all. For a busy account, that's a recent slice, not its whole history.

Can this tracker copy or follow a whale's trades?

No, by design. It has no key and no order code, and the prompt tells your AI tool not to add a follow, mirror or copy feature. BotCookery doesn't publish copy-trading tools. The tracker reports public data for research. It doesn't tell you what to do.

Is a large trade or a big position a signal?

Not on its own, and this recipe doesn't treat it as one. A large taker order might be a hedge, a liquidation, a rebalance or one leg of a trade elsewhere. BotCookery doesn't give financial advice.

Hyperliquid Funding Rate Monitor: Read-Only Python Alerts (2026)

An AI prompt that builds a read-only Hyperliquid funding-rate monitor in Python: current and predicted funding per perp, annualized, with threshold alerts to the console or a webhook, on mainnet or testnet. No keys, no orders.

Hyperliquid Read-only (no keys) Beginner

More from the kitchen: Recipes by platform · Kalshi & Polymarket fee calculator · AI model test results · Safety Pack