RFC 3492: Punycode — A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)

2026-07-06

RFC: RFC 3492

Published: March 2003

Authors: Adam M. Costello

DNS labels have been trapped in an ASCII cage since 1985. RFC 1035 defined the "preferred name syntax" as letters, digits, and hyphens — the so-called LDH rule — and by the late 1990s every resolver, registrar, and firewall on Earth assumed it. Then the world noticed that most humans don't type English. How do you register bücher.de or 例え.jp without breaking every piece of DNS software ever written?

The answer was IDNA: keep the wire format ASCII, and encode Unicode labels into a reversible ASCII form prefixed with xn--. The interesting part is how that encoding works. Adam Costello's Punycode is one of the more elegant compression schemes ever standardized — and almost nobody who uses it daily can explain it.

The problem it actually solves. A general Unicode-to-ASCII encoder is easy: hex-encode every codepoint. But DNS labels are limited to 63 octets, and most internationalized labels are mostly one script plus a few ASCII characters (think café). A naive encoding would blow past the length limit and waste bytes on the ASCII parts that were already fine. Punycode's design goals were: completeness (any Unicode string), uniqueness (one canonical output), reversibility, efficiency for realistic labels, simplicity, and readability for the ASCII portion.

How it works. Punycode is an instantiation of a more general algorithm called Bootstring, also defined in this RFC. The trick has two parts:

The bias adaptation is the clever bit: after each codepoint is emitted, the encoder shifts its expectation of digit magnitudes so that runs of similar codepoints (common in real scripts) encode in fewer digits. So bücher becomes bcher-kva, then IDNA prepends the ACE prefix to yield xn--bcher-kva. Everything before the last hyphen is the ASCII skeleton; everything after is the delta needed to reconstruct the Unicode.

Why it matters today. Every browser, every TLS library, every email client silently runs Punycode on hostnames. It is the reason emoji domains (xn--i-7iq.ws = 💩.ws) work, why xn-- appears in your certificate viewer, and why the IDN homograph attack exists — Cyrillic а encodes differently from Latin a, but they render identically, which is why Chrome's URL bar sometimes shows xn-- instead of the pretty form when the label mixes suspicious scripts.

The history. Costello wrote the reference implementation in about 200 lines of C, and the RFC includes it inline — one of the few RFCs where you can copy-paste working code out of the document. Bootstring was designed to be patent-unencumbered at a time when the IETF was skittish about IP claims around alternative IDN proposals like RACE and DUDE. It won largely on that combination of technical elegance and clean provenance, and was locked in as the encoding underlying IDNA2003 and its successor IDNA2008 (RFC 5891).

Why it matters: Punycode is the reason DNS could go global without a flag day — a compact, deterministic ASCII encoding of Unicode that lets every legacy resolver keep working while humans type in their own scripts.

All newsletters