๐ŸŽ“ Tutorials

Hyperliquid Python SDK Tutorial: Build a Bot (2026)

โš ๏ธ Disclosure: Some links on this page are affiliate links. If you sign up through them, I may earn a commission โ€” at no extra cost to you. I only review tools I actually use.
# Hyperliquid Python SDK Tutorial: Build a Bot (2026)

> About this guide: I'm the writer behind supa.is. Between February and May 2026 I've published 150+ articles on supa.is across crypto and brokerage tooling โ€” including 30+ Hyperliquid-specific guides (recent examples: Hyperliquid setup walkthrough, cross vs isolated margin on Hyperliquid, Hyperliquid zero-fee assets). The most-repeated reader question across that Hyperliquid archive is exactly how to wire the official Python SDK to a working perp bot without losing keys or getting rate-limited, which is why I'm publishing this standardized guide instead of answering one-off.

> Note: Code patterns below are reconstructed from the official Hyperliquid Python SDK (github.com/hyperliquid-dex/hyperliquid-python-sdk) and the Hyperliquid developer docs (hyperliquid.gitbook.io/hyperliquid-docs) as of 2026-04. SDK method names and request shapes change between releases โ€” pin your dependency, read the upstream CHANGELOG.md, and verify every snippet against the current SDK before pointing it at real funds.

Why use the Python SDK at all

You can talk to Hyperliquid in three ways: the official Python SDK, raw HTTPS POSTs against the documented /info and /exchange endpoints, or the WebSocket feed. The SDK is a thin wrapper that handles three things you genuinely don't want to write yourself:

1. EIP-712 message signing. Every order, cancel, and transfer on Hyperliquid is a signed action โ€” not just an authenticated REST call. Getting the typed-data structure, chain ID, and signing primitive wrong silently rejects orders with cryptic "User or API Wallet ... does not exist" errors.

2. Tick/lot rounding. Each perp has a pxDecimals and szDecimals constraint enforced by the matching engine. Submitting 0.1234567 when the symbol allows three decimals returns a generic error. The SDK's meta() payload tells you the precision per symbol โ€” verify against the current Hyperliquid developer docs (hyperliquid.gitbook.io/hyperliquid-docs) before relying on cached values. 3. Nonce and signature replay protection. The SDK auto-increments the nonce per signing wallet so you don't accidentally reuse one and get an order silently dropped.

If you're building a discretionary alert bot, raw HTTP works. If you're placing thousands of orders a day or running a market-maker, the SDK saves a week of debugging. The rest of this article assumes the SDK route.

Installation and project layout

The SDK is on PyPI as hyperliquid-python-sdk (PyPI page):

pip install hyperliquid-python-sdk

Pin the version in requirements.txt or pyproject.toml rather than tracking latest โ€” the SDK occasionally renames symbols between minor versions, and a silent upgrade in CI can break a live bot at 3 a.m.

Top-level modules you'll touch most:

ModulePurpose
hyperliquid.infoRead-only market data, user state, fills history
hyperliquid.exchangePlace/cancel orders, transfer USDC, update leverage
hyperliquid.utils.constantsMAINNET_API_URL, TESTNET_API_URL
hyperliquid.utils.signingLower-level signing helpers (rarely needed directly)
hyperliquid.websocket_managerStreaming subscriptions to L2 books, trades, user events
A minimal bot typically has one Info client (for polling), one Exchange client (for sending orders), and one WebsocketManager (for live state).

The API wallet model โ€” read this before generating any keys

This section is where most first-time bot developers lose money. Hyperliquid uses an API wallet (also called an agent wallet) abstraction โ€” search for "API wallets" or "agents" in the Hyperliquid docs to find the canonical reference. The mechanism is also encoded directly in the SDK's examples/ folder in the SDK repo.

Mental model:

This split is the difference between "a server compromise costs you whatever's in your perp account" and "a server compromise costs you everything in your wallet, on every chain."

In code, the pattern looks like this:

import eth_account
from hyperliquid.exchange import Exchange
from hyperliquid.info import Info
from hyperliquid.utils import constants

