# How to check Binance API status and read error codes

> /sapi/v1/system/status is the first maintenance signal, not a complete outage detector. After it, test the exact product, host, transport, and authenticated operation that failed, then interpret the HTTP status and Binance error code.

- Source: https://papaproxy.net/blog/binance-api-status.php
- Published: 2026-08-02
- Author: Alex Young
- Category: API & data · PapaProxy.net Blog

---

## Key takeaways

- `/sapi/v1/system/status` reports normal or maintenance state, but it does not prove that every Spot, Futures, WebSocket, account, or trading component is healthy.
- Diagnose by layers: distinguish no HTTP response, non-Binance content, Binance JSON errors, and successful but stale data before branching on an error code.
- A `5XX` or `-1007` can leave order execution unknown; use a stored `newClientOrderId`, check User Data Stream, and query order state before retrying.
- Validate symbols through the current product's `exchangeInfo`, including status, permissions, order types, and filters; use the delist schedule as an advance-warning feed.

## What the system status endpoint actually proves

`GET /sapi/v1/system/status` costs IP weight 1, requires no API key in the current global Wallet API reference, and returns two fields:

JSONCopy code

```json
{
  "status": 0,
  "msg": "normal"
}
```

A value of `0` means this endpoint is not reporting general system maintenance. A value of `1` means it is reporting system maintenance. The response does not identify whether the work is planned, which products are affected, or when normal service will return.

That scope matters. A normal result does not prove that Spot trading, Futures, WebSocket Streams, User Data Stream, one REST cluster, or one account is healthy. The endpoint is a useful first signal, but each following check proves only one layer:

| Check | What it proves |
| --- | --- |
| DNS, TCP, and TLS connection | A network path to that hostname can be established |
| `/sapi/v1/system/status` | The endpoint is or is not reporting general maintenance |
| `/api/v3/ping` | A specific Spot REST host answers a public request |
| `/api/v3/time` | The host returns valid Spot API JSON |
| `/api/v3/exchangeInfo` | The public Spot metadata layer responds |
| Signed account request | The key, signature, timestamp, permissions, and account path work |
| User Data Stream | Private account events are reaching the client |
| Order query or test order | The particular trading path is available |
| Futures or WebSocket probe | That separate product or transport is available |

Binance publishes several Spot REST base endpoints: `api.binance.com`, `api-gcp.binance.com`, and `api1` through `api4.binance.com`. The documentation says `api1`–`api4` may offer better performance with lower stability. A failure on one host and success on another therefore points to a host- or route-specific difference; it does not by itself prove a Binance-wide outage.

The following script performs public checks without retries or account access. It records latency, content type, HTTP status, `Retry-After`, and any Binance JSON code instead of assuming that every failure has the standard error body:

PythonCopy code

```python
from __future__ import annotations

import json
import time
from dataclasses import asdict, dataclass
from typing import Any

import requests

SYSTEM_STATUS_URL = "https://api.binance.com/sapi/v1/system/status"
SPOT_HOSTS = [
    "https://api.binance.com",
    "https://api-gcp.binance.com",
    "https://api1.binance.com",
]

@dataclass
class ProbeResult:
    url: str
    latency_ms: float | None = None
    http_status: int | None = None
    content_type: str | None = None
    retry_after: str | None = None
    binance_code: int | None = None
    message: str | None = None
    exception: str | None = None

def probe(url: str, timeout: float = 5.0) -> ProbeResult:
    started = time.monotonic_ns()

    try:
        response = requests.get(
            url,
            timeout=timeout,
            headers={"Accept": "application/json"},
        )
    except requests.RequestException as exc:
        return ProbeResult(
            url=url,
            latency_ms=(time.monotonic_ns() - started) / 1_000_000,
            exception=type(exc).__name__,
            message=str(exc),
        )

    result = ProbeResult(
        url=url,
        latency_ms=(time.monotonic_ns() - started) / 1_000_000,
        http_status=response.status_code,
        content_type=response.headers.get("Content-Type"),
        retry_after=response.headers.get("Retry-After"),
    )

    try:
        payload: Any = response.json()
    except ValueError:
        result.message = response.text[:300].strip() or "<empty body>"
        return result

    if isinstance(payload, dict):
        code = payload.get("code")
        result.binance_code = code if isinstance(code, int) else None
        result.message = str(payload.get("msg", payload))
    else:
        result.message = json.dumps(payload)[:300]

    return result

def get_egress_ip(timeout: float = 3.0) -> str:
    try:
        response = requests.get("https://api.ipify.org", timeout=timeout)
        response.raise_for_status()
        return response.text.strip()
    except requests.RequestException as exc:
        return f"unavailable ({type(exc).__name__})"

def triage() -> None:
    print("egress_ip:", get_egress_ip())

    urls = [SYSTEM_STATUS_URL]
    for host in SPOT_HOSTS:
        urls.extend([
            f"{host}/api/v3/ping",
            f"{host}/api/v3/time",
        ])

    for url in urls:
        print(json.dumps(asdict(probe(url)), ensure_ascii=False))

if __name__ == "__main__":
    triage()
```

