Skip to content

Learn

Exchange APIs

Bybit API errors 10006 vs 10018: account vs IP rate limits

Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs.

Bybit’s 10006 — “Too many visits. Exceeded the API Rate Limit.” — means one account (UID) sent too many requests to one endpoint within Bybit’s rolling per-second window. 10018 — “Exceeded the IP Rate Limit.” — means the traffic leaving one IP address was too much. The fixes differ: pace the specific endpoint for 10006, using the X-Bapi-Limit* headers; reduce total traffic from the address for 10018.

This page is for anyone running more than one bot, polling several endpoints, or seeing rate-limit errors that do not match their own request counts. It explains Bybit’s two layers, what each code implies about your architecture, and how to handle both in code. It deliberately contains no quota numbers — those change, and they live on Bybit’s rate-limit page.

What these errors actually mean

Bybit documents two independent layers.

The API limit — per UID, per endpoint. Bybit describes it as “based on the rolling time window per second and UID”. Each endpoint has its own budget for your account. Breach it and the response is retCode: 10006. Every response carries three headers that describe this layer:

HeaderContent
X-Bapi-Limit-StatusRequests remaining for this endpoint
X-Bapi-LimitCurrent limit for this endpoint
X-Bapi-Limit-Reset-TimestampReset time if exceeded; otherwise the current timestamp

The IP limit — per address. A per-IP request budget over a short fixed window, applied across api.bybit.com and the regional hosts. The rate-limit page says a breach returns HTTP 403 “access too frequent”, that you should stop all HTTP sessions and wait, and that “the ban will be lifted automatically”. Bybit’s error table also lists retCode 10018, “Exceeded the IP Rate Limit.”

We did not find official text explaining when 10018 is returned versus the HTTP 403. Handle both as the IP layer and do not build logic that depends on getting one rather than the other.

The distinction, side by side

1000610018 / HTTP 403
Counted perAccount (UID) and endpointIP address
WindowRolling, per secondShort fixed window
Visible in advanceYes — X-Bapi-Limit-StatusNo per-response header documented
What it says about youOne endpoint is called too oftenThe machine, as a whole, sends too much
FixPace that endpoint; wait for the reset timestampStop HTTP sessions from that IP, wait, then reduce total traffic
Raised by VIP / Pro tiersOn endpoints the table marks “upgradable”We did not find anything saying so

The practical reading: 10006 is local to one endpoint; the others still work. A strategy that hammers the order-status endpoint can hit 10006 there while its order placement is fine. The IP layer is global to the address, so everything on that machine is affected at once.

The usual cause of each

10006: polling. A loop that checks order status, positions or balances far more often than anything changes. The per-endpoint budget is spent on questions whose answer has not moved. Our suggestion is to move repeated reads of changing state to a WebSocket subscription, which has its own, separate connection limits — see WebSocket vs REST for trading.

10018: several consumers behind one address. This is our reading, not Bybit’s wording, but the arithmetic makes it the usual way in: each account on a machine has its own per-UID budgets, while all of them share one per-IP budget. Three bots on three sub-accounts, each well within its own limits, can together exceed what the address is allowed. Sharing an IP across accounts is the pattern to look for.

Other causes, in order of likelihood

1. A retry storm. An error handler that retries immediately turns a single 10006 into a burst, and a burst across many endpoints into an IP-layer problem.

2. Batch endpoints sized wrong. Batch create, amend and cancel have their own limit, not shared with the single-order endpoint, and consume one unit per order in the batch. If a batch is larger than the remaining budget, the overflow orders fail and the rest succeed. That is a partial success, and code that checks only the top-level retCode will miss it: inspect the result for every order in the batch.

3. Startup bursts. Every process fetching instruments, positions, balances and open orders at once on boot — worse when a crash loop restarts it repeatedly.

4. Not a quota at all. Two codes read like rate limits and are not yours to pace:

CodeMeaningImplication
HTTP 429“System level frequency protection. Please retry when encounter this”Platform-side; back off and retry
429 (UTA retCode)“The trading service is experiencing a high server load…”Server load, not your quota
10429 (WebSocket order entry)“System level frequency protection”WebSocket channel
20003 (WebSocket order entry)“Too frequent requests under the same session”Per-session message rate
10003 (WebSocket order entry)“Too many sessions under the same UID”Session count, not request rate — see Bybit API error 10003

How to confirm which one you have

  • Read the code, then the headers. On 10006, log the endpoint and all three X-Bapi-Limit* headers. A X-Bapi-Limit-Status that fell steadily to zero points at polling; one that jumped from high to zero points at a burst.
  • Count per IP, not per process. For 10018 or 403, sum the request rate of every process on that address. The single process that got the error is rarely the whole story.
  • Check the timing. Errors clustered after restarts are startup bursts; errors after other errors are retry storms.

Handling both in code

remaining = int(resp.headers.get("X-Bapi-Limit-Status", "1"))
body = resp.json()

if body["retCode"] == 10006:
    reset_ms = int(resp.headers["X-Bapi-Limit-Reset-Timestamp"])
    pause_endpoint(path, until_ms=reset_ms)   # this endpoint only
elif body["retCode"] == 10018 or resp.status_code == 403:
    pause_all_http(backoff_with_jitter())     # whole IP; also check the other 403 causes
elif remaining <= LOW_WATERMARK:
    slow_endpoint(path)                        # pace before you hit zero

A 403 also covers GET requests sent with an empty JSON body and requests from restricted regions, so log the body before assuming it is the IP layer.

For orders, a 10006 is a refusal: Bybit answered and did not accept the order. That is different from a timeout, where you do not know what happened and must reconcile before resending — see error handling patterns for trading APIs.

FAQ

What is the difference between Bybit error 10006 and 10018?

10006 means your account exceeded the limit for one specific endpoint, in Bybit’s rolling per-second window per UID. 10018 means the IP address as a whole exceeded its limit. The first is fixed by pacing that endpoint, guided by the X-Bapi-Limit* headers; the second by reducing total traffic from the address.

How do I know how close I am to Bybit’s rate limit?

Every Bybit V5 response carries X-Bapi-Limit-Status (requests remaining for that endpoint), X-Bapi-Limit (the endpoint’s current limit) and X-Bapi-Limit-Reset-Timestamp. These describe the per-UID, per-endpoint layer. We did not find equivalent per-response headers documented for the IP layer.

Why do I get 10018 when each bot is within its limits?

Because the IP layer counts every request from the address, regardless of account. Several bots on different accounts can each stay within their own per-UID budgets and still exceed the shared per-IP budget together. Give heavy consumers their own egress address, or reduce polling across all of them.

Do Bybit batch orders count as one request?

No. Bybit’s batch create, amend and cancel endpoints have their own limit and consume one unit per order in the batch. If the batch is larger than the remaining budget, the overflow orders fail while the rest succeed, so check the result of each order rather than only the top-level response.