Skip to content

Learn

Exchange APIs

Binance API error -1022: signature for this request is not valid

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

Binance error -1022 is INVALID_SIGNATURE: “Signature for this request is not valid.” Binance rebuilt the signed payload from what it received, computed the signature itself, and got a different answer from the one you sent.

It is almost never a cryptography bug. HMAC-SHA256 is one library call and it does not get the arithmetic wrong. What goes wrong is the input: the string you signed and the string Binance reconstructed differ by at least one byte. This page is the checklist for finding that byte. The concept — what signing proves and why venues do it differently — is in what is HMAC request signing.

What this error actually means

Binance defines the signature payload precisely. For Spot, verbatim:

“the query string concatenated without separator to the HTTP body. Any non-ASCII character must be percent-encoded before signing.”

HMAC output is sent as a hex string in the signature parameter; the key goes in the X-MBX-APIKEY header. USDⓈ-M futures uses the same header and signs totalParams, which it defines the same way: query string concatenated with the request body.

The phrase that trips people is “without separator”. When a request has parameters in both places, there is no & between the two parts:

query string:     symbol=BTCUSDT&timestamp=1758600000000
request body:     recvWindow=5000
signed payload:   symbol=BTCUSDT&timestamp=1758600000000recvWindow=5000

Most clients put everything in one place, so the body is empty and the payload is just the query string. The trap only springs when the two are split.

It is also worth being clear about what -1022 is not. A timestamp outside the window has its own code, -1021. A key string that is malformed has its own code, -2014. A key that is refused for its IP or permissions is -2015. If you are seeing -1022, the signature comparison itself failed.

The usual cause: what you signed is not what you sent

In practice, the most common version is an HTTP library re-serialising your parameters after you signed them. You build a string, sign it, then hand the library a dictionary — and the library builds its own string. It may order the keys differently, encode spaces or symbols differently, drop empty values, or append parameters of its own. The signature is valid for a string that never went on the wire.

The fix is structural: build the final query string once, sign that exact string, and send that exact string.

import hashlib, hmac, time
from urllib.parse import urlencode

params = {"symbol": "BTCUSDT", "timestamp": int(time.time() * 1000)}
query = urlencode(params)                       # built once
sig = hmac.new(SECRET.encode(), query.encode(), hashlib.sha256).hexdigest()
url = f"{BASE}{PATH}?{query}&signature={sig}"   # sent verbatim

Nothing downstream re-encodes query. If your client insists on taking a dictionary, give it the finished URL instead.

Other causes, in order of likelihood

1. Parameters split between query and body, joined wrongly. Signing the query string alone, signing the body alone, or joining them with &. All three produce a well-formed signature over the wrong payload. Re-read the example above.

2. Non-ASCII characters not percent-encoded before signing. Any free-text field is a candidate — a client order ID with an accented character, for example. Binance’s rule is that the encoding happens before the signature is computed, so the encoded form is what you sign.

3. The wrong secret. A secret from a different key pair — the key was rotated and the secret was not, or the secret belongs to a testnet key while the API key is production. In practice a trailing newline or space picked up when the secret was loaded from a file does the same thing. The key can be perfectly valid while the secret is not the one that matches it.

4. The signing method does not match the key type. Spot supports HMAC, RSA and Ed25519 keys. If the key you registered is Ed25519 and your code computes an HMAC, or the reverse, the signature cannot verify. We did not find which error Binance returns for this mismatch specifically; -1022 is the likely result, but treat that as inference.

5. Case changed on an asymmetric signature. Binance documents HMAC signatures as not case-sensitive and RSA and Ed25519 signatures as case-sensitive. Code that upper- or lower-cases the signature is harmless with HMAC and fatal with the others. The USDⓈ-M General Info page states that “the signature is not case sensitive” and documents HMAC SHA256 and RSA; we did not find Ed25519 mentioned there, so do not assume a Spot Ed25519 signer carries over to futures.

6. The signature parameter inside the payload. Code that appends signature= to the parameter set and then signs the whole set produces a hash of a string that includes the thing being computed. Sign first, append after.

How to confirm which one you have

Log two things for one failing request: the exact pre-hash string you passed to the signing function, and the exact request that went on the wire — full URL and raw body, not the dictionary you started from. Never log the secret.

Then compare. Strip &signature=… from the wire URL; what remains, followed directly by the raw body, must equal your pre-hash string byte for byte.

The failure pattern narrows it further:

PatternMost likely cause
Every signed request fails, including a simple one with only timestampWrong secret, or signing method does not match key type
GET requests pass, POST requests failBody handling — split parameters or a missing concatenation
Most requests pass, some failEncoding of particular values: non-ASCII, spaces, special characters
Failed right after a key rotationOld secret still loaded somewhere
Only RSA or Ed25519 signatures failCase changed, or the signature was altered in transit by encoding

A useful isolating test: send the simplest signed request you have, with nothing but timestamp. If that fails, the problem is the secret or the key type, because there is no payload left to get wrong. If it passes, add parameters back one at a time.

If Binance’s signing documentation includes a worked example for your key type, reproduce it offline with your own signer before debugging against the live API. A signer that cannot reproduce the documented example has a local bug.

For error handling, -1022 belongs in the permanent class: the request will fail identically every time until the code changes, so it should stop the process rather than loop. See error handling patterns for trading APIs.

FAQ

What does Binance error -1022 mean?

INVALID_SIGNATURE — “Signature for this request is not valid.” Binance recomputed the signature over the request it received and it did not match the one you sent. The cause is almost always a difference in the signed input, such as re-serialised parameters, a wrong secret or unencoded characters, rather than the hashing itself.

Can a clock problem cause -1022?

Not directly. Binance reports timestamp problems with their own code, -1021, whose messages say the timestamp was outside recvWindow or ahead of server time. If you see -1022, look at what was signed and how; if you see -1021, look at your clock.

Why does -1022 happen only on POST requests?

Usually because the parameters are split between the query string and the body. Binance signs the query string concatenated with the body, with no separator between them. Signing only one part, or joining the two with &, produces a signature over a payload Binance never reconstructs.

Is the Binance API signature case-sensitive?

It depends on the key type. Binance’s Spot documentation states that HMAC signatures are not case-sensitive while RSA and Ed25519 signatures are. The USDⓈ-M futures General Info page documents HMAC SHA256 and RSA and states that the signature is not case-sensitive.