Run it from the same host, container, and egress route as the failing application. A successful check from a developer laptop does not prove that a production worker has the same DNS, routing, proxy, or eligibility conditions.

## How to classify the response before reading an error code

A Binance negative code exists only when you receive a parseable Binance JSON error. Incidents can fail earlier or return a different body, so begin with the response layer:

| Result | What it usually means | Next step |
| --- | --- | --- |
| No HTTP response | DNS, connect, TLS, proxy, timeout, or disconnect problem | Record the exception and test the route |
| HTTP response with HTML or malformed JSON | CDN, WAF, invalid route, intermediary, or nonstandard error | Log status, content type, and a short body sample |
| Binance JSON with negative `code` | The API classified the request | Branch on the numeric code |
| HTTP 200 with stale or missing updates | Availability and data freshness are separate | Check event time and sequence continuity |

When a Binance JSON response is present, read the HTTP family first:

| HTTP | Documented meaning | Operational response |
| --- | --- | --- |
| 4XX | The request is malformed or rejected on the sender side | Read the Binance code and request details |
| 403 | A WAF rule fired; this may indicate rate-limit or security enforcement | Inspect rate, payload, parameters, SQL-like strings, and shared-IP traffic |
| 409 | A `cancelReplace` request partially succeeded | Reconcile both the cancellation and the new order |
| 429 | A request or order limit was exceeded | Stop sending, honor `Retry-After`, and coordinate all workers |
| 418 | The IP was auto-banned after continued traffic following 429 responses | Stop traffic on that IP until `Retry-After`; fix the limiter |
| 5XX | Binance returned an internal error | Treat state-changing execution as unknown, not failed |

The final row is critical. A `5XX` from an order operation does not prove that the Matching Engine rejected the order. Blindly repeating the request can create a duplicate position.

## How to reconcile an order after `5XX` or `-1007`

Build reconciliation before the first production order is sent. Supply a unique `newClientOrderId` that your system stores with the intended order. If a timeout or `5XX` leaves the result unknown, do not create a new order immediately.

Use this sequence:

TextCopy code

```text
1. Pause automatic retries for that logical order.
2. Check User Data Stream for an executionReport with the client order ID.
3. If no event appears, query GET /api/v3/order using origClientOrderId.
4. Reconcile status, executedQty, cumulative quote quantity, and fills.
5. Retry only after confirming that the original order does not exist.
```

Binance documents a ten-second processing timeout for Spot API requests. Error `-1007` explicitly says that send and execution status are unknown. The official guidance is to check User Data Stream first and perform an API status query if the event has not appeared.

The client order ID is not a replacement for reconciliation, but it gives the application a stable identifier when no Binance `orderId` reached the HTTP client. Store it before sending, together with the symbol, side, quantity, intended price, request time, and worker identity.

## How to use Binance error codes without overfitting the ranges

The current Spot error reference says codes are universal and messages can vary. In this context, “universal” refers to the current Binance Spot interfaces documented on that page. Do not assume that a separate regional entity or another Binance product publishes an identical list.

The official reference groups `10xx` as general server or network issues and `11xx` as request issues, but production handling is clearer when organized by the action required:

| Category | Examples | Typical action |
| --- | --- | --- |
| Transport or uncertain execution | `-1001`, `-1006`, `-1007`, `5XX` | Reconnect or reconcile state before retrying |
| Rate and connection limits | `-1003`, `-1015`, `-1034`, HTTP 429/418 | Central backoff and limiter correction |
| Authentication and signing | `-1002`, `-1021`, `-1022`, `-2014`, `-2015` | Check clock, signature, key, IP, and permissions |
| Request validation | `-1100`, `-1102`, `-1111`, `-1121`, `-1130` | Correct parameters using current metadata |
| Matching or order state | `-2010`, `-2011`, `-2013`, `-2026`, `-2039` | Inspect order state and matching-engine message |

