Non-punycode emojis in domains
Emojis that when encoded in punycode for domains become text
- By Jeremy Nguyen
tl;dr: When they were first introduced, Unicode added existing non-pictograph emojis for compatibility with Japanese carriers and unified them with pre-existing text-style counterparts, including
"Ⓜ️","ℹ️","™️"("Ⓜ","ℹ","™"). Since this changed the appearance of existing documents, they later added a presentation selector code point to differentiate between text and emoji style. Hence, after being mapped to their normalized forms,"Ⓜ","ℹ","™"become"m","i","tm", respectively, and the emoji presentation selector is silently ignored.
While browsing the Wikipedia article for Emoji domain, I stumbled upon the following line that struck me as interesting:
With the exception of three emoji (TM-™️, Information-ℹ️ and M-Ⓜ️), for an emoji to work reliably in a domain name, it must be converted into so-called "Punycode".
The lack of a citation and the seemingly arbitrary emoji choices given made me doubt its reliability. Still, I thought it would be really interesting if it were true that some emojis were for some reason exempt from being encoded to punycode. That bit of trivia was added in December 2025 by an anonymous user with no source attached.1
I searched on Google and couldn't find any source corroborating that claim. Despite that, surprisingly, this trick seems to actually hold true. For example, the websites https://Ⓜ️icrosoft.com, https://ℹ️nstagram.com, and https://www.™️z.com do end up routing to their correct counterparts, whereas https://facebo🆗.com, https://🅿️interest.com, https://g🅾️ogle.com do not.
Brief summary of Punycode
Punycode is a way to encode Unicode text into ASCII characters intended for use with internationalized domain names (IDNA).2 Since domain names can only include ASCII characters,3 this was necessary to be able to support non-English languages. For compatibility with existing ASCII domain names, these punycode sequences are prepended with "xn--".4 Browsers like Google Chrome and Firefox have somewhat complex policies in place to determine whether hostnames should be displayed in their ASCII punycode forms or their intended Unicode form.5
Verifying this claim with Python
The goal is simple: use the emoji package from PyPI to brute force a solution by iterating through all possible emojis. This way, we can find any emojis that don't encode into punycode (i.e., do not start with "xn--") and are instead encoded into only ASCII characters. Fortunately, Python provides a codec for IDNA 2003 by default.6
from emoji import EMOJI_DATA
import json
punycode_by_emoji = {}
for emoji in EMOJI_DATA.keys():
try:
punycode = emoji.encode("idna")
if not (punycode.startswith(b"xn--")):
punycode_by_emoji[emoji] = punycode.decode("utf-8")
except UnicodeEncodeError:
pass
print(json.dumps(punycode_by_emoji, ensure_ascii=False)) # Allow emoji{
"Ⓜ️": "m",
"Ⓜ": "m",
"‼️": "!!",
"‼": "!!",
"⁉️": "!?",
"⁉": "!?",
"ℹ️": "i",
"ℹ": "i",
"™️": "tm",
"™": "tm"
}Interesting... While "‼️" and "⁉️" were not included in our original list, those characters are effectively irrelevant, as exclamation points and question marks are forbidden in URIs.7
The most noteworthy shared quality between all of these emojis is that they all have both a text style and an emoji style presentation. Essentially, emoji characters can default to a text-based and pictographic-based representation. For example, the emoji character "Ⓜ" (\u24c2) defaults to a text representation. However, by adding either a text presentation selector or an emoji presentation selector, you can force one variant. For example, "Ⓜ️" and "Ⓜ︎" are represented by \u24c2\ufe0f and \u24c2\ufe0e, respectively.8
Interestingly, for some reason, other textual emojis, such as "🅰️", "🆔", "🅾️", "🅿️", "🆎", "🅱️", "0️⃣"-"9️⃣", have seemingly been excluded. Why is that?
What makes these characters special?
In a Microsoft blog post, Raymond Chen documented an unclear security report where a user reported that, as expected, https://ⓜicrosoft.com goes to https://microsoft.com.9 I had not found this initially since it cites the text style instead of the emoji style, but he notes that:
The web browser is doing exactly what the standard says it’s supposed to do: Unicode Technical Standard #46 describes how so-called international domain names are converted to ASCII for domain lookup purposes. One of the steps is to map the code points according to the IDNA Mapping Table, and the IDNA Mapping Table says that character CIRCLED LATIN SMALL LETTER M (U+24DC) is mapped to LATIN SMALL LETTER M (U+006D).9
Indeed, viewing the IDNA mapping table, you can verify that his statement is true, and that "ⓜ" does map to "m". Furthermore, all variation selectors are simply ignored, meaning they map to nothing.10 This document, Unicode Technical Standard #46, also reports that the IDNA mapping table was derived via NFKC_Casefold.11
Since NFKC normalization is built into JavaScript, we can use a quick Node.js script using the emojis-list library and find all the emojis that, when normalized with NFKC, output something other than themselves.
import emojis from "emojis-list";
const unidempotentEmoji = emojis.reduce((acc, emoji) => {
const normalizedEmoji = emoji.normalize("NFKC");
if (normalizedEmoji !== emoji) {
acc[emoji] = [
normalizedEmoji,
Array.from(
normalizedEmoji,
(c) => "U+" + c.codePointAt(0).toString(16).padStart(4, "0"),
),
];
}
return acc;
}, {});
console.log(unidempotentEmoji);{
"🈁": ["ココ", ["U+30b3", "U+30b3"]], // "here"
"🈂️": ["サ️", ["U+30b5", "U+fe0f"]], // "service charge"
"🈚️": ["無️", ["U+7121", "U+fe0f"]], // "free of charge"
"🈯️": ["指️", ["U+6307", "U+fe0f"]], // "reserved"
"🈲": ["禁", ["U+7981"]], // "prohibited"
"🈳": ["空", ["U+7a7a"]], // "vacancy"
"🈴": ["合", ["U+5408"]], // "passing grade"
"🈵": ["満", ["U+6e80"]], // "no vacancy"
"🈶": ["有", ["U+6709"]], // "not free of charge"
"🈷️": ["月️", ["U+6708", "U+fe0f"]], // "monthly amount"
"🈸": ["申", ["U+7533"]], // "application"
"🈹": ["割", ["U+5272"]], // "discount"
"🈺": ["営", ["U+55b6"]], // "open for business"
"🉐": ["得", ["U+5f97"]], // "bargain"
"🉑": ["可", ["U+53ef"]], // "acceptable"
"‼️": ["!!️", ["U+0021", "U+0021", "U+fe0f"]],
"⁉️": ["!?️", ["U+0021", "U+003f", "U+fe0f"]],
"™️": ["TM️", ["U+0054", "U+004d", "U+fe0f"]],
"ℹ️": ["i️", ["U+0069", "U+fe0f"]],
"Ⓜ️": ["M️", ["U+004d", "U+fe0f"]],
"㊗️": ["祝️", ["U+795d", "U+fe0f"]], // "congratulations"
"㊙️": ["秘️", ["U+79d8", "U+fe0f"]], // "secret"
}The result of this script is indeed a superset of our previous list of emoji, only this time with various Japanese characters. This does make sense, as Japanese characters are not ASCII-compatible and would need to be encoded into punycode to be used as a domain name.
Again, the aforementioned \ufe0f emoji variation selector appears, though this time not in every emoji. In particular, only the emojis "🈂", "🈚", "🈯", "🈷", "㊗", "㊙" use a presentation selector. This also makes sense since those emojis are also the only ones listed to have an emoji presentation sequence, whereas the rest default to emoji.12
Furthermore, using one of these Japanese character emojis, we can verify our theory using a Japanese domain. .jp domains can use the Kanji, Hiragana, and/or Katakana character sets.13 The website for the Kokuzōsan Daimanji Temple (虚空蔵山 大満寺) in Sendai, Japan is located at http://虚空蔵尊.jp and contains the kanji "空" (empty/vacant). Hence, a URL like http://虚🈳蔵尊.jp should correctly route to its intended destination. And indeed, it does.
However, this does raise another question, and that is, what makes these emoji in particular special?
Compatibility and Unicode
If you ever wonder why a strange Unicode character exists, 9/10 times it'll be because of compatibility with older systems. For example, the somewhat strange Man in Business Suit Levitating emoji ("🕴") was added in 2014 for compatibility with the 1997 font Webdings.14
Hence, to understand this behavior, we have to look back to the history of emojis.
On March 5, 2009, the "Proposal for Encoding Emoji Symbols" was filed, the document that would introduce emoji into Unicode. Specifically, the reason given for the proposal was compatibility with the top three carriers in Japan: NTT DoCoMo, KDDI, and SoftBank. Indeed, the document provides a hint for this behavior:15
Existing UCS symbols are used where appropriate. This includes unifications with "upcoming" characters in ISO/IEC 10646 AMD6 and Unicode 5.2. In particular, some unifications are with symbols from the ARIB set... Characters were disunified in a small number of cases, where the visual images were very different and not semantically associated. For example, the 'M' symbol for Metro is disunified from the Metro train image.15
Indeed, we can view all the emojis they intended to introduce here: N3681 - Emoji Symbols: Background Data. This list includes the emojis we are searching for: "Ⓜ️", "ℹ️", "™️".
| Unicode code point | Emoji | DoCoMo | KDDI | SoftBank | Notes |
|---|---|---|---|---|---|
| U+203C | ‼️ | double exclamation mark | |||
| U+2049 | ⁉️ | exclamation question mark | |||
| U+2122 | ™️ | trade mark | |||
| U+2139 | ℹ️ | information | |||
| U+24C2 | Ⓜ️ | circled M | |||
| U+1F202 | 🈂️ | Japanese "service charge" button | |||
| U+1F237 | 🈷️ | Japanese "monthly amount" button | |||
| U+1F236 | 🈶 | Japanese "not free of charge" button | |||
| U+1F22F | 🈯 | Japanese "reserved" button | |||
| U+1F250 | 🉐 | Japanese "bargain" button | |||
| U+1F239 | 🈹 | Japanese "discount" button | |||
| U+1F21A | 🈚 | Japanese "free of charge" button | |||
| U+1F232 | 🈲 | Japanese "prohibited" button | |||
| U+1F251 | 🉑 | Japanese "acceptable" button | |||
| U+1F238 | 🈸 | Japanese "application" button | |||
| U+1F234 | 🈴 | Japanese "passing grade" button | |||
| U+1F233 | 🈳 | Japanese "vacancy" button | |||
| U+3297 | ㊗️ | Japanese "congratulations" button | |||
| U+3299 | ㊙️ | Japanese "secret" button | |||
| U+1F23A | 🈺 | Japanese "open for business" button | |||
| U+1F235 | 🈵 | Japanese "no vacancy" button |
NTT DoCoMo used a "M" symbol to represent the Metro emoji. In an earlier working draft, it was written that they "disunified the 'M' symbol for Metro from the Metro train image" since the symbol would "have translations problems.16" The "information" emoji was used by KDDI. Meanwhile, the "trademark" emoji was represented by all three of the top carriers. DoCoMo and KDDI both supported "⁉️" and "‼️" emojis. Our previously-mentioned Japanese character emojis also make an appearance in this table.17
Interestingly, it seems that unification only occurred if there had been a prior pre-existing Unicode symbol (i.e., no new text-style characters had been created). For example, "🆔" and "🆑" were both introduced in that document, yet are standalone emojis.17 In a later proposal, it claims that the emojis had only been unified with "characters or character sequences from Unicode 5.2 or earlier".18
Another interesting detail is that the earlier-mentioned keycap emojis "0️⃣"-"9️⃣", "#️⃣" were unified into two code points: their ASCII counterpart and \u20e3 (combining enclosing keycap). This means that in Unicode code points, if we also include the emoji presentation selector, the emoji "1️⃣" is \u0031\ufe0f\u20e3.17 Since \u20e3 is a valid character in the IDNA mapping table, this means these emojis do not normalize to ASCII and instead are encoded into punycode.
Will there be any new emojis like this?
I don't expect that any more non-punycode emojis will ever be added again.
ASCII-normalized emojis
Unicode Technical Standard #51 explicitly notes that for emojis:
The data does not include non-pictographs, except for those in Unicode that are used to represent characters from emoji sources, for compatibility, such as: 🈹 or 🆔19
Indeed, this seems to have held true. All the emojis present in the "alphanum" section of the current full emoji list were introduced in that initial Unicode 6.0 release. Furthermore, they are also all legacy emojis from NTT DoCoMo, KDDI, or SoftBank.20
Emoji unification
Evidently, it seems that some issues may have arisen from emoji unification. In October 2010, the same month the release of Unicode 6.0 would introduce emoji,21 "Emoji Variation Sequences" were proposed.18 The proposal noted that many systems and users expected their documents to remain displayed as black-and-white characters rather than colorful emojis. Apparently, as a result, black-and-white fonts had been developed. \ufe0e and \ufe0f were chosen to represent black-and-white text and emoji presentation, respectively.18 It would eventually be introduced in Unicode 6.1.19
When one looks to the frequently asked questions page for submitting an emoji, it seems that they no longer accept proposals to emojify existing characters. Apparently, while "[s]uch proposals were accepted in the past, but that proved to be problematic for a variety of reasons.22" In fact, in 2023, the Unicode Consortium outright stated that they have "determined that unifying text and emoji characters was a mistake." This comment was made on a proposal to disunify 10 characters that had been unified with emoji.23 Charlotte Buff, who originally submitted the proposal to add variation sequences for these ten emojis,23 claimed the decision was to encode a new character that was not "'tainted' by emoji presentation." Buff provided the example of the inverse of this with the newer Khanda emoji ("🪯") not being unified with the older Adi Shakti character ("☬").24
Doug Ewell, the proposer of the language subtag registry25 and an author of the aforementioned disunification proposal,23 wrote that the practice of unifying emojis with older Unicode characters has likely been deprecated.26 In particular, he claimed that "'emojifying' existing characters...[had] caused some headaches on its own." Ewell also noted that much to his chagrin, he cannot use the copyright, registered trademark, and trademark characters without them being converted to "huge, comical emoji versions" despite the standard specifying they should default to text.26
Conclusion
Emojipedia claims there are 3,953 emojis in the Unicode standard as of September 9, 2025.27 Yet, even as doubtless more emojis are added, there will still only ever be three emojis that punycode will be unable to encode.