Base58Check encoder / decoder
Take any 1…, 3…, 5… or K… string apart: version byte, payload body, the 4-byte double-SHA256 checksum and whether it actually verifies. Or go the other way — hand it a hex payload and get the Base58Check string, checksum included.
Enter a value above and press Convert. Not sure what to type? Press “Use example” to load the sample from the placeholder.
What this page does
Base58Check is the encoding behind every 1…, 3…, m…,
2…, 5… and K… string in Bitcoin. It is a base conversion with a
checksum bolted on:
Decode mode takes a finished string and pulls it apart: version byte, payload body, checksum, and whether that checksum actually verifies. Encode mode takes a hex payload and gives you back the Base58Check string, showing the checksum it appended.
1. The Base58 alphabet, and why four characters are missing
Base58 is not a standard. It is base 64 with the awkward characters removed and six more taken out to make hand-copying safe. The Bitcoin alphabet is:
| Index | Characters | Count |
|---|---|---|
| 0 – 8 | 123456789 | 9 digits |
| 9 – 32 | ABCDEFGHJKLMNPQRSTUVWXYZ | 24 upper-case letters |
| 33 – 57 | abcdefghijkmnopqrstuvwxyz | 25 lower-case letters |
| Total | 58 characters | |
Base64 gave up + and / because both break copy-paste and URL handling. The
Bitcoin variant removes four more on purpose:
| Removed | Why |
|---|---|
0 (zero) | Almost identical to O in most typefaces; also confusable with the letter o |
O (capital o) | Same problem from the other side |
I (capital i) | Identical to lower-case l in sans-serif and monospace fonts |
l (lower-case L) | Identical to the digit 1 in many fonts |
Note what stays: lower-case i and o are both in the alphabet. The
rule is not "no look-alike letters", it is "never two characters that can be confused with each other":
1 remains because it is now the only vertical-stroke glyph, and i and
o remain because their look-alikes were the ones deleted. The payoff is that a mistyped
address is far more likely to fail the checksum than to silently become a valid but wrong
address.
2. The leading-1 convention
A base conversion maps a number to digits. It cannot represent a leading zero byte, because leading
zeros carry no numeric information: 0x0021 and 0x21 are the same number. Bitcoin
therefore uses a separate, explicit rule:
1 per leading 0x00 byte, then the base-58 digits of the remaining number| Base58 string | Decoded bytes | Explanation |
|---|---|---|
1 | 00 | One zero byte, no numeric part |
11 | 0000 | Two zero bytes |
12 | 0001 | One zero byte, then the number 1 |
z | 39 | No leading zero; z is index 57 — the largest single-digit value |
This is why mainnet P2PKH addresses start with 1: their payload begins with the version
byte 0x00, which produces a literal 1 that is not part of the
base-converted number. It is also why a 25-byte P2PKH address is always exactly 34 characters: one
1 for the version byte, plus about 33 characters for the remaining 24 bytes.
You can see the rule directly with an extreme case: the payload 0x00 followed by twenty
zero bytes encodes to 1111111111111111111114oLvT2 — twenty-one leading 1
characters, one per zero byte, followed by four ordinary base-58 digits standing for the 4-byte
checksum.
3. The checksum: what it detects, and what it cannot do
Four bytes of double-SHA-256 are appended before encoding, and any decoder recomputes them:
| Error | Detected? | Why |
|---|---|---|
| A single mistyped character | Yes, with probability 1 − 2−32 | The payload changes, so the recomputed checksum changes; only a 1-in-4-billion coincidence passes |
| Two or more mistyped characters | Same probability | No structure is assumed about the error, so the guarantee is probabilistic rather than absolute |
| Transposed characters | Same probability | Unlike some code-based checksums, Base58's order sensitivity comes from the value, not the digits |
An invalid character (0, O, I, l) | Yes, deterministically | Those characters are simply not in the alphabet, so decoding fails outright |
| A truncated string | Usually — or it fails as "too short" | Fewer than 5 decoded bytes cannot even contain a 4-byte checksum |
| A valid string for a different address | No | The checksum protects against typos, never against substitution by a well-formed string |
When the checksum fails, that is all you learn: the string is wrong. The checksum is a hash,
so it is a random-looking 4-byte digest with no algebraic structure — there is no way to work backwards
from "expected cbd7667e, got cbd76695" to "character 27 is the suspect". The
only correct response is to re-copy or re-scan the original string. Guessing is how people lose coins;
this is also why BIP173 notes that a Base58Check-style design "has no error-detection guarantees", only
a small random-collision chance.
For context, bech32 addresses take the opposite design decision: their BCH checksum is guaranteed to detect any error affecting up to four characters, and it is even possible to compute a small set of candidate error positions — see Bech32 / Bech32m.
4. Version bytes: the first payload byte is the type tag
Everything after the checksum is opaque bytes; the meaning comes from the version byte, which is the first byte of the payload. This site supports six of them:
| Version byte | Meaning | Payload size (excl. checksum) | First character(s) |
|---|---|---|---|
0x00 | P2PKH address, mainnet | 21 B (1 + hash160) | 1 |
0x05 | P2SH address, mainnet | 21 B (1 + script hash) | 3 |
0x6F | P2PKH address, testnet | 21 B | m or n |
0xC4 | P2SH address, testnet | 21 B | 2 |
0x80 | WIF private key, mainnet | 33 B (uncompressed) or 34 B (compressed, trailing 0x01) | 5, or K / L |
0xEF | WIF private key, testnet | 33 B or 34 B | 9 or c |
Two consequences worth internalising. First, the first character is not chosen — it is a
consequence of the version byte and the payload length, which is why "addresses starting with
1" and "version byte 0x00" are the same statement. Second, the version byte is
not authenticated by anything: a string is either internally consistent or not, but nothing stops someone
from building a well-formed testnet address and calling it a mainnet one. Wallets that accept both
networks must check the version byte themselves.
5. How many characters? The 58N arithmetic
Each Base58 character carries log2(58) ≈ 5.858 bits, so a byte string needs about 1.3657 characters per byte:
| Bytes (payload + 4-byte checksum) | Bits | log58(2bits) | Characters | Example |
|---|---|---|---|---|
| 25 B | 200 | 34.141 | 34, at most 35 | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT (34) |
| 37 B | 296 | 50.529 | 51 | 5HssbguBnjbaUVZCsH9YuzUG7T4vYQf51iiodi4izdVy6aVNekU (51) |
| 38 B | 304 | 51.895 | 52 | KwVYL77Lcs1ckM39NvGjrtfKhU4KKdR2iB9Wq2FSMN6rbGK5tVqG (52) |
For reference, 5833 = 15599970876632771988160814054146447252125923204784443097088 and
5834 = 904798310844700775313327215140493940623303545877497699631104, while 2192 =
6277101735386680763835789423207666416102355444464034512896 and 2200 =
1606938044258990275541962092341162602522202993782792835301376. Because 2192 <
5834, 24 bytes always fit in 34 characters — that is the 1 plus 33 characters of a
P2PKH address.
Could an address ever be 35 characters? Arithmetically yes: a 25-byte payload needs a 35th character
once its numeric value reaches 5834, which requires a first byte of 0x90 or
higher. Every version byte in the table above is far below that, so real Bitcoin 1… and
3… addresses are always 34 characters. (Measured here: a payload starting with
0x8F gives 34 characters, one starting with 0x90 gives 35.)
6. Base58 vs Base58Check vs Bech32
| Base58Check | Bech32 (v0) | Bech32m (v1+) | |
|---|---|---|---|
| Alphabet | 58 characters, mixed case | 32 characters, lower case only | 32 characters, lower case only |
| Checksum | 4 bytes of double SHA-256 | 6 characters, BCH code, constant 1 | 6 characters, BCH code, constant 0x2bc830a3 |
| Error detection | Probabilistic (1 − 2−32) | Guaranteed for ≤ 4 wrong characters | Guaranteed for ≤ 4 wrong characters |
| Type tag | Version byte inside the payload | Witness version as the first data value | Witness version as the first data value |
| Case handling | Case is significant; both cases legal | Mixed case is forbidden | Mixed case is forbidden |
| Used for | P2PKH, P2SH, WIF | P2WPKH, P2WSH | P2TR and future versions |
7. Worked example: decoding the demo P2PKH address
This table is the real structure of 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT, exactly as decode
mode prints it:
| Step | Value |
|---|---|
| Base58 string | 146ZNjH7XTXnMd1ofe3z7CL2i8WM7N2UqT (34 characters) |
| Decoded bytes (payload ‖ checksum) | 0021f57b6debcfc5b67182dfb4af1641f0a8189012cbd7667e (25 B) |
| Payload | 0021f57b6debcfc5b67182dfb4af1641f0a8189012 (21 B) |
| Version byte | 00 → P2PKH, mainnet |
| Payload body | 21f57b6debcfc5b67182dfb4af1641f0a8189012 (20 B = a hash160) |
| SHA-256 of the payload | 705cbbd9867cfeb7d5b0356c9bafe09bb2a50c40e69c7ee0535cfcbf987db587 |
| Double SHA-256 of the payload | cbd7667ea989f5994e7e12439589085e0eda7572712b71cf66374edff592182f |
| Checksum (last 4 bytes of the string) | cbd7667e — matches the first 4 bytes above, so it verifies |
| Interpretation | P2PKH, mainnet, paying to the hash160 21f57b6d…89012 |
A P2SH address has exactly the same shape with a different version byte:
3DZT76KyKyc5zkzvLugP8umgt4RPY4XPQw decodes to payload
05823333d5fd23a83661e8e47629552c4a5bfc8b6e (version 05, checksum
acbfef44), where the 20-byte body is the hash of a redeemScript, not of a public key.
8. Worked example: decoding the demo WIF
| Step | Value |
|---|---|
| Base58 string | KwVYL77Lcs1ckM39NvGjrtfKhU4KKdR2iB9Wq2FSMN6rbGK5tVqG (52 characters) |
| Decoded bytes | 800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca013a0a0417 (38 B) |
| Payload | 800824c314772b2c2859c889471390a36bf66e53a1ca1642f96f0f2c9307a171ca01 (34 B) |
| Version byte | 80 → WIF, mainnet |
| Payload body | 0824c314…a171ca (32 B private key) followed by 01 |
The trailing 01 | The "compressed public key" flag — its presence is why this address family produces K…/L… WIFs |
| Double SHA-256 checksum | 3a0a0417ffa98881ccdd0c7b283639584e0e909389f6bfbbdbac54547d2b732d → first 4 bytes 3a0a0417, matching the string |
| For contrast | 5HssbguBnjbaUVZCsH9YuzUG7T4vYQf51iiodi4izdVy6aVNekU is 51 characters: same version byte, no trailing flag, therefore an uncompressed key |
Without unstripping the 01 flag you cannot tell which address the key controls, which is
the single most common way people "lose" coins they still own. The flag lives in the encoded string, not
in the key.
9. Worked example: encoding
Encode mode with the payload 00751e76e8199196d454941c45d1b3a323f1433bd6 (the standard
BIP173 test hash160, version byte 00) produces:
| Step | Value |
|---|---|
| Payload | 00751e76e8199196d454941c45d1b3a323f1433bd6 (21 B) |
| Double SHA-256 | 510d1634d943109b69da527ef5948106f22b655fb5193b4e9ef7e4dcd342d245 |
| Appended checksum | 510d1634 |
| Bytes that get converted | 00751e76e8199196d454941c45d1b3a323f1433bd6510d1634 (25 B) |
| Base58Check result | 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH (34 characters) |
Round-tripping that result through decode mode returns the original 21-byte payload and a passing checksum, which is the whole point of the encoding: a string that carries its own proof of integrity.
10. Security notes and common mistakes
- Never "fix" a failing checksum by hand. The checksum says no; there is nothing to repair and no way to find the bad character.
- A passing checksum is not an endorsement. An attacker who can replace your address with their own well-formed address passes every checksum in the world. Verify address provenance out of band.
- Case matters. Base58 contains both cases, so
146znjh7…is a different (and almost certainly checksum-failing) string from146ZNjH7…. Bech32 forbids mixed case altogether; Base58 simply treats it as different data. - Version byte ≠ network authentication. Nothing in the string says "mainnet"; the byte only makes the string self-consistent.
- Expecting an address-shaped payload from a WIF. A 34-byte payload is a key plus a flag. Feeding it to an address decoder produces nonsense, not a wallet.
This page decodes any Base58Check string you paste, including private keys. Anyone who has ever seen that string owns the coins. If a "found" or "leaked" WIF is real, its balance is gone the moment you look at it.
11. Where this fits in the chain
- Before: hash160 → P2PKH / P2SH / P2WPKH produces the 20-byte body that goes inside the payload; private key → P2PKH address and private key → compressed WIF produce finished strings.
- After: Bech32 / Bech32m decoder handles the other address encoding, and WIF → private key HEX goes one step further on a WIF than decode mode does.
12. Quick reference
| Item | Value |
|---|---|
| Alphabet | 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz |
| Characters excluded | 0, O, I, l |
| Bits per character | log2(58) ≈ 5.858 |
| Checksum | First 4 bytes of SHA256(SHA256(payload)) |
| Checksum space | 232 = 4 294 967 296 values |
| Leading zero bytes | One literal 1 per 0x00 byte |
| P2PKH / P2SH address length | Always 34 characters |
| WIF length | 51 characters (uncompressed) or 52 (compressed) |
| Can it correct errors? | No — detection only |