Bech32
Bech32 addresses in Bitcoin: the bc1 format for SegWit and Taproot, with one letter case, a 32-character alphabet and a stronger checksum.
By Dimitar Zurnov · Updated 4 Nov 2026
Adapted from Learn Me a Bitcoin by Greg Walker.
Bech32 is the text format for SegWit and Taproot addresses, such as P2WPKH, P2WSH and P2TR. On mainnet, every Bech32 address starts with bc1. BIP 173 defined the format for SegWit version 0. BIP 350 defined Bech32m, the same design with a different checksum constant, for version 1 and later.
Why use Bech32 instead of Base58?
Bech32 keeps the job of a Base58 address but makes it easier to use.
- One letter case. A Bech32 address never mixes upper and lower case, so it is easier to type and to read out loud. A wallet should reject a mixed-case address.
- Fewer look-alike characters. The alphabet leaves out 1, b, i and o.
- A stronger checksum. It guarantees detection of any error in up to 4 characters. A Base58Check checksum catches most errors but gives no such guarantee.
- Smaller QR codes. QR codes have an alphanumeric mode for capital letters, digits and a few symbols. A Bech32 address written in capitals fits that mode, so the code needs less data.
- Faster to process. Each character maps straight to a value. There is no big-number division, as in Base58.
What does a Bech32 address look like?
| Type | Example | Length |
|---|---|---|
| P2WPKH | bc1qrlsryzydvj8fyhc45f9qea4paq8sr0u3svqwyd |
42 characters |
| P2WSH | bc1q37qzzxnhnwdsde7yjzq5hc0wktmnqejp3zt0pj9l0pgn9f2gpyls4hahsc |
62 characters |
| P2TR | bc1p4pzgu93t5nlw9mscn0v6s7spfya7qntp0afynva267lr0vp0sxyqqj24dc |
62 characters |
The first example is the P2WPKH address of our example key. The other two are example addresses, and both are valid. The bc1 prefix shows mainnet. The character after it is the witness version: q means version 0, and p means version 1, which is Taproot. P2WPKH, P2WSH and P2TR are the three locking scripts that use these addresses.
What characters does Bech32 use?
The data part of an address uses 32 characters:
qpzry9x8gf2tvdw0s3jn54khce6mua7l
These are the digits 0 to 9 and the lower-case letters, without 1, b, i and o.
The number 1 is missing because it is the separator, and it looks like a lower-case l. The letter b is missing because it looks like 8 in capitals. The letter i can look like l, and o can look like 0. The first part of an address, the human-readable part, is not limited to this set. Bitcoin uses bc for mainnet, tb for testnet and bcrt for regtest.
How is a Bech32 address built?
The steps below turn a SegWit scriptPubKey into an address. The example is the P2WPKH script of our key, which is 0014 followed by its public key hash.
- Choose the human-readable part. Use
bcfor mainnet,tbfor testnet orbcrtfor regtest. - Take the scriptPubKey apart. It has three pieces: a version opcode, a size byte and the witness program. Drop the size byte. The decoder can work out the program length from the address itself.
- Convert the version to a 5-bit value. The version is the number behind the opcode, so
OP_0is 0 andOP_1is 1. Do not use the raw byte as the version. The byte51is the opcodeOP_1, which means version 1. - Regroup the program into 5-bit values. Twenty bytes of 8 bits become 32 values of 5 bits. If the bits do not fill the last group, pad it with zeros.
- Calculate the checksum. It covers the human-readable part, the version and the program, as the next section explains. The result is six 5-bit values.
- Map each value to a character. Use the 32-character set above. The version comes first, then the program, then the checksum.
- Join the parts. Write the human-readable part, a
1, then the data.
For our key, the 32 program values are:
3 31 16 3 4 2 4 13 12 18 7 9 4 23 24 21 20 9 5 0 25 29 21 1 29 0 7 16 3 15 28 17
Those values spell rlsryzydvj8fyhc45f9qea4paq8sr0u3. The checksum is svqwyd. So the address is bc1 + q + the program characters + the checksum.
How is the Bech32 checksum calculated?
The checksum is a BCH code, a type of error-detecting code. You do not need the algebra to use it. You need four things:
- The human-readable part, expanded into 5-bit values. Take the top three bits of each character, add a zero, then take the low five bits of each character.
- The version and the program, as 5-bit values.
- Six zero values, which reserve room for the checksum.
- A 30-bit register that starts at 1. For each 5-bit value, the register shifts left and takes in the value. The five bits that shifted out decide which of five fixed generator constants are XORed in.
When every value has been processed, XOR the register with a constant. For version 0 that constant is 1, as in Bech32. For version 1 and later it is 0x2bc830a3, as in Bech32m. The result is split into six 5-bit values. Those values are the checksum.
The script below builds a complete SegWit address with this method. It needs no library.
CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
BECH32_CONST = 1 # version 0 (BIP 173)
BECH32M_CONST = 0x2bc830a3 # version 1 and later (BIP 350)
def polymod(values):
gen = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
chk = 1
for v in values:
top = chk >> 25
chk = ((chk & 0x1ffffff) << 5) ^ v
for i in range(5):
if (top >> i) & 1:
chk ^= gen[i]
return chk
def convert_bits(data, src, dst):
"""Regroup bits, e.g. 8-bit bytes into 5-bit groups (zero padded at the end)."""
acc, bits, out = 0, 0, []
for v in data:
acc = (acc << src) | v
bits += src
while bits >= dst:
bits -= dst
out.append((acc >> bits) & ((1 << dst) - 1))
if bits:
out.append((acc << (dst - bits)) & ((1 << dst) - 1))
return out
def segwit_address(hrp: str, version: int, program: bytes) -> str:
const = BECH32_CONST if version == 0 else BECH32M_CONST
data = [version] + convert_bits(program, 8, 5)
values = [ord(c) >> 5 for c in hrp] + [0] + [ord(c) & 31 for c in hrp] + data
pm = polymod(values + [0] * 6) ^ const
checksum = [(pm >> 5 * (5 - i)) & 31 for i in range(6)]
return hrp + "1" + "".join(CHARSET[d] for d in data + checksum)
print(segwit_address("bc", 0, bytes.fromhex("1fe032088d648e925f15a24a0cf6a1e80f01bf91")))
# bc1qrlsryzydvj8fyhc45f9qea4paq8sr0u3svqwyd
print(segwit_address("bc", 1, bytes.fromhex("a8448e162ba4fee2ee189bd9a87a01493be04d617f5249b3aad7be37b02f8188")))
# bc1p4pzgu93t5nlw9mscn0v6s7spfya7qntp0afynva267lr0vp0sxyqqj24dc
The second call uses a 32-byte Taproot program and produces a valid Bech32m address. Bitcoin Core's bech32.cpp uses the same algorithm.
How do you decode a Bech32 address?
Decoding reverses the steps, and it checks everything on the way.
- Find the separator. It is the last
1in the string. Everything before it is the human-readable part, and everything after it is the data. Do not split at the first1, and do not assume a fixed length for the prefix. - Check the case. The whole address must be lower case or upper case, never mixed. Convert the address to lower case before you go on. A QR code often stores the capital form, so a scanner may return capitals.
- Map each data character to its value. The first value is the version, and the last six values are the checksum.
- Verify the checksum. Run the calculation above on the human-readable part and the data. The result must equal the constant for the version. If it does not, the address is invalid. The checksum guarantees detection of any error in up to 4 characters. A decoder may point to where an error might be, but it should not correct the address on its own, because a corrected string can be a different valid address (BIP 173).
- Convert the program back to bytes. Regroup the 5-bit values into 8-bit bytes. Any padding must be fewer than 5 bits and all zero.
- Check the program length. A version 0 program must be 20 or 32 bytes. Each address must be 90 characters or fewer in total, as BIP 173 sets.
When all the checks pass, rebuild the scriptPubKey from the version opcode, the length byte and the program.
What is Bech32m, and why was it needed?
Bech32m is the same design with a new constant. The reason is a weakness in the original Bech32 checksum. If the last character of an address is p, inserting or deleting any number of q characters just before it does not break the checksum. BIP 350 changes only the constant, which removes that weakness.
| Witness version | Constant | Encoding | Used for |
|---|---|---|---|
| 0 | 1 |
Bech32 (BIP 173) | P2WPKH and P2WSH |
| 1 and later | 0x2bc830a3 |
Bech32m (BIP 350) | P2TR and future versions |
Each constant gives its own checksum, so an address built with the wrong one fails validation. A Taproot address must use Bech32m. The Taproot example above checks out with the Bech32m constant and fails with the Bech32 one.
Where is Bech32 used?
- P2WPKH (starts with
bc1q) uses a 20-byte public key hash. SegWit went live with block 481,824, and this is the simplest SegWit output. See also SegWit. - P2WSH (starts with
bc1q) uses a 32-byte script hash, for multisig and other scripts. - P2TR (starts with
bc1p) uses a 32-byte tweaked public key. It went live with block 709,632. See also Taproot.
Base58 is still used for legacy P2PKH and P2SH addresses, for WIF keys and for extended keys.
What mistakes should you watch for?
- Mixed case. A valid address never mixes upper and lower case, so a wallet should refuse it.
- Look-alike characters. The letters 1, b, i and o are not in the set. A string with one of them is invalid.
- Trusting the prefix. A string that starts with
bc1is not automatically valid. Check the checksum. - Missing or extra characters. A dropped or doubled character almost always breaks the checksum, so the address will not validate.
- The wrong constant. A Taproot address must use Bech32m. A wallet that mixes the two will reject it.
Summary
Bech32 writes SegWit and Taproot addresses in one letter case, from a 32-character alphabet, with a checksum that is stronger than Base58Check's.
Version 0 uses the original constant from BIP 173, and version 1 and later use Bech32m from BIP 350. The address is the version, the witness program and the checksum, joined to the bc prefix with a 1. You can paste any bc1 address into our explorer, which reads it from our own node. The address page explains what the explorer shows for each one.
In this section: Keys and addresses
Something look wrong? Tell us