main_wallet_address = "0xYourMainWalletAddress"
api_wallet_secret   = "0xPrivateKeyOfTheAGENTWalletYouAuthorized"

agent = eth_account.Account.from_key(api_wallet_secret)

info = Info(constants.MAINNET_API_URL, skip_ws=True)
exchange = Exchange(
    wallet=agent,
    base_url=constants.MAINNET_API_URL,
    account_address=main_wallet_address,
)

Three things to verify before you run this:

1. The address derived from api_wallet_secret is not the same as main_wallet_address. If you accidentally put your main key into api_wallet_secret, the SDK will happily sign with it and you've negated the entire safety story.

2. The agent wallet has been authorized in the Hyperliquid UI under the API tab. Unauthorized agents return "User or API Wallet ... does not exist". 3. Your account_address (the main wallet) matches the wallet you authorized the agent for. The signing wallet and the funded wallet are different โ€” the SDK separates them via account_address.

For a refresher on the underlying account model and how isolated margin behaves under the same main wallet, the margin-mode comparison explains why you might want one agent per sub-strategy.

Reading market data with Info

The Info client wraps the public read endpoints described in the Hyperliquid developer docs. Common calls during a bot's hot path:

meta = info.meta()                       # all perp metadata: szDecimals, maxLeverage, etc.
all_mids = info.all_mids()               # latest mid prices keyed by symbol
user_state = info.user_state(main_wallet_address)
open_orders = info.open_orders(main_wallet_address)
fills = info.user_fills(main_wallet_address)

meta() is the one you care about at startup. Each entry has szDecimals (size precision) and maxLeverage, and you should cache it. Submitting an order whose size doesn't conform to szDecimals is a silent rejection in many SDK versions โ€” the matching engine returns an error string the SDK passes through, and rookie bots log it as "weird API blip" and retry forever.

user_state returns the canonical view of your account: margin summary, asset positions, withdrawable USDC. Use this โ€” not your bot's internal accounting โ€” as the source of truth after every fill.

For historical data, info.candles_snapshot(coin, interval, start_ms, end_ms) returns OHLCV bars. The interval set is fixed (1m, 3m, 5m, 15m, 1h, 4h, 1d, 1w as documented in the SDK source) โ€” you can't request 7-minute bars; resample yourself.

Placing orders with Exchange

The Exchange client wraps the signed write endpoints. The single most common call:

result = exchange.order(
    name="ETH",
    is_buy=True,
    sz=0.1,
    limit_px=2500.0,
    order_type={"limit": {"tif": "Gtc"}},
    reduce_only=False,
)

A few things that aren't obvious from the signature:

The result dict needs to be parsed carefully. A successful submission returns:

{"status": "ok", "response": {"type": "order", "data": {"statuses": [{"resting": {"oid": 12345678}}]}}}

๐Ÿ’ก Hyperliquid

Like what you're reading? Try it yourself โ€” this link supports ChartedTrader at no cost to you.

Open a Hyperliquid account (4% fee discount on first $25M of volume) โ†’
๐ŸŽ You receive: 4% fee discount on first $25M volume ยท per account, lifetime

But a partially filled order looks like:

{"status": "ok", "response": {"type": "order", "data": {"statuses": [{"filled": {"oid": ..., "totalSz": "0.05", "avgPx": "2500.1"}}]}}}

And a rejection looks like:

{"status": "ok", "response": {"type": "order", "data": {"statuses": [{"error": "Insufficient margin"}]}}}

Note that the outer status is still "ok" even when the inner status is error. This is the single most common silent-bug source in beginner Hyperliquid bots: code checks result["status"] == "ok" and assumes the order made it. Always inspect result["response"]["data"]["statuses"][i].

Managing positions, leverage, and transfers

Setting leverage before a trade:

exchange.update_leverage(leverage=3, name="ETH", is_cross=True)

Closing a position is just an opposite-side reduce_only=True order. There is no dedicated "close" method โ€” reduce_only is the contract.

USDC transfers between perp and spot wallets, and between cross/isolated margin sub-accounts, also live on Exchange:

exchange.usd_transfer(amount=100.0, destination=main_wallet_address)

