Emoji Counter – Count Emoji, Graphemes, Code Points and UTF-16 Units
Paste any text into this emoji counter and it answers two questions exactly: how many emoji is that, and how long is the string really. Both answers are more slippery than they look, which is why most counters on the web disagree with each other about the same sentence. Everything here runs in your browser — nothing you paste is uploaded, stored or sent anywhere.
Why there are three lengths, not one
A string has at least three defensible lengths and they are routinely confused with each other:
- Grapheme clusters — the characters a reader perceives, found with
Intl.Segmenterat grapheme granularity. - Code points — Unicode scalar values, what
Array.from(text).lengthreturns. - UTF-16 code units — what JavaScript’s
String.lengthreports, and what a great many length budgets are quietly built on.
The family emoji U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 is 1 grapheme cluster, 7 code points and 11 UTF-16 code units. A counter that reports a single number has picked one of those three and not told you which. This tool always shows all three, always labelled, and never derives the emoji count by subtracting one from another.
How “is this an emoji?” is decided
Classification uses Unicode property escapes rather than a hardcoded list of code-point ranges, because a range list rots with every Unicode release. A cluster counts as an emoji cluster when it contains at least one \p{Extended_Pictographic} code point, or is a regional-indicator pair, or is a keycap sequence.
\p{Emoji} on its own is not a valid test. The ASCII digits 0–9, # and * all carry Emoji=Yes, so a counter built on that property reports a bare 7 as an emoji. A plain digit is plain text here, and there is a test for exactly that case.What the breakdown tells you
Every grapheme cluster is labelled with its kind and its cost. A single pictograph such as U+2615 is one thing; a skin-tone sequence such as U+1F44D U+1F3FD is a modifier base plus a Fitzpatrick modifier, reported by type number. A ZWJ sequence lists its joined components, and because multi-person sequences carry a tone per person, skin tone is reported as a list rather than as one field. A flag is a pair of regional indicators, decoded to the ASCII letters it spells — with the important caveat that an odd trailing indicator is not half a flag but a dangling one, so 🇺🇸🇬 is two clusters and one flag.
Tag sequences produce the most surprising number in the tool. A subdivision flag is U+1F3F4 followed by one invisible tag character per letter of the subdivision code and a cancel tag to close the run. Every tag character lives above the BMP and therefore costs two UTF-16 units, so a single apparent glyph climbs to 14 UTF-16 code units across 7 code points.
The hearts problem, and other invisible differences
❤ is U+2764. ❤️ is U+2764 U+FE0F, with a variation selector requesting the colour glyph. On most screens they look identical, but they are 1 and 2 code points respectively, and many keyboards insert the second form without telling you. The same story runs through plain text: é as U+00E9 is one code point, while the decomposed e plus combining acute is two. Grapheme is not code point for ordinary letters either, not just for emoji.
Reading the ruler
The grapheme ruler draws one box per cluster, with each box’s width scaled to its UTF-16 cost, so an emoji-heavy line visibly sprawls next to a line of letters of the same apparent length. Clicking a box opens the code-point inspector, where every invisible code point — joiners, variation selectors, tag characters — appears as its own labelled chip. The stacked bar beneath answers “how much of this string is emoji?” in units rather than by eye.
Emoji names come from a local dataset by exact sequence match. When a sequence is not in it, the tool says so rather than inventing a name — a wrong name is worse than no name.