Skip to content

Derivation Paths (BIP44/49/84/86)

You’ve seen that one seed grows into an unlimited tree of keys via HD wallets (BIP32). But a tree with infinite branches is useless if two wallets disagree on which branches hold your money. Derivation paths are the shared map: a standardized route through the tree so that any compatible wallet, given your seed, lands on the exact same addresses. Get the path wrong and your coins look “missing” — they’re not lost, they’re just down a branch your wallet never checks.

A derivation path is a sequence of steps down the key tree, written like a filesystem path:

m / purpose' / coin_type' / account' / change / address_index
│ │ │ │ │ │
root what kind which sub- receive(0) the Nth key
of wallet coin wallet or in this branch
(BTC=0) (0,1,2…) change(1)

The apostrophe ' marks a hardened step (see HD wallets for why hardening protects you if an xpub leaks). A concrete example:

m/84'/0'/0'/0/5 → the 6th (index 5) receive address of the first account
of a native-SegWit Bitcoin wallet

This is the field that trips people up. The purpose number isn’t decorative — by convention it tells the wallet which script type (and therefore which address format) to use. The four you’ll meet:

purpose'BIPScript typeAddress looks like
44'BIP44Legacy P2PKH1...
49'BIP49P2SH-wrapped SegWit3...
84'BIP84Native SegWit (P2WPKH)bc1q...
86'BIP86Taproot (P2TR)bc1p...

So m/44'/0'/0' and m/84'/0'/0' derived from the same seed produce completely different addresses — same money-generating secret, different doors. (For what these script types actually are, see address types and Taproot.)

  • account' lets one seed hold independent sub-wallets — “Savings” (0'), “Spending” (1'), “Business” (2') — that don’t share addresses, all recoverable from the one backup.
  • change is a clever split: branch 0 is for receive addresses you hand out; branch 1 is for change addresses your wallet generates internally when a transaction returns leftover funds (see fees & change). Keeping change on its own branch helps the wallet track which addresses are “yours but internal.”
  • address_index just counts up: 0, 1, 2, … — a fresh address every time, which is exactly the privacy practice you want (never reuse addresses; see privacy & deanonymization).
m/84'/0'/0'/0/0 first receive address (give this out)
m/84'/0'/0'/0/1 second receive address
m/84'/0'/0'/1/0 first change address (wallet uses internally)

Wallets don’t scan infinitely. They look ahead a fixed number of unused addresses — the gap limit, conventionally 20. If you generate address index 0, then jump to index 50 manually, a restoring wallet may stop after 20 empty addresses and never find index 50’s coins. Stay within the gap and your wallet rediscovers everything from the seed alone.

Step back from the slashes and apostrophes and ask the five questions that turn an implementer into an architect:

  • Why does it exist? To give the infinite BIP32 tree a shared mapm / purpose' / coin_type' / account' / change / address_index — so any compatible wallet, handed the same seed, walks to the exact same addresses.
  • What problem does it solve? Wallet portability without trust. The purpose' field (44/49/84/86) pins the script type, coin_type' follows the SLIP-0044 registry (BTC = 0'), and the change branch separates receive (0) from internal change (1) — turning “where are my coins” from guesswork into a deterministic lookup.
  • What are the trade-offs? The standard is a convention, not enforced by consensus, so a wallet defaulting to the wrong purpose' shows a zero balance even though the keys are fine — the classic “my coins disappeared” scare. The gap limit (conventionally 20) adds another footgun: skip ahead to index 50 and a restoring wallet may stop scanning before it ever finds those coins.
  • When is this the wrong design? For a throwaway single-key wallet that never needs portability or sub-accounts, the full five-level path is ceremony you don’t need. And if you stray from registered numbers or invent a private path, you sacrifice the one thing it buys — interoperable recovery in other software.
  • What breaks if I remove it? Two wallets sharing a seed would disagree on which branches hold money, so funds would appear “missing” on restore; without the account'/change structure you lose independent sub-wallets and the change-address hygiene that keeps internal outputs sorted.

How do derivation paths help untrusting strangers agree on one ledger? They’re a public standard that makes self-custody portable and verifiable without trusting your wallet vendor. Because the path-to-address mapping is open and deterministic, you can walk away from any wallet app, hand your seed to a different implementation, and it will independently rederive the very same keys — proving your coins were never hostage to one company’s software. Open standards are what keep “be your own bank” from meaning “trust one bank’s app forever.”

  1. Write out the six components of a BIP44-style path and say what each one selects.
  2. Why do m/44'/0'/0' and m/84'/0'/0' from the same seed produce different addresses?
  3. A user restores their seed and sees a zero balance. What’s the most likely cause, and what’s the fix?
  4. What is the change branch (1) used for, and why keep it separate from the receive branch (0)?
  5. Explain the gap limit and a scenario where ignoring it makes funds appear lost.
Show answers
  1. m / purpose' / coin_type' / account' / change / address_index: m is the root; purpose’ selects the wallet/script type; coin_type’ picks the coin (BTC = 0); account’ the sub-wallet; change chooses receive (0) vs change (1); address_index the Nth key in that branch.
  2. The purpose number selects the script type by convention — 44' is legacy P2PKH, 84' is native SegWit — so m/44'/0'/0' and m/84'/0'/0' derive different address formats (1... vs bc1q...) from the same seed. Same money-generating secret, different doors.
  3. The most likely cause is restoring into a wallet that defaults to a different purpose' (derivation path) than the one that received the funds — so it scans the wrong script type and shows zero. The keys are fine; the fix is to restore with the same wallet type / derivation path, or import the correct account descriptor.
  4. Branch 1 holds change addresses the wallet generates internally when a transaction returns leftover funds (see fees & change). Keeping it separate from the receive branch (0, the addresses you hand out) helps the wallet track which addresses are “yours but internal.”
  5. The gap limit (conventionally 20) is how many consecutive unused addresses a restoring wallet scans ahead before stopping. If you generate index 0 then jump to index 50 manually, the restore may stop after 20 empty addresses and never find index 50’s coins — they look lost though the key is in your seed. Stay within the gap (or bump it and rescan) and everything reappears.