Note that the agent wallet cannot withdraw to a different address โ€” that operation requires a signature from the main wallet. This is the safety guarantee from the previous section made concrete.

If you plan to scale up volume, the Hyperliquid 4% fee discount math covers how the per-account $25M referral cap interacts with HYPE-staking discounts โ€” both apply automatically as long as your main wallet was registered through a referral link, no SDK setting required.

WebSocket subscriptions for live state

For anything beyond a slow polling loop, use the WebSocket feed:

from hyperliquid.websocket_manager import WebsocketManager

ws = WebsocketManager(constants.MAINNET_API_URL)
ws.start()

def on_l2(msg):
    print(msg["data"]["levels"])

ws.subscribe({"type": "l2Book", "coin": "ETH"}, on_l2)
ws.subscribe({"type": "userEvents", "user": main_wallet_address}, lambda m: print(m))

Useful subscription types:

ChannelWhat you get
l2BookOrder book snapshots and updates per coin
tradesPublic trade prints
userEventsYour fills, funding payments, liquidations
userFillsJust fills (lighter than userEvents)
candleOHLC bars, useful for low-latency strategy ticks
Two practical notes: WebSockets disconnect โ€” wrap your WebsocketManager in a supervisor that reconnects and re-subscribes on close. And reconcile your in-memory state against info.user_state() periodically; missed messages do happen, especially during spikes.

Rate limits, error handling, and idempotency

Search the Hyperliquid developer docs for the current rate-limit numbers and verify before sizing your strategy โ€” they have changed across releases. Three patterns from production hold across versions:

1. Batch where possible. exchange.bulk_orders([...]) submits multiple orders in one signed action and counts as a single rate-limit unit. A market-maker placing 20 quotes per second should never call order() 20 times.

2. Use cloid for idempotency. Pass a client order ID (cloid) on every order() call. If your bot crashes mid-send and you retry, the matching engine will reject the duplicate by cloid rather than placing two orders. Generate a UUID per intent and log it before sending. 3. Don't busy-poll user_state from the hot path. Many beginner bots call info.user_state() after every order to "confirm." This eats your read-budget and lags behind WebSocket userFills anyway. Confirm via WebSocket; treat user_state as a slow reconciliation tool every 30โ€“60 seconds.

Ten pitfalls that cost beginner bots money

1. Confusing main wallet and agent wallet โ€” covered above. The single highest-stakes mistake.

2. Not pinning the SDK version. A pip install --upgrade in a deploy script can silently change a method signature. 3. Treating result["status"] == "ok" as success. The inner statuses list is the real signal. 4. Submitting non-tick-aligned prices. Always round limit_px to the symbol's pxDecimals. 5. Using Gtc when you meant Alo. Gtc will cross the book and pay taker fees if your price is aggressive โ€” silently turning a maker strategy into a taker strategy. 6. Ignoring funding rate accruals. Funding is paid hourly on perps; if you carry positions overnight without modeling it, your post-fee P&L will diverge from your simulated P&L. 7. No cloid on retries. Network-flaky deploys end up with duplicate orders. 8. Hardcoding asset indexes. Indexes shift when new perps list โ€” always look up by symbol via meta(). 9. WebSocket without a watchdog. Disconnections that don't auto-reconnect leave a bot trading on stale state. 10. Testing on mainnet "just to be sure." Testnet (constants.TESTNET_API_URL) is a near-clone of mainnet for SDK behaviour. Use it.

SDK vs raw HTTP: when to drop down

ConcernSDKRaw HTTP
EIP-712 signingHandledYou implement
Symbol โ†’ asset index lookupAuto via meta()You cache and refresh
Tick rounding helpersBuilt inYou write them
Custom transports (e.g. aiohttp connection pooling)LimitedFull control
Footprint in a Lambda cold-startHeavierMinimal
Multi-language stack (e.g. Rust signing, Python orchestration)Forces Python signing pathCleaner separation
Rule of thumb: start on the SDK. Drop to raw HTTP only if profiling shows the SDK is the bottleneck (rare) or if you genuinely need a custom transport.

Production checklist before pointing it at real USDC

