Skip to content

Standard Scripts & Address Types (P2PK → P2TR)

People say “send Bitcoin to this address,” but Bitcoin has no concept of an address at the protocol level — only outputs with locking scripts. An address is a user-facing shorthand: a compact, error-checked encoding that tells a sender’s wallet which kind of lock to build and what to put in it. This page traces the standard lock shapes from the original P2PK to modern Taproot, and shows what each address string actually commits to.

An address is a commitment to a locking script

Section titled “An address is a commitment to a locking script”

When you hand someone an address, you are really saying: “build an output whose scriptPubKey is of type X, committing to my key/script Y.” The wallet decodes the address, recognizes the type from its prefix and encoding, and constructs the matching lock. The address never travels onto the chain — only the scriptPubKey it described does.

address (you give this out)
│ decode + error-check
"type + committed key/script hash"
│ wallet builds
scriptPubKey (this is what's stored on-chain)

Two encodings dominate. Base58Check (legacy, leading 1 or 3) and Bech32 / Bech32m (SegWit and Taproot, bc1...). The encoding details — checksums, character sets, why typos are caught — live in addresses & encoding.

Each new type was introduced to fix a shortcoming of the last: smaller, safer, more private, or more flexible.

The original. The lock is simply <pubKey> OP_CHECKSIG — “sign for this exact public key.” It has no short address form (the raw key is large) and exposes the public key on-chain immediately. Used in the earliest blocks; essentially obsolete today.

The classic 1... address. The lock commits to the hash of the public key: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG. Smaller than P2PK and the raw key stays hidden until spending. This is the script we stepped through.

The 3... address. Instead of committing to a key, the lock commits to the hash of an entire redeem script: OP_HASH160 <scriptHash> OP_EQUAL. The spender later reveals the full script and satisfies it. This is what made complex locks (multisig, escrow) usable as ordinary-looking addresses — the sender doesn’t need to know or pay for the complicated script; the recipient reveals it only when spending.

P2WPKH — Pay to Witness-Public-Key-Hash (SegWit v0)

Section titled “P2WPKH — Pay to Witness-Public-Key-Hash (SegWit v0)”

The bc1q... address. Functionally P2PKH, but the unlocking data (signature + key) moves into the witness rather than scriptSig. This fixed transaction malleability and made the signature cheaper, because witness bytes are discounted when computing transaction weight. (Its sibling P2WSH is the SegWit version of P2SH for arbitrary scripts.)

The bc1p... address. Taproot commits to either a single (Schnorr) public key or a hidden tree of alternative spending scripts — and lets the common “just one key” case look identical to any other Taproot spend on-chain, revealing the extra scripts only if they’re used. The result is better privacy and cheaper, more flexible contracts. The cryptography (Schnorr signatures, key aggregation) is covered in Taproot, Schnorr & MuSig.

TypeAddress prefixEncodingCommits toIntroduced for
P2PK(no address)a raw public keythe original coinbase payouts
P2PKH1...Base58Checkhash of a public keysmaller addresses, hide key until spend
P2SH3...Base58Checkhash of a redeem scriptarbitrary locks as simple addresses
P2WPKHbc1q...Bech32hash of a public key (in witness)malleability fix, cheaper signatures
P2WSHbc1q... (longer)Bech32hash of a witness scriptSegWit version of P2SH
P2TRbc1p...Bech32ma Schnorr key or script treeprivacy, flexibility, cheaper contracts

Under the hood — what the bytes inside an address actually are

Section titled “Under the hood — what the bytes inside an address actually are”

An address string is a thin wrapper around a payload plus a checksum. The two encoding families lay those bytes out differently:

Base58Check (legacy — "1..." and "3...")
[version byte] + [20-byte hash] + [4-byte checksum] then Base58
version 0x00 → P2PKH (leading "1")
version 0x05 → P2SH (leading "3")
checksum = first 4 bytes of double-SHA-256 of (version + hash)
Bech32 / Bech32m (SegWit & Taproot — "bc1...")
HRP "bc" + "1" + [witness version] + [program] + [6-char checksum]
witness version 0, 20-byte program → P2WPKH (Bech32, "bc1q...")
witness version 0, 32-byte program → P2WSH (Bech32, "bc1q...")
witness version 1, 32-byte program → P2TR (Bech32m, "bc1p...")

Two things fall out of this. First, the human-visible prefix isn’t decorative — it’s a direct readout of the version byte (or the witness version), which is why 1, 3, bc1q and bc1p map cleanly onto distinct script types. Second, Taproot uses Bech32m, a tweaked checksum, because the original Bech32 had a subtle weakness when an address’s length changed; Bech32m closes it, so a mistyped or mis-padded address still fails the check before any coins move.

How do address types help untrusting strangers agree on one ledger? An address compresses “here is exactly the lock to put on my coins, with a checksum so you can’t get it wrong” into a string a stranger can paste. The sender doesn’t need to trust the recipient about how the funds will be guarded — the address itself, once decoded, fully and verifiably specifies the on-chain scriptPubKey that every node will independently enforce. And because each new type is a backward-compatible soft fork, the network can adopt better locks over time while every node — old or new — still agrees on one history. The address is the handshake; the script is the contract; consensus is the enforcement.

Step back from the prefixes and ask the five questions an architect asks of any naming scheme:

  • Why does it exist? To give a sender a compact, error-checked string that fully specifies which kind of locking script to build and what key/script hash to commit to — without the recipient ever publishing the raw script.
  • What problem does it solve? Safely communicating a spending condition between strangers: the Bech32/Bech32m checksum rejects a mistyped character before funds move, and the prefix (1, 3, bc1q, bc1p) tells the wallet exactly which scriptPubKey shape every node will enforce.
  • What are the trade-offs? A proliferation of incompatible types — six and counting — each a real consensus distinction, not cosmetic; send to a type a chain doesn’t recognize and the coins can be unspendable. Newer encodings (Bech32m for Taproot) exist precisely to patch subtle flaws in the old.
  • When is it the wrong design? When you’d rather expose the script directly (P2PK locks to a raw key with no address at all), or on a chain using the account model, where a single long-lived account identifier replaces the per-output, fresh-lock convention.
  • What breaks if I remove it? Senders would hand-build raw scriptPubKeys with no checksum and no type signal — a single typo would burn coins silently, and the soft-fork upgrade path that lets old and new nodes share one ledger would lose its clean version-byte handshake.
  1. Why does Bitcoin have “no addresses” at the protocol level, and what does an address actually encode?
  2. What does P2SH commit to that P2PKH does not, and why was that useful?
  3. What changed between P2PKH and P2WPKH, and which two problems did the change address?
  4. Match each prefix — 1..., 3..., bc1q..., bc1p... — to its script type.
  5. How do soft forks let Bitcoin introduce new address types without splitting the ledger?
Show answers
  1. At the protocol level there are only outputs with locking scripts (scriptPubKeys) — the address never goes on-chain. An address is a user-facing shorthand: a compact, error-checked encoding that tells the sender’s wallet which type of lock to build and what key/script hash to commit to.
  2. P2PKH commits to the hash of a public key (OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG); P2SH commits to the hash of an entire redeem script (OP_HASH160 <scriptHash> OP_EQUAL). That let complex locks like multisig or escrow appear as ordinary 3... addresses — the sender needn’t know or pay for the script; the recipient reveals it only when spending.
  3. P2WPKH is functionally P2PKH, but the unlocking data (signature + key) moves out of scriptSig into the witness. That fixed transaction malleability and made signatures cheaper, since witness bytes are discounted when computing transaction weight.
  4. 1... → P2PKH (Base58Check); 3... → P2SH (Base58Check); bc1q... → P2WPKH / P2WSH SegWit v0 (Bech32); bc1p... → P2TR Taproot (Bech32m).
  5. Each new type ships as a soft fork designed so old nodes still see the spends as valid (often as “anyone-can-spend” outputs they choose not to enforce) while upgraded nodes enforce the stricter real rules. That backward-compatible path is how the network adopts better locks over time while every node — old or new — still agrees on one history; see soft forks & anyone-can-spend.