Emoji to Unicode, one code point at a time

A single emoji on screen is often three, five or seven code points glued together. Paste one below to see each piece, the job each piece does, and the exact escape your code, HTML or database expects. Paste codes instead and you get the emoji back.

Visible characters
0
Emoji
0
Code points
0
UTF-16 units
0
UTF-8 bytes
0

Character breakdown

  • base emoji
  • joiner
  • style selector
  • modifier
  • flag letter
  • tag

Why one emoji turns into several code points

Seven building blocks explain almost every multi-part emoji you will meet.

Unicode gives each base emoji one code point. Everything beyond the base, a skin tone, a gender, a second person, a flag, gets built by stacking extra code points behind the base. Your phone or browser reads the stack and draws one picture. If the font has no picture for the stack, you see the parts in a row instead.

Building blockCode pointsJobExample
Zero width joinerU+200DGlues the emoji on either side into one picture.👨‍👩‍👧
Variation selector 16U+FE0FAsks for the color emoji form of a symbol older than emoji.❤️
Skin tone modifierU+1F3FB to U+1F3FFFive tones based on the Fitzpatrick scale, placed right after a person or hand.👋🏼
Regional indicatorU+1F1E6 to U+1F1FFLetters A to Z. Two in a row spell an ISO country code, drawn as a flag.🇵🇰
Combining keycapU+20E3Draws a key outline around a digit, # or *, after U+FE0F.1️⃣
Tag charactersU+E0020 to U+E007FSpell a region code such as gbeng after a black flag. Only England, Scotland and Wales are on the recommended list.🏴󠁧󠁢󠁥󠁮󠁧󠁿
Hair componentU+1F9B0 to U+1F9B3Red, curly, bald or white hair, joined to a person with U+200D.👩‍🦰

The breakdown cards in the converter color each piece by its job, using the key above the cards. Load sample fills the box with a short line holding seven different cases. The 👩🏽‍💻 card lists four code points: U+1F469 woman, U+1F3FD medium skin tone, U+200D joiner, U+1F4BB laptop. Delete the joiner and most systems draw two separate emoji, a woman and a laptop.

The England flag on the same line is the heaviest case: seven code points, 28 bytes, for one small flag.

One emoji, four different lengths

Each language counts a different unit, so the same string reports a different size.

Length reported for each emoji
CheckCounts😀❤️👨‍👩‍👧England flag
str.length in JavaScript, s.length() in JavaUTF-16 code units22814
len(s) in Python, CHAR_LENGTH() in MySQLCode points1257
len(s) in Go, LENGTH() in MySQLUTF-8 bytes461828
s.count in Swift, Intl.Segmenter in JavaScriptVisible characters1111

The stats strip under the converter shows all four counts for whatever you paste. Three places where the gap bites:

Form limits

Browsers measure maxlength in UTF-16 units. A field set to maxlength="10" accepts only five 😀, and one family emoji uses eight of the ten slots.

Database columns

MySQL sizes VARCHAR(n) in code points. A column of VARCHAR(20) holds twenty plain smileys but only four family emoji. The older utf8 charset (an alias for utf8mb3) stores at most 3 bytes per character, so every emoji above U+FFFF fails with Incorrect string value: '\xF0\x9F\x98\x80'. Use utf8mb4 for the column, the table and the connection.

Truncation

Cutting a string with substring(0, n) in JavaScript or Java splits surrogate pairs and leaves a broken half. Cut on visible characters with Intl.Segmenter instead.

Pick the escape your code expects

Same emoji, nine spellings. The output format menu writes each of them.

Where the text goesMenu optionGrinning face written out
JavaScript (ES2015 and later), PHP 7+, Ruby, Swift, Rust\u{} escape\u{1F600}
JSON, Java, pre-2015 JavaScriptUTF-16 \uXXXX\uD83D\uDE00
Python, C#, C and C++, Go\U0001F600\U0001F600
HTML page or attributeHTML hex or decimal entity😀 or 😀
CSS content propertyCSS escape\01F600
URL query stringPercent-encoded%F0%9F%98%80
Hex dump, packet captureUTF-8 bytesF0 9F 98 80
Docs, bug reports, specsU+ notationU+1F600