Log the numeric code as its own field. Also keep the HTTP status, endpoint, host, and message text: the number drives handling, while the message remains useful context when one code has several documented forms.

## What `invalid symbol` means

Code `-1121` means `BAD_SYMBOL`: the supplied symbol is invalid for that endpoint. Do not construct API symbols by stripping `/` or `-` from a display pair and assuming the result exists. Use the exact value returned by `exchangeInfo` on the product and host you call.

For Spot, inspect more than the name:

BashCopy code

```bash
curl -sS \
  "https://api.binance.com/api/v3/exchangeInfo?symbol=BTCUSDT" \
  | jq '.symbols[0] | {
      symbol,
      status,
      orderTypes,
      permissionSets,
      quoteOrderQtyMarketAllowed,
      filters
    }'
```

Check:

- the exact symbol string;
- its current `status`;
- whether the account satisfies the relevant `permissionSets`;
- whether the intended order type is supported;
- `PRICE_FILTER`, `LOT_SIZE`, `MIN_NOTIONAL`, `NOTIONAL`, and other applicable filters;
- whether the code is calling Spot, Futures, Binance.US, or another platform.

A valid symbol name can still be unusable for a particular operation. The current error list also includes `-1220 SYMBOL_DOES_NOT_MATCH_STATUS`, which is separate from an unknown symbol.

For future removals, Binance provides `GET /sapi/v1/spot/delist-schedule`. It requires `X-MBX-APIKEY` and consumes IP weight 100. Poll it on a schedule suitable for the trading universe—for example, once per day—and cache the result instead of calling it inside an order loop:

BashCopy code

```bash
curl -sS \
  "https://api.binance.com/sapi/v1/spot/delist-schedule" \
  -H "X-MBX-APIKEY: $BINANCE_API_KEY" \
  | jq '.[] | {delistTime, symbols}'
```

This endpoint is an advance-warning source. `exchangeInfo` remains the runtime source for the symbols and filters currently exposed by the Spot API.

## Why HTTP 200 is not enough for market-data health

An API can accept connections while a client is no longer processing current market data. For WebSocket-driven systems, monitor freshness separately from connectivity:

- age of the latest event time;
- time since the last message was received;
- expected update cadence for that stream;
- sequence or update-ID continuity where the stream defines it;
- reconnect and resynchronization count;
- age of the local order-book snapshot;
- difference between REST and locally maintained state during recovery.

A connected socket with no recent events should not be reported as healthy merely because the TCP session remains open. Likewise, a successful REST ping does not prove that a WebSocket consumer is current.

## Which incident fields to log

A useful incident record should preserve enough context to reproduce the exact path:

TextCopy code

```text
timestamp
product
host
endpoint
method
HTTP status
Binance code
message
request latency
response content type
Retry-After
X-MBX-USED-WEIGHT-*
X-MBX-ORDER-COUNT-*
clientOrderId
egress IP
exception type
latest market-event age
```

Keep `product` and `host` explicit. A failure on `fapi.binance.com`, `api.binance.com`, and a regional platform should not be merged into one metric called `binance_api_down`.

Useful production counters and gauges include:

TextCopy code

```text
binance_http_errors_total{product,host,status}
binance_api_errors_total{product,host,code}
binance_request_latency_ms{product,host,endpoint}
binance_unknown_execution_total{endpoint}
binance_market_event_age_ms{stream}
binance_stream_reconnect_total{stream}
binance_egress_ip_info{worker,ip}
```

## Where to check official service notices

The general Binance announcements center may contain maintenance notices, but it is not a component-level machine-readable status page. Binance also directs API developers to its official API announcements channel for service notices, API changes, upgrades, and deprecations.

Use notices as context alongside your own component checks. Third-party outage trackers aggregate user reports; they can show that many users are seeing problems, but they do not identify which Binance component failed or whether the issue affects your route.

A proxy does not fix Binance maintenance, stale application state, WAF enforcement, or a broken rate limiter. Its relevant role here is providing a stable egress identity for IP whitelisting and incident attribution. Our [proxies for Binance](/target/binance-proxy-server/) include dedicated IPv4 addresses reserved exclusively for you for the plan term, so a worker can keep the same logged and IP-whitelisted egress after redeployment.
