Punycode and IDNA Converter

Convert internationalized domain names to and from Punycode, and see where one typed name becomes two DNS names. Your browser turns faß.de into xn--fa-hia.de. A client that applies the deviation mapping, such as Python's built-in idna codec, turns the same text into fass.de. Everything runs in this tab, offline.

1. Convert a domain name

Type a bare domain (bücher.de), a full URL (https://user@bücher.de:8443/x), or an A-label (xn--bcher-kva.de). The host is read out by your browser's own URL parser, then shown two ways.

2. Raw Punycode (RFC 3492, no IDNA)

This pane runs the bare codec: no xn-- prefix, no mapping, no validation. It accepts strings that are valid Punycode but could never be a domain label, such as RFC 3492 sample S, -> $1.00 <--. Use the converter above for anything that is meant to be a host name.

3. Your browser

The WHATWG column is whatever this browser's URL parser returns. The IDNA mapping table it uses is the browser's own, and a web page cannot read which Unicode or IDNA version that table is, so this page does not print one.

4. Self test

Runs on load. Codec tests use only this page's own code and must pass in every browser. Rows marked browser run your browser's URL parser; if one of those fails, your browser's IDNA differs from the published values, which is not a codec bug.

GroupTestResult

5. How to use it, with real cases

  1. A link opens a different site in a script than in the browser. Paste the host. If the verdict is SPLIT, a client that applies the deviation mapping (Python's standard library idna codec is one) and your browser are asking DNS for two different names. Send the A-label from the WHATWG column instead of the Unicode text, and both sides agree: Punycode is validated without mapping in both modes.
  2. Registering or configuring an IDN. Check the per-label table for the octet count. The URL parser does not enforce DNS length, so a name your browser happily produces can still be over the 63-octet label limit or the 253-octet name limit.
  3. An xn-- label in a log, a certificate or an email header. Paste it. The page decodes it with its own RFC 3492 decoder and checks that it is a real A-label: it must decode, must contain at least one non-ASCII code point, and must survive a round trip through your browser's parser unchanged. xn--8i7caa decodes to three fullwidth letters that the parser maps to www, so it fails.
  4. Hidden characters. The converter echoes your input on a "Your input" line with zero width joiners, non-joiners, soft hyphens and other invisible code points drawn as visible U+200D badges, and lists each one with its position. IDNA mapping deletes some of them (a soft hyphen vanishes from both columns) and refuses others, so the input line is where you see what a pasted name really contains.
  5. Debugging your own Punycode code. Use the raw pane to encode or decode a bare string and compare. The self test shows the 19 RFC 3492 sample strings passing in your browser.

6. What the two columns mean

WHATWG (nontransitional). The WHATWG URL Standard ("domain parser" and "domain parser ToASCII", Last Updated 10 September 2026) runs UTS #46 ToASCII with CheckHyphens=beStrict, CheckBidi=true, CheckJoiners=true, UseSTD3ASCIIRules=beStrict, Transitional_Processing=false, VerifyDnsLength=beStrict and IgnoreInvalidPunycode=false. For URLs beStrict is false, which is why DNS length is not enforced and why this page checks it itself.

Deviation-mapped (UTS #46 Transitional Processing, deprecated), same flags as the WHATWG column. UTS #46 names four deviation characters: U+00DF ß, U+03C2 ς, U+200D ZWJ and U+200C ZWNJ. Section 2 says the only difference between Transitional and Nontransitional Processing "is the handling of the four Deviation characters", and Section 4 adds one more rule: under Transitional Processing, U+1E9E capital sharp s is replaced by "ss". So this column applies exactly five replacements to your whole input before parsing it with the same parser: ß and ẞ to ss, ς to σ, and ZWJ and ZWNJ deleted. Verified against IdnaMappingTable 18.0.0: U+1E9E is the only code point whose mapping produces a deviation character.

This column is not a current browser mode. UTS #46 (Version 18.0.0, Revision 36, 2026-08-31) marks conformance clause C1 "(deprecated)" and says "the industry has fully transitioned to IDNA2008 behavior, and transitional processing has been deprecated." It is also not IDNA2003, which used a different mapping. It is what a client that still applies the deviation mapping computes.

Two DNS-length rules are checked here because the parser does not: each label is 1 to 63 octets (RFC 1035 section 2.3.4, "labels 63 octets or less"; UTS #46 section 4.2), and the whole name is 1 to 253 octets, excluding a trailing root dot (UTS #46 section 4.2).

Sources, as plain text so this page links nowhere it does not need to:

  • UTS #46: https://www.unicode.org/reports/tr46/
  • WHATWG URL Standard, domain parser: https://url.spec.whatwg.org/#concept-domain-to-ascii
  • RFC 3492 (Punycode): https://www.rfc-editor.org/rfc/rfc3492
  • RFC 1035 (DNS): https://www.rfc-editor.org/rfc/rfc1035
  • IdnaMappingTable 18.0.0: https://www.unicode.org/Public/18.0.0/idna/IdnaMappingTable.txt

Punycode is implemented from RFC 3492 sections 5 and 6; no code is reproduced.

This is an independent project. It is not affiliated with or endorsed by the Unicode Consortium, the WHATWG, the IETF, or the Python Software Foundation. Their names identify the specifications and software being compared.