Why Emojis Show as Empty Boxes — And How to Fix It

The empty rectangle where an emoji should be has a name — tofu — and it always means exactly one thing. This page explains what that is, walks through the several distinct reasons it happens, and covers two behaviours that surprise people: why Windows will never show you a flag emoji, and why a family emoji sometimes splits into four separate people.

What the box means

It is the .notdef glyph — the placeholder a font draws when asked for a character it has no picture for. Your text is not damaged. The character code is intact and correct; the font simply cannot draw it. The same message will display perfectly on a device with a more complete font.

Tofu, and why it exists

Every font contains a glyph at index 0 called .notdef, which is conventionally an empty or crossed rectangle. When text rendering requests a character the font does not contain, this is what gets drawn.

Displaying something is deliberate. Silently dropping unknown characters would hide the fact that information is missing — you would read a sentence with a word invisibly absent and never know. The box is an honest signal: something is here and this font cannot show it.

The nickname comes from the resemblance to a block of tofu, and it is used seriously enough that Google's pan-Unicode font family is called Noto — short for "no more tofu". Its explicit goal is to cover every character in Unicode so the box never needs to appear.

💡 Boxes with numbers inside are more helpful

Some systems draw the character's hexadecimal code point inside the box instead of leaving it empty. A box reading 1F92F tells you precisely which character is missing, which you can look up. This is standard on Android and in some Linux font stacks, and it turns an unhelpful placeholder into a diagnostic.

The five causes

CauseLooks likeFix
No emoji font installedEvery emoji is a boxInstall Noto Color Emoji
Font predates the emojiOlder emoji fine, new ones boxesUpdate the operating system
Renderer ignores ZWJCompound emoji split into partsUpdate software; often unfixable on old systems
Deliberate non-supportFlags shown as letter pairsNot fixable — it is by design
Encoding damageQuestion marks or ð charactersA different problem — see below

Distinguishing tofu from encoding damage

This distinction matters because the fixes are completely different.

You seeMeaningData intact?
□ or ▯Tofu — font lacks the glyphYes
Box with hex digitsTofu, with the code shownYes
?Converted to a lossy encodingNo — permanently lost
ð and similarUTF-8 bytes read as Latin-1Yes, recoverable if re-decoded
Invalid byte sequenceNo

A box is a display problem — copy the text elsewhere and it works. A question mark is a data problem — the character was replaced during a conversion to an encoding that could not represent it, and copying it anywhere gives you a question mark forever.

Why Windows shows flags as letters

Type 🇬🇧 on a Mac and you get a Union Jack. Type the same characters on Windows and you get GB. This is not a bug and no update will change it.

Flag emoji are not single characters. They are pairs of regional indicator symbols — a separate alphabet of 26 letters, A to Z, at code points U+1F1E6 to U+1F1FF. A renderer sees two of them together, reads the pair as an ISO country code, and draws the corresponding flag.

🇬🇧 = U+1F1EC (regional indicator G) + U+1F1E7 (regional indicator B) 🇺🇸 = U+1F1FA (U) + U+1F1F8 (S) 🇮🇳 = U+1F1EE (I) + U+1F1F3 (N) 🇯🇵 = U+1F1EF (J) + U+1F1F5 (P) // The characters are letters. Drawing a flag is the // renderer's interpretation of the pair — and optional.

Microsoft's emoji font contains the regional indicator letters but no flag glyphs, so Windows draws the letters. The design is widely understood to sidestep the question of which territories get a flag — a genuinely fraught issue that has caused real problems for other vendors.

⚠️ This affects your product, not just your chat

If your interface uses flag emoji for language pickers or country selectors, roughly half your desktop users see two-letter codes instead of flags. It is not broken — GB is arguably clearer than a small flag — but if the design assumed a visual marker, it does not work there.

Use SVG flag icons if flags matter to the design. They render identically everywhere and let you control exactly which territories appear.

When compound emoji fall apart

Many emoji are not single characters at all. They are sequences joined by an invisible character called the zero-width joiner (U+200D), which instructs the renderer to merge the neighbouring emoji into one glyph.

👨‍👩‍👧‍👦 family = 👨 + ZWJ + 👩 + ZWJ + 👧 + ZWJ + 👦 = 7 code points, 1 intended glyph 👨‍💻 man technologist = 👨 + ZWJ + 💻 // man + laptop 🧑‍🚀 astronaut = 🧑 + ZWJ + 🚀 // person + rocket ❤️‍🔥 heart on fire = ❤ + VS16 + ZWJ + 🔥

A renderer that understands the sequence draws one merged image. One that does not draws each component in turn — so the family becomes a man, a woman, a girl and a boy standing in a row, and the astronaut becomes a person followed by a rocket.

This is a graceful degradation by design. The meaning survives even when the combined artwork does not, which is why the ZWJ approach was chosen over allocating a new code point for every possible combination — an approach that would have required thousands of them.

Skin tones work the same way

👋🏽 = 👋 (wave) + U+1F3FD (medium skin tone modifier) // Unsupported: renders as 👋 followed by a colour swatch

The five skin tone modifiers are based on the Fitzpatrick dermatological scale. A renderer without support shows the base emoji followed by a small coloured square, which is the modifier drawn as its own character.

