Punycode vs IDNA: RFC 3492 and UTS #46
RFC 3492 Punycode encodes Unicode scalar values and does not add xn--. UTS #46 ToASCII (Unicode 18.0.0 / Revision 36, nontransitional) runs NFC, lowercase, and label split, then RFC 3492 with xn-- on each non-ASCII label. Encoding bücher writes bcher-kva on /punycode/. Encoding Bücher.de writes xn--bcher-kva.de on /idna/. Punycode of NFC é writes 9ca; IDNA of that same é writes xn--9ca. Neither page is a URL parser or a DNS lookup.
Punycode is not IDNA. RFC 3492 is a Bootstring encoder over one string. UTS #46 ToASCII is domain processing that uses that encoder after NFC, lowercase, and a label split. This page names those outputs on the live Punycode encoder and IDNA ToASCII tool. It is not new URL() and not a DNS client.
One string versus DNS labels
No xn-- versus xn-- plus a split
Encode on /punycode/ is RFC 3492 Punycode (Bootstring: base 36, tmin 1, tmax 26, skew 38, damp 700, initial_bias 72, initial_n 128). Basic ASCII is copied literally; non-ASCII is a delta after the last hyphen. Encode does not prefix xn--. Decode strips one optional leading xn-- (RFC 3490 / 5890). Encode on /idna/ is UTS #46 ToASCII (Unicode 18.0.0 / Revision 36, nontransitional): trim, NFC, JavaScript toLowerCase, split on U+002E / U+3002 / U+FF0E / U+FF61, then RFC 3492 with xn-- on each non-ASCII label.
The same host is not interchangeable
Encoding bücher writes bcher-kva on /punycode/. Decode output of that string or xn--bcher-kva is bücher. A dot is a basic code point: bücher.de is bcher.de-65a, not xn--bcher-kva.de. Encoding Bücher.de writes xn--bcher-kva.de on /idna/. Decode output of that ACE is bücher.de. All-ASCII hello is hello- on /punycode/ and stays hello on /idna/. German ß is encoded: Straße → Strae-oqa on /punycode/; Straße.de → xn--strae-oqa.de on /idna/. Ideographic full stop 中文。中国 is xn--fiq228c.xn--fiqs8s on /idna/.
Only IDNA normalizes first
NFC é and NFD e + U+0301
Encode on /punycode/ never calls String.prototype.normalize. Canonically equivalent e + U+0301 and é (U+00E9) are different code-point sequences. Punycode output of NFC é is 9ca. Punycode output of NFD é is e-xbb. Decode of 9ca writes NFC é. Decode of e-xbb writes NFD e + U+0301. Decode of xn--9ca is the same NFC é. Encode on /idna/ runs NFC first, so output of NFC é and of NFD e + U+0301 is the same xn--9ca. Decode output of xn--9ca or mixed-case XN--9CA is NFC é. Try it withbücher or Bücher.de. UAX #15 output e + U+0301 → é (U+00E9) as normalized.txt lives on /unicode-normalize/.
Not a URL parser or a DNS lookup
Host only versus a full URL
Both pages reject a string that starts with http:// or https://. Host output of https://bücher.de/ is hostname xn--bcher-kva.de on /url-parser/. That page applies UTS #46 to the host of a full URL. Percent-encode a string on /url-encoder/. /idna/ is not the full UTS #46 IDNA Mapping Table, not Nameprep, not CheckBidi / CheckJoiners, and not a DNS lookup. Download on both pages is encoded.txt or decoded.txt as text/plain. Encode and Decode are buttons.
Encode the same host with either algorithm
RFC 3492 Punycode or UTS #46 ToASCII in the browser. Nothing is uploaded.
FAQ
- What is the difference between Punycode and IDNA?
- Punycode encodes Unicode characters. IDNA (Internationalized Domain Names) uses Punycode plus validation rules.
- What is the xn-- prefix?
- ACE (ASCII Compatible Encoding) prefixes Punycode labels with xn-- to indicate they contain international characters.
- Does IDNA normalize Unicode first?
- Yes. UTS #46 IDNA runs NFC normalization before encoding, so different character sequences may produce the same result.
- Does this tool upload my data?
- No. All encoding runs in your browser using JavaScript. Nothing is sent to a server.