If you're still working through wallet setup and your first hand-placed perp before automating any of this, the Hyperliquid post-signup setup checklist covers the prerequisite manual flow, and the trailing stop setup guide shows how the same order primitives behave from the UI before you wire them into Python.

Open a Hyperliquid account before pointing the bot at real funds

Everything above assumes you already have a funded Hyperliquid main wallet with an authorized API agent. If you don't, the cleanest path is:

1. Sign up via the referral link: https://app.hyperliquid.xyz/join/RICH888. The 4% fee discount tier is set at the moment of registration โ€” Hyperliquid does not let you backfill a referral onto a wallet that was created without one. For a bot that does any meaningful taker volume, that single click is the difference between paying full taker fees forever and paying the discounted rate from your first fill. The exact math against the per-account volume cap is broken down in the 4% fee discount cap explainer.

2. Bridge USDC to the perp account (the USDC bridging walkthrough from OKX is the most common path for non-US users). 3. Generate the API agent wallet in the API tab and authorize it for your main wallet. Save *only the agent private key* on the server. Never copy the main wallet's seed phrase or private key onto any machine the bot runs on. 4. Place one manual perp trade through the UI before the bot ever submits an order โ€” it's the cheapest way to catch a margin-mode or symbol-permission misconfiguration.

> CTA โ€” Open a Hyperliquid account with the referral discount applied: Sign up here โ†’

The discount stacks with the HYPE-staking fee tier when you eventually qualify, and neither requires any flag inside the SDK โ€” both apply automatically based on the main wallet's registration state and on-chain stake.

Wrap-up

The Hyperliquid Python SDK is small enough to read end-to-end in an afternoon, and most production bugs come not from the SDK itself but from misunderstanding the API wallet model, the inner-status response shape, and the tick/lot/oracle-band constraints the matching engine enforces. If you internalize those three things, pin your SDK version, use cloid everywhere, and reconcile WebSocket state against info.user_state() on a slow timer, you're ahead of nearly every beginner bot operator on the venue.

Build it on testnet first, keep your main key cold, let the agent wallet do the talking โ€” and if you haven't already, open the account through the referral link before you ever fund it, so the fee discount is locked in for the life of the wallet.

๐Ÿงฎ Free Hyperliquid calculators

Fee Calculator โ†’
Hyperliquid vs centralized exchange fee comparison
PnL & Liquidation โ†’
Perp PnL + liquidation price
Position Size โ†’
Risk-aware position sizing for HL perps
Hyperliquid

Ready to get started? Use the link below โ€” it helps support ChartedTrader at no cost to you.

Open a Hyperliquid account (4% fee discount on first $25M of volume) โ†’
๐ŸŽ You receive: 4% fee discount on first $25M volume ยท per account, lifetime
๐Ÿ“ˆ

About the author

I'm a systematic trader running live strategies on IB (USDJPY momentum) and Hyperliquid (crypto perps). Every tool reviewed here is something I've used with real capital. Questions? Reach out.

๐Ÿ“š Related Articles

๐ŸŽ“ Tutorials

TradingView Paper Trading Without Real Money (2026)

Practice trading on TradingView with $100K paper money โ€” setup, realistic commissions, common beginner mistakes, when to switch to real cash.

May 5, 2026 โฑ 12 min read
๐ŸŽ“ Tutorials

How to Trade Solana (SOL) Perpetual Futures on OKX: CLI and Web Guide (2026)

Complete guide to trading SOL perpetual futures on OKX using the CLI and web interface. Covers market data, position management, trailing stops, grid bots, and DCA bots โ€” all commands tested on okx-cli v1.2.3.

March 14, 2026 โฑ 13 min read
๐ŸŽ“ Tutorials

OpenClaw + Xerolite: Set Up an AI Trading Bot for Interactive Brokers โ€” Step-by-Step (2026)

Learn how to connect OpenClaw AI to Interactive Brokers through Xerolite and place real stock trades with natural language. Full setup walkthrough with IB Gateway, API permissions, and security best practices.

March 13, 2026 โฑ 11 min read

๐Ÿ“ฌ Get weekly trading insights

Real trades, honest reviews, no fluff. One email per week.