— Contents 11 sections
- 01 Can you run a trading bot on Hyperliquid?
- 02 What you need before you start
- 03 Understanding the Hyperliquid API
- 04 Creating your API wallet, safely (there is no API key)
- 05 Practice on the Hyperliquid testnet first
- 06 Placing your first order with Python
- 07 From script to bot: running it unattended
- 08 Hyperliquid rate limits and common errors
- 09 Security and risk checklist
- 10 Conclusion and next steps
- 11 Frequently asked questions
There are two common ways to automate trading on Hyperliquid: a third-party bot product you subscribe to, and a bot you write yourself using the API — the exchange ships no bots of its own. This guide covers the second kind, end to end: how the Hyperliquid API works, how API wallets replace API keys so your funds stay out of reach of the bot, how to verify your setup without risking anything, and how to place your first automated order. No prior automation experience is assumed. Trading strategy — deciding when to buy and sell — is not covered; the goal of this guide is working infrastructure.
Can you run a trading bot on Hyperliquid?
Yes — and unlike the big centralized exchanges, Hyperliquid has no built-in bot products at all: no grid bot, no DCA bot, no copy trading. What the platform does ship natively is narrower and more infrastructural. Vaults are pooled capital traded by one leader or strategy, with depositors sharing the profit and loss (the current generation is built on HyperEVM, the chain’s smart-contract half, superseding the original native vaults) — the closest thing to copy trading here, though it is a capital-pooling product rather than a mirror of someone’s clicks, and the docs’ own caution applies: assess a vault’s risks and history before depositing. TWAP orders slice a large order into timed sub-orders natively, so execution slicing is not something you need to build. And a scheduled cancel-all (a dead man’s switch — an automatic safety trigger for when your bot dies) exists purely for API users. Automated trading is plainly a first-class use case: Hyperliquid maintains a first-party Python SDK, documents a recommended bot architecture, and states that no market maker gets special fees or latency — your bot uses the same API as everyone else’s.
There are two routes to a bot that trades your account:
| Route | Effort | Flexibility |
|---|---|---|
| Third-party bot platforms (hosted services, Telegram bots) | Low — configure on the vendor’s side | Depends on the vendor |
| Your own bot via the API | High — you write and run the code | Unlimited |
The custody question weighs heavier here than on a centralized exchange: any bot you don’t run yourself needs signing power over your account, which means handing the vendor a private key — at best a restricted API-wallet key, at worst your actual wallet key. The rest of this guide covers the second route: building your own bot with the API. The logic stays under your control, and every key stays with you.
What you need before you start
- An EVM wallet (any Ethereum-compatible wallet) with a funded Hyperliquid account. There is no registration form and no identity verification (KYC) anywhere in onboarding — you connect a wallet (the docs name Rabby, MetaMask, WalletConnect and Coinbase Wallet) and deposit USDC. Two costs to know before funding: the first transfer into a brand-new account pays a one-time 1 USDC activation fee, and the deprecated Arbitrum bridge — not the route to use, but still live — has a 5 USDC minimum below which a deposit is lost — so fund with a sensible amount once, not with dust. If you don’t have an account yet, our Hyperliquid review covers onboarding, deposits and fees step by step.
- Python 3 on any machine that can stay online while your bot runs,
plus the official
hyperliquid-python-sdkpackage — the guide uses plain HTTP requests for every API call and borrows only the SDK’s signing module, the one part the docs say not to write yourself. - A small amount of capital you can afford to lose. The minimum perpetual order is $10 of notional value (price × size), so a first live order can stay genuinely small.
- An hour or two. Everything in this guide can be completed in one sitting.
One eligibility note before any of that: the Terms of Use bar persons in the United States and Ontario, Canada from using the official interface, and the project states it holds no license in any jurisdiction. Read the Terms and check your own position before trading.
This guide works with perpetual futures (leveraged contracts that track a spot price and never expire) throughout — that is Hyperliquid’s main market, and spot trading uses the same endpoints with a different asset id and decimal cap. Perps carry leverage, and leverage plus unattended code is a sharp combination: the examples here size orders near the $10 minimum, and an unattended leveraged position is the main thing the closing risk checklist is for.
Understanding the Hyperliquid API
An API (application programming interface) is simply a way for your program to talk to the exchange directly — the same actions you perform in the app (check a price, place an order, read your balance), but issued by code and answered in machine-readable JSON.
Hyperliquid’s API surface is unusually small: two HTTP endpoints and one
WebSocket URL. Every read — prices, candles, balances, positions, orders,
fills — is a POST to /info. Every write — orders, cancels, transfers —
is a POST to /exchange. The WebSocket (a persistent connection the
server pushes live data through) streams market data and can carry the same
requests. There are no REST-style GET routes at all; the operation is
selected by a type field in the JSON body.
Two facts shape everything that follows:
Reads need no authentication of any kind. Not just market data — any account’s state. Because Hyperliquid’s state lives on a public blockchain, anyone can query any address’s positions and fills with no credentials. This works from any terminal, with no account:
curl -s -X POST https://api.hyperliquid.xyz/info \
-H "Content-Type: application/json" -d '{"type":"allMids"}'
Writes are authorized by wallet signatures, not credentials. There is
no API key to create (the next section covers what replaces it). Every
/exchange request carries a signature from an Ethereum private key.
On cost: API access itself is free, trading is gas-free, and orders placed
through the API pay the same fees as the app — for a new account that is
0.045% taker / 0.015% maker on perps (spot is higher; a maker order rests
on the book, a taker order fills against it). A taker round trip therefore
costs about 0.09% before any price movement — fee drag is a structural cost
of frequent trading, not an afterthought. Bookmark the
official documentation;
one orientation note for reading it: the docs tree also covers HyperEVM, a
separate smart-contract environment with its own JSON-RPC interface —
trading never touches it, so if you find yourself reading about eth_*
methods, you are in the wrong half of the docs. The API also labels itself
v0 and signals a breaking v1 with no date, one more reason to date-stamp
your integration.
Creating your API wallet, safely (there is no API key)
The most important correction for anyone arriving from a centralized exchange: Hyperliquid has no API keys. No secret, no passphrase, no IP whitelist, no permission checkboxes. Searching for the “create API key” page is the number one way beginners lose an afternoon here, because the thing it finds — your wallet’s private key — is the one credential you should never give a bot.
What replaces the API key is the API wallet (the docs also say agent wallet): a second keypair that your master account authorizes to sign on its behalf. The permission split is structural, not a settings toggle — an API wallet can place orders, cancel and change leverage, but the official SDK states it plainly: “The agent does not have permission to transfer or withdraw funds.” Withdrawals and transfers require the master key, always. A leaked API-wallet key can lose you trades; it cannot drain the account. That is a stronger guarantee than a CEX permission checkbox, and it is the single best reason to trade through an API wallet from day one.
You can create a named API wallet in the app at app.hyperliquid.xyz/API,
or do it in code with the master key — the SDK generates the agent key
locally, and only the derived address ever leaves your machine:
# pip install hyperliquid-python-sdk
# one-time setup, run with the MASTER key; store the printed agent key safely
import eth_account, os
from hyperliquid.exchange import Exchange
master = eth_account.Account.from_key(os.environ["HL_MASTER_KEY"])
result, agent_key = Exchange(master, "https://api.hyperliquid.xyz").approve_agent("mybot")
print(result) # {'status': 'ok', ...}
print(agent_key) # the new API wallet's private key — shown here and nowhere else
Three rules from the nonces and API wallets page prevent the classic failures:
- Query with the master address, never the agent address. API wallets only sign. Asking the API for the agent address’s balance returns an empty account — the docs name this exact pitfall, and it looks exactly like a broken API.
- One API wallet per trading process. Nonces (numbers used once, which stop a captured request from being replayed) are tracked per signing key, so two processes sharing one agent key will collide.
- Never reuse a deregistered agent’s address. Its nonce history can be pruned, which reopens old signed actions to replay. Generate a fresh key instead — an account gets one unnamed plus up to three named agents, with more per sub-account, and a named agent can carry an expiry of up to 180 days.
Handle both keys like passwords: environment variables or a config file excluded from version control, never hardcoded, never pasted into a third-party site. The master key deserves stricter treatment still — it approves agents and moves money, so it belongs on your own machine (or in cold storage), not on the server the bot runs on. The full key and signing detail — both signing schemes, the typed-data internals, and every operation an agent can and cannot sign — is in our Hyperliquid API guide.
Practice on the Hyperliquid testnet first
Hyperliquid runs a full testnet: the same API at
https://api.hyperliquid-testnet.xyz, with its own app at
app.hyperliquid-testnet.xyz and a faucet that grants 1,000 mock USDC.
One gate surprises almost everyone: the faucet only works for addresses
that have already deposited on mainnet. You cannot rehearse with play
money before ever funding a real account — so the risk-free path runs in a
different order than on a CEX, from cheapest to most committed:
- Every read works right now, with nothing. All the market-data and account queries in this guide run against mainnet or testnet with no funds, no account and no setup.
- Signing can be proven offline. The official SDK publishes a throwaway test key with the expected signature for a fixed order, so you can verify your signing setup with no network connection at all — this matters because a wrong signature never errors on your machine, it just gets rejected by the server:
# pip install hyperliquid-python-sdk — offline signing self-check
import eth_account
from hyperliquid.utils.signing import sign_l1_action
test_wallet = eth_account.Account.from_key(
"0x0123456789012345678901234567890123456789012345678901234567890123")
test_action = {"type": "order",
"orders": [{"a": 1, "b": True, "p": "100", "s": "100",
"r": False, "t": {"limit": {"tif": "Gtc"}}}],
"grouping": "na"}
sig = sign_l1_action(test_wallet, test_action, None, 0, None, True)
assert sig["r"] == "0xd65369825a9df5d80099e513cce430311d7d26ddf477f5b3a33d2806b100d78e"
print("signing verified against the official test vector")
The key comes from the SDK’s public test suite — it holds no real funds and is safe to print precisely because it is not a real secret; never reuse it for anything real. 3. Deposit once on mainnet, then rehearse orders on testnet. After a real deposit unlocks the faucet, every order in the next sections can be practiced with mock USDC first.
Testnet code differs from mainnet code in exactly two places, and both must move together: the base URL, and the network flag passed to the signing function. Signing with the mainnet flag and posting to testnet (or the reverse) produces the misleading “does not exist” error covered in the errors section — which is why the helper in the next section derives the flag from the base URL instead of taking it separately, so the two cannot drift apart. One more trap: asset indices differ between networks — on 2026-08-18, mainnet asset 0 was BTC while testnet asset 0 was SOL — so never hardcode an asset id; always resolve names on the network you are pointed at, as the next section does.
Placing your first order with Python
The snippets below use plain Python with the requests library for every
API call, and the official SDK only for signing. Everything builds on one
small helper file:
# pip install hyperliquid-python-sdk (brings the official signing module + requests)
import os, requests, eth_account
from hyperliquid.utils.signing import sign_l1_action, float_to_wire, get_timestamp_ms
BASE = "https://api.hyperliquid-testnet.xyz" # mainnet: https://api.hyperliquid.xyz
IS_MAINNET = BASE == "https://api.hyperliquid.xyz" # signing flag must follow the URL
# The API wallet's key signs trading actions; it cannot move funds.
# ADDRESS is the funded master account — every query uses it, never the agent's.
wallet = eth_account.Account.from_key(os.environ["HL_API_WALLET_KEY"])
ADDRESS = os.environ["HL_MASTER_ADDRESS"].lower()
def info(payload):
r = requests.post(f"{BASE}/info", json=payload)
r.raise_for_status()
return r.json()
def exchange(action):
nonce = get_timestamp_ms() # ms timestamp; also the nonce
sig = sign_l1_action(wallet, action, None, nonce, None, IS_MAINNET)
r = requests.post(f"{BASE}/exchange", json={
"action": action, "nonce": nonce, "signature": sig,
"vaultAddress": None, "expiresAfter": None})
r.raise_for_status()
return r.json()
Before any order, resolve the market’s integer id and rounding rules from
the live meta response — indices shift as assets list and delist, and
sizes and prices that ignore the rounding rules are the number one cause
of first-order rejections:
# continuing in the same file
meta = info({"type": "meta"})
live = [(i, a) for i, a in enumerate(meta["universe"]) if not a.get("isDelisted")]
ASSET = {a["name"]: i for i, a in live} # name -> asset index
SZ_DECIMALS = {a["name"]: a["szDecimals"] for i, a in live}
def round_px(px, coin): # the official rounding recipe (SDK examples/rounding.py)
if px > 100_000: # integer prices are always allowed
return round(px)
return round(float(f"{px:.5g}"), 6 - SZ_DECIMALS[coin]) # perps; spot uses 8
def round_sz(sz, coin): # sizes round to the asset's szDecimals
return round(sz, SZ_DECIMALS[coin])
The rules those helpers encode: a price may have at most 5 significant
figures and at most 6 - szDecimals decimal places (integer prices are
always allowed, which is why a BTC price like 64178 is valid); a size
rounds to the asset’s szDecimals; and the order’s value must clear
$10. Now the order itself — a small limit buy priced a few percent
below the mid (the midpoint between best bid and best offer), so it rests
on the book instead of filling:
# continuing in the same file
mid = float(info({"type": "allMids"})["ETH"])
px = round_px(mid * 0.97, "ETH") # a few percent below — rests, doesn't fill
sz = round_sz(12 / mid, "ETH") # ~$12 at the mid (~$11.6 at the order price) — clears $10 with room
result = exchange({"type": "order",
"orders": [{"a": ASSET["ETH"], "b": True,
"p": float_to_wire(px),
"s": float_to_wire(sz),
"r": False,
"t": {"limit": {"tif": "Gtc"}}}],
"grouping": "na"})
float_to_wire is the SDK’s number formatter — prices and sizes travel as
strings with trailing zeroes removed, and it raises rather than silently
rounding a value it cannot represent exactly; the tick and lot rules are
still yours to apply first, which is what the helpers above do. "Gtc" (good-till-canceled) rests until
filled or canceled; the other two time-in-force values are "Alo"
(post-only) and "Ioc" (fill immediately or cancel the rest — which is
also how market orders work here: there is no market order type, only an
aggressively priced IOC limit).
Read the verdict from inside the response, not from the HTTP status.
A rejected order still returns HTTP 200 with a top-level "ok" — the
per-order result is nested, and code that doesn’t look at it will believe
every order succeeded. This helper belongs in every script:
# continuing in the same file
def order_statuses(result):
if result["status"] != "ok": # signature/account-level failure
raise RuntimeError(result["response"])
return result["response"]["data"]["statuses"]
for st in order_statuses(result):
if "error" in st:
print("rejected:", st["error"]) # e.g. 'Order must have minimum value of $10.'
elif "resting" in st:
print("resting on the book, oid", st["resting"]["oid"])
elif "filled" in st:
print("filled", st["filled"]["totalSz"], "@", st["filled"]["avgPx"])
If the order rested, cancel it to finish the round trip:
# continuing in the same file — cancel the test order
oid = order_statuses(result)[0]["resting"]["oid"]
exchange({"type": "cancel", "cancels": [{"a": ASSET["ETH"], "o": oid}]})
If it filled instead, you are holding a leveraged position rather than an
order, and canceling does nothing. Read the position first, then close it
with the opposite side — an IOC limit priced through the book, with
"r": True (reduce-only, so it can only shrink the position, never flip
it):
# continuing in the same file — inspect a filled test position before closing it
for p in info({"type": "clearinghouseState", "user": ADDRESS})["assetPositions"]:
pos = p["position"]
print(pos["coin"], pos["szi"], "liquidation at", pos["liquidationPx"])
# szi is signed size — positive long, negative short; close with the opposite side
This is the same request a production bot sends — only the base URL and
the mock funds differ. One habit to carry forward: leave optional fields
out of the action entirely rather than sending null or false — the
signature runs over the exact bytes of the action, so an absent field and
a null field are different payloads. (The outer envelope is not signed,
which is why the helper above can send vaultAddress: None safely.) Copy-paste code for every other common operation —
market orders, stop-losses, balances, transfers, withdrawals and WebSocket
streams — is collected in our Hyperliquid API guide.
From script to bot: running it unattended
A script becomes a bot when it runs in a loop unattended. Four mechanics keep an unattended process running reliably:
- The loop. Fetch data → decide → (maybe) order → sleep → repeat.
Start with a generous interval; a bot that acts once a minute is far
easier to debug and stays far away from rate limits. Polling
allMidsorclearinghouseStatecosts the smallest weight of any read the API has, so a slow loop is effectively free. - Expect disconnection. When you move from polling to the WebSocket,
know that the server closes any connection it hasn’t sent a message to
in 60 seconds — send
{"method": "ping"}on a ~30-second timer — and the docs are blunt that disconnects “may happen periodically and without announcement”. On reconnect, replayed history arrives taggedisSnapshot: true; filter it or you will double-count fills. Reconnect logic is mandatory, not optional. - The dangerous retry. If a request times out, the order’s fate is
unknown — it may still have gone through. Hyperliquid adds a constraint with no
CEX equivalent: an action not accepted within 15 seconds fails with
"Action already expired", protection that exists precisely because a delayed order landing late can mean duplicate fills. On any ambiguous failure: query your open orders and recent fills first, then decide. Never blind-retry an order. - Arm the dead man’s switch. This is the piece most exchanges make you
build yourself, shipped as an API action:
scheduleCancelcancels all your open orders at a future time, so orders don’t outlive a crashed process. Set the deadline to several loop intervals, never one — a deadline equal to the loop period fires between iterations of a healthy bot, and the ten-triggers-per-day cap is spent in minutes. Each re-arm is also an action against the address budget covered in the next section, so re-arm on a cadence you have budgeted for, not as fast as you can:
# continuing in the same file — orders die if the bot misses several beats
LOOP_SECONDS = 60
exchange({"type": "scheduleCancel",
"time": get_timestamp_ms() + 3 * LOOP_SECONDS * 1000})
# re-arm each iteration; omit "time" to clear. Min 5s ahead; max 10 triggers/day (resets 00:00 UTC)
Log every decision and every response, and keep a manual way to stop the bot and cancel everything immediately. Run one API wallet per bot process — the nonce rules make sharing a key between processes a collision, not a convenience. The trading logic itself — when to buy and when to sell — is out of scope for this guide. Get the mechanics above working against testnet first: infrastructure failures cost money regardless of how good the strategy is, so this layer deserves to be solid before any strategy complexity is added.
Hyperliquid rate limits and common errors
Hyperliquid runs two unrelated rate limiters, and the second has no
CEX analogue. The first is conventional: 1,200 request-weight per minute
per IP address. The reads a polling bot wants — allMids, l2Book,
clearinghouseState — cost weight 2, so you can poll a price ten times a
second all day; most other info requests cost 20, history queries add
extra weight per 20 items returned, and an exchange action costs
1 + floor(orders_in_batch/40).
The second limiter is per address, and earned by trading: 1 action per 1 USDC of cumulative traded volume since the address was created, on top of a starting buffer of 10,000 actions. Run it dry and the address is throttled to one action per 10 seconds until more volume earns more budget. A bot that churns orders and cancels without ever filling is spending a finite lifetime budget — “don’t resend a cancel you already got an answer for” is a correctness rule here, not politeness. Two details limit the damage: reads never count against it, and cancels get a carve-out so even a fully throttled bot can always pull its resting orders. One detail cuts the other way: batching helps only the IP limiter — a batch of n orders counts as n actions against the address budget. Check your own budget anytime, free:
# continuing in the same file
print(info({"type": "userRateLimit", "user": ADDRESS}))
# {'cumVlm': ..., 'nRequestsUsed': ..., 'nRequestsCap': ..., 'nRequestsSurplus': ...}
The docs specify no HTTP status code for hitting either limiter — the documented behavior is the 10-second throttle, so key retry logic on non-success responses with a backoff rather than watching for a 429 that is not promised.
The errors a first bot actually meets:
| Error | Meaning | Usual fix |
|---|---|---|
User or API Wallet 0x… does not exist. | wrong signature or unfunded account | the address test below |
Must deposit before performing actions. User: 0x… | account never funded | deposit first |
Price must be divisible by tick size. | price violates the rounding rules | the round_px helper |
Order must have minimum value of $10. | notional below the perp floor | size from the live mid |
Post only order would have immediately matched, bbo was … | Alo order priced through the book | reprice behind the echoed best bid/offer |
Order could not immediately match against any resting orders. | IOC found no liquidity within its limit | widen the price buffer |
Insufficient margin to place order. | perp balance can’t carry the order | check withdrawable; funds may sit on the spot side |
Order was never placed, already canceled, or filled. | canceling a dead order id | benign in cleanup loops |
Action already expired | action not accepted within 15 seconds | check connectivity; query state before retrying |
HTTP 422, Failed to deserialize the JSON body… | typo in the request body | fix the type field — this is not a signing problem |
The first row needs a decoder, because it is ambiguous by design: a wrong signature makes the server recover a different signer address (which has no funds), and a correct signature from an unfunded account fails identically. Compare the address in the error message to your own. If it differs, your signature is wrong — go back to the offline test vector. If it matches, your signing is fine and the account simply needs a deposit. The wrong-network flag from the testnet section is the most common way to land in the first branch.
Security and risk checklist
Two kinds of risk apply here, and they are different. Market risk
comes first: a bot that works perfectly can still lose money, because the
strategy itself can be wrong — and automation executes losses at the same
speed as gains, with no pause for judgment while it runs unattended. On a
perpetuals exchange that includes leverage and liquidation: an unattended
position with too much leverage can be closed by the exchange while you
sleep. The two numbers that make this manageable are both a read away —
clearinghouseState returns each position’s liquidation price
(liquidationPx) alongside its signed size, and leverage is set per asset
with the updateLeverage action before you open a position, so set it
deliberately rather than inheriting the default. Operational risk — bugs, leaked keys, outages — is what the
checklist below addresses. Passing the checklist protects you from the
second kind only.
Run down this list before your first live order:
- The bot signs with an API wallet key, never the master key
- The master key is not on the machine the bot runs on
- Both keys live in environment variables / untracked config — not in the code, not in a repository
- No key is ever pasted into a third-party website, bot platform or Telegram bot you have not deliberately chosen to trust with your account
scheduleCancelis armed, the bot logs every action, and you can stop it and cancel all orders in seconds- The account holds only what the bot is allowed to lose — withdrawals can’t be automated away by the bot, but losses can still consume the balance
- Leverage is set deliberately and low; you know each position’s liquidation price
- You have decided in advance how much loss makes you stop the bot
Two Hyperliquid-specific habits round this out. Everything your bot does is public: anyone who learns your address can watch your positions, orders and fills in real time, so don’t publish the address you trade from. And the official onboarding docs state it plainly: “anyone with access to your private key or seed phrase can access your funds. Do not share these with anyone.” No bot is profitable by itself. Verify signing offline, rehearse on testnet, keep the first live orders near the $10 minimum, and increase size only after the bot has run correctly over time.
Conclusion and next steps
This guide covered the full setup path: the two automation routes on Hyperliquid and the native primitives that replace bot products, the API wallet that stands in for an API key, the offline-then-testnet verification ladder, a first order that clears the rounding rules and the $10 floor, and the loop mechanics — reconnects, safe retries, the dead man’s switch — that keep it running unattended. This is the infrastructure layer of automated trading — the prerequisite for everything a bot does.
Next steps: run the reads and the offline signing check today; they cost nothing. When you go live, keep the first order small — sized off the live mid and comfortably above the $10 minimum rather than at it — and let the checklist above clear the operational risks; the market risk is yours to size for. If you don’t have a funded Hyperliquid account yet, our Hyperliquid review covers onboarding, fees and features in detail. For working code covering every common API operation beyond this first order — market orders, stops, transfers, withdrawals, WebSocket streams — see our Hyperliquid API guide.
All API facts verified against official Hyperliquid documentation on
2026-08-18, with live checks against the public API and signature
verification against the official SDK’s test vectors. Limits, fees and
rounding parameters change — always confirm current values via the meta
request and the official docs.
Frequently asked questions
Does Hyperliquid have a built-in trading bot?
No. There is no grid bot, DCA bot or copy-trading product on the platform. The native automation features are vaults (pooled capital that follows one trader or strategy), TWAP orders (automatic order slicing) and a scheduled cancel-all. Anything beyond that is either a third-party product or a bot you build yourself — this guide covers building your own.
Does Hyperliquid have API keys?
No. There is no API key, secret or passphrase. Identity is an Ethereum address and every action is authorized by a wallet signature. The closest analogue is an API wallet (agent wallet): a separate keypair your account approves to sign trading actions — it can place and cancel orders but can never withdraw or transfer funds.
Are trading bots allowed on Hyperliquid?
API trading is a first-class use case: Hyperliquid publishes its own Python SDK, documents a recommended architecture for automated strategies, provides API wallets specifically for bots, and ships an API-only dead man's switch. The docs also state there is no special market-maker program — a bot uses the same API on the same terms as everyone else. Regional eligibility under the Terms of Use still applies.
Can I test a Hyperliquid bot without real money?
Partly. Every market-data and account read works with no funds and no account, and your signing code can be verified offline against the official SDK's published test vectors. Placing practice orders needs the testnet, whose faucet of 1,000 mock USDC only unlocks for addresses that have already deposited on mainnet.
Are trading bots profitable?
A bot executes a strategy; it does not supply one. Whether it makes money depends entirely on the strategy and how it is operated. Be cautious of any product that claims guaranteed profits.
Can US residents use the Hyperliquid API?
Hyperliquid's Terms of Use bar persons in the United States and Ontario, Canada from using the official interface, and the project states it holds no license in any jurisdiction. Read the Terms at app.hyperliquid.xyz/terms and check your own position before trading.