Punycode
The form a domain name takes when it has to travel through systems that only speak ASCII.
What is loaded above
xn--80aswg.xn--p1ai decodes to сайт.рф, the Russian word for “site” under Russia’s Cyrillic top-level domain. Both labels were encoded, which is the half people miss: .рф travels as xn--p1ai. Each label between the dots is converted on its own, and one that is already ASCII is left exactly as it is, since prefixing it would change what it resolves to.
Reading the encoded form
münchen.de becomes xn--mnchen-3ya.de.
xn-- is the ACE prefix, reserved by IDNA to mark a label as encoded. mnchen is every ASCII character of the original in order, with the ü simply absent. The hyphen closes that run. 3ya is what remains: base-36 digits carrying which code point to insert and where it belongs. Each run holds a distance from the previous insertion rather than an absolute code point, and a bias adjusts after every one, so a name whose characters cluster in one script encodes short. RFC 3492 (A. Costello, March 2003) calls the general algorithm Bootstring and defines Punycode as Bootstring with the constants set for domain names.
The homograph problem
Unicode holds a great many characters that render as Latin letters. On 14 April 2017 Xudong Zheng published a working demonstration at xn--80ak6aa92e.com, served over HTTPS. Chrome, Firefox and Opera drew it as аррӏе.com, indistinguishable from apple.com in the fonts those browsers used. Every character in the label was Cyrillic, so it was single-script and walked past the mixed-script check the browsers relied on. Chrome answered in version 58 with whole-script confusable detection, showing the raw xn-- form for a label written wholly in one script that reads as Latin. Mozilla’s position at the time was that registry policy should handle it. The rules still differ by browser, and decoding a label yourself gives an answer that does not depend on whose heuristics you are running.
Where Punycode stops
Punycode is one step of IDNA. It normalizes nothing and applies no script or bidi rules. Whether a label should ever have been registered is a question for the registry, and registries answer it differently.
Decoding here folds each label to lower case first, since XN--MNCHEN-3YA names the same host as xn--mnchen-3ya. Single string mode runs Bootstring over the input with no prefix and no splitting on dots, which is what an RFC test vector or a fragment lifted from a log line needs.
Related
Inspect decodes Punycode as part of a wider report and names each lookalike letter it finds. Unicode code points gives the exact identity of every character in a decoded name.