Text versus emoji presentation

Some characters existed long before emoji and can be drawn either way. A variation selector decides which:

SequenceRenders as
U+2764❤ — monochrome text heart
U+2764 U+FE0F❤️ — colour emoji heart
U+2708✈ — text aeroplane
U+2708 U+FE0F✈️ — emoji aeroplane

U+FE0F requests emoji presentation; U+FE0E requests text presentation. This is why a heart appears black and flat in one application and red and glossy in another — the same base character with a different, invisible selector, or a renderer applying its own default.

Fixing it per platform

PlatformEmoji fontHow to fix
WindowsSegoe UI EmojiWindows Update. Flags will still not render.
macOS / iOSApple Color EmojiSystem update — the font is not separately installable
AndroidNoto Color EmojiSystem update; some apps bundle their own via AndroidX Emoji2
LinuxUsually noneInstall one — see below
WebWhatever the OS providesServe an emoji web font, or use images
# Linux — the usual missing piece sudo apt install fonts-noto-color-emoji # Debian, Ubuntu sudo dnf install google-noto-emoji-color-fonts # Fedora sudo pacman -S noto-fonts-emoji # Arch # Rebuild the font cache, then restart applications fc-cache -f -v # Confirm an emoji font is now visible to the system fc-list | grep -i emoji

Guaranteeing emoji on a website

/* Name the platform emoji fonts explicitly at the end of your stack, so the browser falls through to them */ body { font-family: 'Inter', system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji'; }

Listing the emoji fonts after your generic families is important — the browser uses the first font in the list that contains each character, so text uses your typeface and emoji fall through to the colour font. Putting them first would apply the emoji font to ordinary text where it happens to have glyphs.

Where emoji must be identical for every visitor — in a product interface, or in marketing where the design matters — use SVG images from an open set such as Twemoji rather than font characters. It costs a few requests and removes all platform variation.

🚨 The same emoji means different things on different platforms

Vendors draw emoji themselves, and the results have historically diverged sharply. The grimacing face has read as a smile on one platform and a pained wince on another; the pistol was redrawn as a water pistol by every major vendor at different times, so the same message could be threatening on one device and playful on another.

For anything where tone matters — a support reply, a moderation decision, a legal record — do not assume the recipient sees what you see.

Emoji in databases

A very common cause of emoji turning into question marks has nothing to do with fonts.

MySQL's utf8 character set is not real UTF-8. It stores a maximum of three bytes per character, which covers everything up to U+FFFF and excludes every emoji — those live above U+FFFF and need four bytes. Inserting an emoji into a utf8 column either raises an error or silently truncates the string at that point.

-- utf8mb4 is real UTF-8. Always use it. ALTER TABLE messages CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- The connection must agree, or it re-encodes on the way in SET NAMES utf8mb4;

The name is a historical accident that has cost an enormous amount of debugging time: utf8 was defined before four-byte characters were in wide use, and renaming it later would have broken existing schemas. In MySQL 8, utf8mb4 is the default — but plenty of older databases and connection strings still specify the incomplete one.

Summary

  • A box means the font lacks the glyph. Your data is intact.
  • A question mark means the data is gone — a different and worse problem.
  • Windows shows flags as letter pairs by design. No update changes it; use SVG icons if flags matter.
  • Compound emoji are joined with an invisible ZWJ and fall back to their components.
  • Linux usually needs an emoji font installed — Noto Color Emoji.
  • List platform emoji fonts last in your CSS stack.
  • MySQL's utf8 cannot store emoji. Use utf8mb4.
  • The same emoji looks different across platforms. Do not rely on it to carry tone.

Frequently Asked Questions

What does the empty box instead of an emoji mean?

It is the .notdef glyph, nicknamed tofu, and it means the font being used has no drawing for that character. It is not corruption and the text is not damaged — the character code is correct and intact, and it will display normally on a device whose font includes it.

Why does Windows show country flags as two letters instead of a flag?

Windows deliberately does not render flag emoji. Flags are encoded as pairs of regional indicator symbols — 🇬🇧 is really the letters G and B in a special alphabet — and Microsoft chose to display those letters rather than draw flags, a decision widely understood to avoid taking positions on contested territories. The characters are correct; Windows renders them as designed.

Why does a family emoji show as several separate people?

Compound emoji are built by joining several emoji with an invisible zero-width joiner, U+200D. A renderer that understands the sequence draws one combined glyph; one that does not draws each component separately. So the family becomes a man, a woman and two children in a row — every character is present, just not merged.

How do I fix missing emoji on Linux?

Install a colour emoji font — Noto Color Emoji is the standard choice and is packaged for every major distribution. Most desktop Linux installations do not include one by default, which is why emoji appear as boxes or monochrome outlines out of the box.

Why do new emoji not show on my older phone?

Emoji are added to Unicode roughly annually, and support requires a font update, which arrives with an operating system update. A device that no longer receives updates is frozen at whichever emoji set shipped last. Nothing can be installed to fix it on a locked-down mobile OS.

P

Written by Paras

We build free, browser-based file tools and write the reference material we wish existed when we were looking things up. Spotted an error? Tell us and we will fix it.