Punycode
Convert Unicode domains to Punycode (xn--) and back. RFC 3492. Runs entirely in your browser.
Convert between Unicode and Punycode (xn--) domain names. Encode internationalized domains, or decode back to readable text. Read more Show less
What is Punycode?
Punycode is a way of writing Unicode domain names using only ASCII characters. It exists because the Domain Name System (DNS) was designed in the 1980s, before internationalized domain names were a concern, and it only supports letters A-Z, digits 0-9, and hyphens.
When you register or visit a domain with non-ASCII characters - like münchen.de or 例え.jp - the browser converts it to a Punycode-encoded ASCII form (xn--mnchen-3ya.de and xn--r8jz45g.jp) before sending the DNS query. The xn-- prefix marks each label as Punycode-encoded. Decoded back, the browser displays the original Unicode form.
The encoding is defined in RFC 3492. The full set of rules for handling internationalized domain names - including normalization, bidi restrictions, and label length limits - is defined in RFC 5891 (IDNA2008).
How to use
Type or paste into the input. The output updates live. Three modes:
- Auto (default) - if any label starts with
xn--, the input is decoded; otherwise it is encoded. This is what you want most of the time. - Encode - forces Unicode to Punycode. Useful when you have a mixed string and want to encode everything.
- Decode - forces Punycode to Unicode. Useful for inspecting a domain you copied from a browser address bar or DNS record.
Encoding (Unicode to Punycode)
Encoding splits the input into labels (by .), converts each label that contains non-ASCII characters to its xn-- form, and leaves pure-ASCII labels untouched. The conversion uses the bootstring algorithm defined in RFC 3492, with the parameters chosen for IDN use.
Example: münchen.de becomes xn--mnchen-3ya.de. The label münchen contains the non-ASCII ü, so it is encoded; de is pure ASCII and passes through.
Decoding (Punycode to Unicode)
Decoding detects labels beginning with xn--, strips the prefix, and runs the reverse bootstring algorithm to recover the Unicode label. Labels without the xn-- prefix are left unchanged.
Example: xn--mnchen-3ya.de becomes münchen.de. The first label is decoded; the second is passed through.
Why this matters
Every non-English internationalized domain - Japanese, Arabic, Cyrillic, Chinese, Greek, Hebrew, Korean, Thai, Vietnamese, and any other script - uses Punycode under the hood. When you see a domain in a browser and it shows Unicode, the browser has decoded it for you. When you see a certificate's SAN list or a DNS zone file, you are usually looking at the encoded form.
Punycode is also used for homograph defense. Attackers can register a domain in Cyrillic that looks identical to a Latin one (аpple.com with a Cyrillic а), and the browser will show it as xn--80ak6aa92e.com or, if it renders Unicode, as the deceptive form. This tool lets you see both.
FAQ
Is Punycode the same as IDNA?
No. Punycode is a general encoding algorithm; IDNA is the set of rules that uses Punycode to handle internationalized domain names. IDNA adds normalization, case folding, bidi rules, and prohibited character checks on top of Punycode.
Can I use Punycode for anything other than domain names?
Punycode is a general-purpose algorithm - it can encode any Unicode string as ASCII - but in practice it is only used for domain names, because that is the problem it was designed to solve. Using it elsewhere is unusual.
Why does Punycode look so scrambled?
The encoding packs Unicode code points into a very tight ASCII representation using a variable-length integer scheme. It is optimized for length, not for human readability. The readable part is the ASCII characters that were already present; the scrambled part encodes the rest.
What is the maximum length of a Punycode label?
The same as any DNS label: 63 octets. This means a Punycode encoding of a Unicode label can fail if the Unicode form is too long, because the encoded form may exceed 63 characters. The tool will show the encoded output regardless, but registrars enforce the DNS limit.
Does my browser send the Unicode or the Punycode form?
Punycode. Browsers always convert to Punycode before sending DNS queries or TLS SNI. The display in the address bar may show the Unicode form, but the network traffic uses the ASCII form.
Command line equivalent
# Python (idna library)
pip install idna
python3 -c 'import idna; print(idna.encode("münchen.de"))'
python3 -c 'import idna; print(idna.decode("xn--mnchen-3ya.de"))'
# Python (standard library, more limited)
python3 -c 'print("münchen.de".encode("idna"))'
python3 -c 'print(b"xn--mnchen-3ya.de".decode("idna"))'
# Node
node -e 'console.log(new URL("http://münchen.de").hostname)'
# punycode.js (deprecated but functional)
npm i punycode
node -e 'const p = require("punycode/"); console.log(p.toASCII("münchen.de"))'
node -e 'const p = require("punycode/"); console.log(p.toUnicode("xn--mnchen-3ya.de"))'