An address is not a thing on the blockchain. It is a human-friendly encoding of an output's locking condition, with a checksum. Decode it and you get a script.
From public key to legacy address (P2PKH)
- SHA-256 the public key, then RIPEMD-160 the result: a 20-byte public key hash.
- Prepend a version byte (0x00 for mainnet).
- Compute a checksum: first 4 bytes of a double SHA-256 of the above.
- Encode in Base58, which drops look-alike characters (0, O, I, l). Result: starts with 1, 26 to 34 characters.
Script hash addresses (P2SH, 3...)
Same recipe with a different version byte and the hash of a script instead of a key. The script (say, a 2-of-3 multisig) is revealed only when spending. Also used to "wrap" SegWit outputs so old wallets could pay them.
Native SegWit (bc1q...)
Bech32 encoding: a human-readable prefix (bc), a separator (1), then the witness version and program in a 32-character alphabet, lowercase only, with a checksum that detects up to four errors. A 20-byte program is P2WPKH (42 characters); a 32-byte program is P2WSH (62 characters).
Taproot (bc1p...)
Bech32m, a tweak of Bech32, encodes witness version 1 and a 32-byte x-only public key. P2TR. The key is "tweaked" with a hidden script tree, so a single-sig wallet and a complex multisig look identical on-chain.
Which to use
Taproot and native SegWit are cheapest in fees and best for privacy. Legacy addresses still work and cost more. Any wallet can pay any type.
Tap a card to flip it.