Bech32 Encoder/Decoder

SegWit Bitcoin address and Lightning invoice encoding with BCH checksum

Free Bech32 encoder and decoder implementing the BIP-0173 BCH checksum used by SegWit Bitcoin addresses and Lightning invoices. Encode an HRP plus data, verify the 6-character checksum, all in your browser. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What is the human-readable part (HRP)?

The HRP is a short lowercase prefix that names the context of the data, like bc for Bitcoin mainnet, tb for testnet, or lnbc for Lightning invoices. It is mixed into the checksum, so a string with the right data but the wrong HRP still fails validation.

Bech32 is the address format introduced in BIP-0173 for SegWit Bitcoin addresses and reused by Lightning Network invoices. It pairs a short human-readable prefix with the data and a strong checksum so typos are caught before any funds move. This tool encodes a human-readable part plus your data into a Bech32 string and decodes Bech32 back, verifying the checksum as it goes.

How it works

A Bech32 string has three parts: a human-readable part (HRP), the separator 1, and the data section. The data is encoded with a 32-character alphabet that drops the ambiguous characters 1, b, i and o. Before encoding, this tool converts your bytes from 8-bit groups into 5-bit groups so they fit the alphabet, then appends a 6-symbol checksum.

That checksum is a 30-bit BCH code. The encoder expands the HRP, concatenates the data, runs a polymod function over five generator constants, and emits the result so that decoding the full string yields the constant 1. On decode, the same polymod must produce 1 or the string is rejected. This is what makes Bech32 robust: it can locate up to four character errors instead of silently accepting a corrupted address.

Tips and notes

Real Bitcoin addresses prepend a witness version before the program bytes, and Lightning invoices pack a timestamp, tagged fields and a signature into the data section. This tool exposes the raw HRP plus data mechanics so you can learn the format, prototype your own checksummed identifiers, or verify why a given address is being rejected. Keep the HRP lowercase: Bech32 forbids mixing upper and lower case in one string.

Bech32 versus Bech32m

BIP-0173 defined the original Bech32 format used for SegWit version 0 addresses (P2WPKH and P2WSH) — the bc1q... addresses you see most commonly today. In 2021, BIP-0350 introduced Bech32m, a small modification to the checksum generator constant, to fix a length-extension malleability issue that affected SegWit version 1 (Taproot) and later addresses. Taproot addresses therefore start bc1p... and use Bech32m rather than Bech32.

The practical implication: if you are validating a Bitcoin address and it starts with bc1q, apply the BIP-173 polymod constant. If it starts with bc1p (Taproot), apply the BIP-350 constant. Applying the wrong constant will always fail validation even for a perfectly valid address.

This tool implements the original Bech32 scheme from BIP-0173. If you need to validate or encode Taproot addresses specifically, note that only the generator polynomial constant differs.

Using Bech32 for non-Bitcoin identifiers

Nothing in the Bech32 format is Bitcoin-specific beyond the convention of using bc or tb as the HRP. The combination of a human-readable prefix, case-insensitive base-32 alphabet, and strong BCH checksum makes it a useful choice for any application that needs checksummed, copy-safe identifiers — for example:

  • Internal record IDs that will be typed by users (the lack of ambiguous characters reduces transcription errors).
  • API tokens that need to be visually distinguishable by prefix (sk_live_... style) while also being self-verifying.
  • Short codes for QR-code delivery where mixed-case encoding wastes QR capacity (Bech32 is all lowercase or all uppercase, which halves the QR mode needed).

Set a meaningful HRP to namespace your identifiers — for example inv for invoices or user for user handles — and the checksum will catch any single-character transcription error before it reaches your database.