Technical › Keys & addresses

Address

95 characters: a network prefix, two public keys and a checksum in a special Base58

In short

A standard Monero address = Base58( prefix ‖ B ‖ A ‖ checksum ). The prefix says which network and address type it is, B and A are the public spend and view keys, and the checksum is the first 4 bytes of Keccak-256 over everything before it.

Layout

12 B — public spend key A — public view key check 1 byte 32 bytes 32 bytes 4 bytes 69 bytes → Monero Base58 → 95 characters

Network prefix

The prefix is written as a varint (one byte for small numbers). Because of how Base58 works, the prefix determines the first character of the address:

NetworkStandardIntegratedSubaddress
mainnet18 → 4…19 → 4…42 → 8…
stagenet24 → 5…25 → 5…36 → 7…
testnet53 → 9…/A…54 → A…63 → B…

Checksum

checksum = Keccak256( prefix ‖ B ‖ A )[0..4]

If the address has a typo, the checksum won't match and the wallet refuses to send.

Monero Base58 is not Bitcoin's

Same alphabet (no 0 O I l), different encoding. Bitcoin turns the whole message into one big number and converts it to base 58. Monero cuts data into 8-byte blocks and encodes each block separately into exactly 11 characters (the last partial block into fewer, per the table).

bytes in block12345678
characters2356791011

69 bytes = 8 full blocks (88 chars) + 5 bytes (7 chars) = 95 characters. The upside: the address length is always the same and encoding is linear-time.

const ENC_BLOCK = [0, 2, 3, 5, 6, 7, 9, 10, 11];
function encodeBlock(block) {
  let n = 0n;
  for (const x of block) n = (n << 8n) | BigInt(x);       // big-endian inside a block
  let s = '';
  while (n > 0n) { s = ALPHABET[Number(n % 58n)] + s; n /= 58n; }
  return s.padStart(ENC_BLOCK[block.length], '1');
}

Integrated address

An integrated address (prefix 19) = a standard address + an 8-byte payment ID (106 characters). The payment ID is encrypted inside the transaction and helps a shop tell which order was paid. Today subaddresses are recommended instead: a new subaddress per order.

What the address doesn't contain

Importantly, the address is never written to the blockchain. The sender uses A and B to build a one-time address, and only that reaches the blockchain.