The highlighted JSON row trips people up most. JSON has no \u{1F600} form, and strict parsers throw an error. Write the surrogate pair, or skip escaping and save the raw emoji, since JSON files are UTF-8 by default. PHP's json_encode writes the surrogate pair unless you pass JSON_UNESCAPED_UNICODE.

The CSS escape is padded to six digits on purpose. A shorter \1F600 followed by a letter from a to f would swallow the letter as part of the number.

With Leave letters and digits readable ticked, a line like Hi 😀 becomes Hi \u{1F600}, ready to drop into a string literal. Quotes, backslashes and angle brackets get escaped either way, so the output never closes your string or tag early.

Reading broken emoji

Match the symptom on your screen to the cause. Paste the broken text into the converter to confirm.

😀Garbled Latin letters
Mojibake. The four UTF-8 bytes of 😀 (F0 9F 98 80) got read as Windows-1252, one letter per byte. The data is fine. The reader picked the wrong encoding. Send Content-Type: text/html; charset=utf-8, or reopen the file as UTF-8.
????Question marks after saving
The database column or connection uses a 3-byte charset. In MySQL, convert the table to utf8mb4 and run SET NAMES utf8mb4 on the connection. Text already saved as question marks stays lost.
PKTwo letters instead of a flag
Windows ships no country flag pictures in its emoji font, so regional indicator pairs show as letters. The code points are correct. Open the same text on a phone and the flag appears.
👨 👩 👧A family split into people
Either the font lacks the combined picture, or something stripped the U+200D joiners. Paste the text in and check the card. No joiner in the chain points to a sanitizer or an old storage layer.
❤︎A black outline heart
The sequence is missing U+FE0F, so some apps draw the text form. Add U+FE0F after U+2764 to request the red emoji.
�A diamond with a question mark
A string got cut between the two halves of a surrogate pair, then encoded. Code to emoji mode flags a lone half such as \uD83D in red with a short reason.

Where this converter stops

Know these before you trust a result in production.

  1. No emoji names. Cards show the Unicode block and the job of each piece, not names such as "grinning face". Use the Unicode Character Finder to look a name up.
  2. No check against the recommended list. Any chain of code points decodes, including combinations no vendor draws as one picture. Your device decides what shows up.
  3. Display follows your fonts. Unicode adds new emoji each September and phone makers ship them months later. A brand new emoji shows as a box on an older device even when every code point is right.
  4. Bare hex means code points. 2764 FE0F decodes to a heart. A run of two-digit values such as F0 9F 98 80 decodes as UTF-8 bytes only when the run forms valid UTF-8. Prefix bytes with \x or % to remove doubt. Spaces between U+ codes or bare hex count as separators, so write U+0020 for a real space. Spaces between escapes such as \u{1F600} stay in the result.
  5. Cards stop at 120 characters. The output box and the counters still cover the full text.
  6. Text stays in your browser. Conversion runs in JavaScript on this page. Copy link puts your text in the URL, so skip the link for anything private.

Emoji and Unicode questions

Short answers to the questions developers send us most about emoji encoding.

What is the Unicode for the red heart emoji?

The red heart is two code points: U+2764 (heavy black heart) followed by U+FE0F, the emoji style selector. Without U+FE0F some apps draw a black text heart. In HTML write ❤️ and in JavaScript write \u{2764}\u{FE0F}.

Why does JavaScript report a length of 2 for one emoji?

JavaScript strings count UTF-16 code units. Any emoji above U+FFFF needs a surrogate pair, which is two units. Use [...str].length to count code points, or Intl.Segmenter to count visible characters.

How do I put an emoji in a JSON string?

Write the UTF-16 surrogate pair, for example \uD83D\uDE00 for the grinning face. JSON has no \u{1F600} syntax. Saving the raw emoji in a UTF-8 file also works with every standard JSON parser.

Why does my database store emoji as question marks?

The column, table or connection uses a charset limited to 3 bytes per character, such as utf8 (utf8mb3) in MySQL. Most emoji need 4 bytes. Switch all three to utf8mb4 and re-save the text, since the question marks replaced the original data.

Why do flag emoji show as two letters on Windows?

A country flag is two regional indicator letters, such as P and K for Pakistan. The Windows emoji font has no flag pictures, so Windows prints the letters. The text itself is correct and shows a flag on Android, iOS and macOS.

Is the text I paste sent to a server?

No. Encoding and decoding run in your browser. The only time your text leaves the page is when you press Copy link, which puts the text in the URL you share.