Address
95 characters: a network prefix, two public keys and a checksum in a special Base58
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
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:
| Network | Standard | Integrated | Subaddress |
|---|---|---|---|
| mainnet | 18 → 4… | 19 → 4… | 42 → 8… |
| stagenet | 24 → 5… | 25 → 5… | 36 → 7… |
| testnet | 53 → 9…/A… | 54 → A… | 63 → B… |
Checksum
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 block | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| characters | 2 | 3 | 5 | 6 | 7 | 9 | 10 | 11 |
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.