Skip to content
DonateБГ

Keys and addresses

Checksum

A Bitcoin checksum is the first 4 bytes of a double SHA-256 hash, added to addresses and keys so that typing mistakes get caught. Learn how it works.

By Dimitar Zurnov · Updated 4 Nov 2026
Adapted from Learn Me a Bitcoin by Greg Walker.

A Bitcoin checksum is 4 bytes of extra data, added to a string so that a wallet can catch typing mistakes. It is the first 4 bytes of HASH256, which is SHA-256 applied twice to the data. Addresses, WIF private keys and extended keys all carry one. If the checksum does not match, the wallet can refuse the string before you send coins to the wrong place.

What does a checksum do?

A checksum lets you check that data is the same as it was when it was written. You compute a short fingerprint of the data and attach it. Later, you compute the fingerprint again. If one character changed, the two fingerprints almost certainly differ.

A checksum detects errors but does not fix them. It tells you that something is wrong, not where the mistake is.

How is a Bitcoin checksum made?

A checksum takes three steps.

  1. Hash the data with SHA-256.
  2. Hash that result with SHA-256 again. Together, the two steps are HASH256.
  3. Keep the first 4 bytes of the result, which is 8 hex digits.

Here is an example with 20 bytes of aa, written as 40 hex digits:

data          = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
hash256(data) = 05c4de7c1069e9de703efd172e58c1919f48ae03910277a49c9afd7ded58bbeb
checksum      = 05c4de7c
A checksum is made by hashing the payload twice with SHA-256, keeping the first 4 bytes, and appending them to the payload. Payload: 21 bytes 001fe032088d648e925f15a24a0cf6a1 e80f01bf91 SHA-256, then SHA-256 hash256 of the payload: 32 bytes 94686373829f8747c77aa9bf0ff58d48 b4d8533e29ae28db390784c770083d09 keep the first 4 bytes Checksum: 4 bytes 94686373 appended to the 21-byte payload Base58 encode Address (P2PKH) 13uYXKWq8VoZgQApSxTXHPtYDs1m1xGi4z
The payload here is from the example key's P2PKH address, and the checksum is computed the same way.

For the example key, the payload is a version byte, 00, followed by its 20-byte public key hash. That makes 21 bytes. Its checksum is 94686373. The full string is the payload with the checksum appended, 25 bytes in all. Base58 encoding of those 25 bytes gives the address 13uYXKWq8VoZgQApSxTXHPtYDs1m1xGi4z.

How do you verify a checksum?

To verify a checksum, split off the last 4 bytes, hash the rest again, and compare. If the two match, the data is intact. The script below creates the checksum for the example payload and then checks it.

import hashlib

def hash256(data: bytes) -> bytes:
    """Double SHA-256."""
    return hashlib.sha256(hashlib.sha256(data).digest()).digest()

payload = bytes.fromhex("001fe032088d648e925f15a24a0cf6a1e80f01bf91")
checksum = hash256(payload)[:4]
print(checksum.hex())                    # 94686373

def checksum_ok(data_with_checksum: bytes) -> bool:
    data, stored = data_with_checksum[:-4], data_with_checksum[-4:]
    return hash256(data)[:4] == stored

print(checksum_ok(payload + checksum))   # True

Now take a single typo. Change the last character of the address from z to y. The decoded checksum changes from 94686373 to 94686372. The wallet recalculates the checksum from the payload and gets 94686373, which does not match. The wallet rejects the address.

One mistyped character changes the stored checksum, so it no longer matches the recalculated one. Typed correctly: accepted 13uYXK…1xGi4z in the address recalculated 94686373 94686373 = One character typed wrong: rejected 13uYXK…1xGi4y in the address recalculated 94686372 94686373
The payload is unchanged here, so only the stored checksum differs. A typo in the body would change the recalculated value instead.

Where do Bitcoin checksums appear?

  • Addresses. Every legacy address, such as P2PKH and P2SH, uses Base58Check: a payload, its checksum, then Base58 encoding.
  • WIF private keys. A WIF key carries a checksum too, so an import can catch a mistyped key.
  • Extended keys. The xprv and xpub strings for HD wallets each have their own checksum.
  • Network messages. Each message header between nodes holds a 4-byte checksum of its payload. Corruption or tampering shows up as a mismatch.

Bech32 addresses also contain a checksum. It is a stronger design, a BCH code that guarantees detection of any error in up to 4 characters. It is not the simple checksum described on this page.

How reliable is a 4-byte checksum?

A 4-byte checksum has 2^32 possible values, which is about 4.3 billion. A random error produces a matching checksum about once in 4.3 billion tries. That is very unlikely, but it is not impossible. So a checksum is a safety net, not a guarantee.

A full 32-byte hash would be stronger, but it would make addresses far longer. Four bytes is a compromise between safety and length.

Summary

A checksum catches typing mistakes. Addresses, WIF keys and extended keys all carry one. A wallet that verifies it can stop you before a payment goes to the wrong place. Still, check every address yourself before you pay. As a developer, always verify the checksum when you accept a string, because the check is only a few lines of code. The next page, Base58, explains the alphabet these strings are written in.

Sources: the Base58Check encoding page on the Bitcoin Wiki describes the construction, and Bitcoin Core's base58.cpp implements the decoding and checksum check.

In this section: Keys and addresses

All of Bitcoin from zero

Something look wrong? Tell us