Address Encoding
How Bitcoin addresses are encoded using Base58Check, Bech32, and Bech32m to prevent errors and identify network types.
Key Takeaways
- Address encoding determines how raw public key data is represented as a human-readable string. Bitcoin uses three encoding schemes: Bech32, Bech32m, and the legacy Base58Check format.
- Each scheme includes a checksum to catch transcription errors before funds are sent to an invalid address. Newer encodings like Bech32 and Bech32m can detect up to four errors and even suggest corrections for up to two.
- The encoding format also signals which address type and network a payment targets: addresses starting with "1" or "3" use Base58Check, while those starting with "bc1q" or "bc1p" use the Bech32 family.
What Is Address Encoding?
Address encoding is the process of converting raw cryptographic data (such as a public key hash) into a string of characters that humans can read, copy, and share. Without encoding, a Bitcoin address would be a raw sequence of bytes with no way to verify whether it was transcribed correctly.
A good encoding scheme solves several problems at once: it makes addresses shorter and easier to communicate, it includes a checksum so typos are caught before funds are lost, and it embeds metadata like the network type (mainnet vs. testnet) and the type of output script the address represents. Bitcoin has evolved through three encoding formats over its history, each improving on the error-detection and usability of the last.
How It Works
Base58Check (Legacy Addresses)
Base58Check was the original encoding scheme, introduced by Satoshi Nakamoto in the first Bitcoin release. It uses a 58-character alphabet: all uppercase and lowercase letters plus digits, minus four characters that are easily confused in certain fonts: 0 (zero), O (uppercase O), I (uppercase I), and l (lowercase L). This choice also avoids the + and / symbols used in Base64, keeping addresses purely alphanumeric so they can be double-clicked to select and won't break across lines in email.
The encoding process works as follows:
- Prepend a version byte to the raw payload (for example, 0x00 for a mainnet P2PKH address, or 0x05 for a P2SH address)
- Compute
SHA-256(SHA-256(version + payload))and take the first 4 bytes as a checksum - Append the 4-byte checksum to the versioned payload
- Encode the result as a Base58 string
# Base58Check encoding structure
[version: 1 byte] [payload: 20 bytes] [checksum: 4 bytes]
# Version bytes determine the leading character:
0x00 → "1..." (mainnet P2PKH)
0x05 → "3..." (mainnet P2SH)
0x6f → "m/n..." (testnet P2PKH)
0xc4 → "2..." (testnet P2SH)The 4-byte checksum provides roughly a 1 in 4.3 billion chance that a random typo produces a valid-looking address. While this catches most transcription errors, it cannot tell you where the error is or suggest a correction.
Bech32 (SegWit v0 Addresses)
Bech32 was proposed in 2017 by Pieter Wuille and Greg Maxwell in BIP 173. It was designed specifically for SegWit version 0 addresses (P2WPKH and P2WSH). The name combines "BCH" (Bose-Chaudhuri-Hocquenghem, the error-correcting code family used for the checksum) with "32" (the character set size).
A Bech32 address has three parts:
- A human-readable part (HRP):
bcfor mainnet,tbfor testnet - A separator: always the digit
1 - A data section: the witness version (one character), the witness program (base32-encoded), and a 6-character BCH checksum
# Bech32 address structure
[HRP: "bc"] [separator: "1"] [witness version] [witness program] [checksum: 6 chars]
# Example P2WPKH address (witness version 0, 20-byte program):
bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
# Character set (32 chars):
qpzry9x8gf2tvdw0s3jn54khce6mua7lThe BCH checksum is a significant upgrade over Base58Check. It is guaranteed to detect any error affecting up to 4 characters in addresses up to 89 characters long. For 5 or more random errors, there is less than a 1 in 1 billion chance of the error going undetected. Crucially, the checksum can also locate the position of up to 2 erroneous characters, enabling wallet software to suggest corrections.
Bech32 addresses are case-insensitive. Encoders produce lowercase by default, but uppercase is valid (and preferred for QR codes, where all-uppercase text triggers the more compact alphanumeric QR mode). Mixed case is rejected by decoders.
The Bech32 Length-Extension Bug
Researchers discovered that inserting or removing q characters immediately before a final p character does not invalidate a Bech32 checksum. For example, if a valid string ends in ...p, then ...qp, ...qqp, and ...qqqp are also valid.
This did not affect SegWit v0 addresses in practice because P2WPKH always uses a 20-byte witness program and P2WSH always uses a 32-byte program. Any length change would be caught during validation. However, future witness versions (like Taproot) could potentially accept variable-length programs, making the vulnerability a real concern.
Bech32m (SegWit v1+ and Taproot)
Bech32m, specified in BIP 350 by Pieter Wuille in late 2020, fixes the length-extension vulnerability for witness versions 1 through 16. The change is minimal but effective: the BCH checksum algorithm is identical to Bech32, except the final XOR constant is 0x2bc830a3 instead of 1.
# The only difference between Bech32 and Bech32m
Bech32: checksum XOR constant = 0x00000001
Bech32m: checksum XOR constant = 0x2bc830a3
# The constant was selected from 2^30 - 1 candidates
# to maximize error detection for substitutions,
# insertions, deletions, and duplications.The constant 0x2bc830a3 was chosen through exhaustive analysis of over one billion candidates, optimizing for superior error detection across all common mutation types. Bech32m retains all the error-detection properties of Bech32 while eliminating the length-extension weakness.
Taproot (P2TR) addresses use Bech32m encoding and start with bc1p on mainnet (the p represents witness version 1 in the Bech32 character mapping). Taproot was activated on the Bitcoin network on November 14, 2021, at block height 709,632.
The rule for which encoding to use is straightforward:
- Witness version 0: Bech32 (BIP 173)
- Witness versions 1 through 16: Bech32m (BIP 350)
Encoding Scheme Comparison
| Property | Base58Check | Bech32 | Bech32m |
|---|---|---|---|
| Introduced | 2009 | 2017 (BIP 173) | 2020 (BIP 350) |
| Character set size | 58 | 32 | 32 |
| Case sensitive | Yes | No | No |
| Checksum algorithm | Double SHA-256 (4 bytes) | BCH polynomial (6 chars) | BCH polynomial (6 chars) |
| Max errors detected | Detection only, no localization | Detects up to 4, locates up to 2 | Detects up to 4, locates up to 2 |
| Mainnet prefix | "1" (P2PKH), "3" (P2SH) | "bc1q" | "bc1p" |
| Script types | P2PKH, P2SH | P2WPKH, P2WSH | P2TR, future witness versions |
| QR code efficiency | Poor (mixed case forces binary mode) | Good (uppercase enables alphanumeric mode) | Good (uppercase enables alphanumeric mode) |
| Length-extension safe | N/A | No | Yes |
Why It Matters
Address encoding directly affects the safety and usability of every Bitcoin transaction. A single transcription error in an address can mean permanent loss of funds. The evolution from Base58Check to the Bech32 family represents a meaningful improvement in protection: stronger error detection, the ability to pinpoint where mistakes occurred, and case-insensitive formatting that reduces confusion.
For wallet developers and payment platforms, supporting all three encoding schemes is essential. Users may receive addresses in any format, and a wallet that rejects valid Bech32m addresses forces users through unnecessary workarounds. Layer 2 protocols like Spark benefit from the efficiency gains of native SegWit and Taproot addresses, since these encodings correspond to smaller on-chain footprints and lower fee rates.
For a comprehensive overview of how these encodings map to specific script types and their trade-offs, see the Bitcoin address types research article.
Use Cases
- Wallet software uses encoding-specific validation to reject malformed addresses before broadcasting a transaction, preventing accidental fund loss
- Payment processors parse the address prefix to determine which output script to construct, since the encoding format directly identifies the script type
- QR code generators use uppercase Bech32/Bech32m addresses to trigger alphanumeric QR encoding mode, producing smaller and more scannable codes for point-of-sale payments
- Block explorers and indexers decode the version byte or witness version from the encoding to classify and display transaction types
- Coin selection algorithms consider the output script type (inferred from address encoding) when estimating transaction weight and fees
Risks and Considerations
Backward Compatibility
Older wallets and services that have not been updated may not recognize Bech32 or Bech32m addresses. Users attempting to withdraw to a P2TR address from an exchange that only supports legacy formats will encounter errors. While adoption of native SegWit and Taproot addressing has grown substantially, compatibility remains a practical concern when interacting with older software.
Encoding vs. Security
Address encoding protects against accidental typos, not malicious attacks. Checksums do not prevent address poisoning (where an attacker generates an address with the same first and last few characters) or clipboard hijacking (where malware replaces copied addresses). Users should always verify the full address, not just the prefix and suffix.
Mixed Encoding in Transactions
A single Bitcoin transaction can include inputs and outputs using different encoding schemes. Sending from a Base58Check address to a Bech32m address is valid, but mixing formats within the same HD wallet can complicate UTXO management and increase transaction sizes if change outputs use different script types than inputs.
Potential for Misidentification
Because Bech32 and Bech32m share the same bc1 prefix, the only visual difference is the character after the separator: bc1q for SegWit v0 and bc1p for Taproot. Wallet software must verify the witness version and apply the correct checksum algorithm. Using the wrong algorithm (Bech32 validation for a Bech32m address or vice versa) will cause valid addresses to be rejected.
This glossary entry is for informational purposes only and does not constitute financial or investment advice. Always do your own research before using any protocol or technology.