String Length Calculator

Paste a string and the tool reports its length in four different senses, JavaScript-style .length (UTF-16 code units), Unicode code points, grapheme clusters (what users perceive as one character), and UTF-8 bytes (what your database column actually stores). These numbers disagree for any string with emoji, flags, or combining marks, and that disagreement is the source of many bugs.

The four senses of string length

  1. 1

    UTF-16 code units

    What `str.length` returns in JavaScript. 1 for most characters, 2 for any code point beyond U+FFFF (emoji, ancient scripts).

  2. 2

    Code points

    One per Unicode scalar. Emoji are 1 each; ZWJ sequences are multiple.

  3. 3

    Grapheme clusters

    What a user calls "one character". `🇺🇸` is 2 code points but 1 grapheme. `n̈` is 2 code points but 1 grapheme.

  4. 4

    UTF-8 bytes

    What your DB stores. ASCII = 1 byte each; common European = 2; CJK = 3; most emoji = 4.

Examples

String JS .length Code points Graphemes UTF-8 bytes
hello 5 5 5 5
café 4 4 4 5
😀 2 1 1 4
🇺🇸 4 2 1 8
👨‍👩‍👧 (family) 8 5 1 18
n̈ (n + diaeresis) 2 2 1 3

Why the numbers differ

JavaScript strings are UTF-16, so a code point above U+FFFF is stored as a surrogate pair, two UTF-16 code units. "😀".length === 2. Users hate this because they think of 😀 as one character.

Graphemes go further: a country flag is two regional-indicator code points that the user sees as one flag. "🇺🇸".length === 4 in JavaScript, which feels absurd, but there it is. To iterate over graphemes, use Intl.Segmenter (modern), grapheme-splitter library, or handle manually.

UTF-8 bytes: what your database stores

For a column typed VARCHAR(255):

  • In MySQL utf8 (actual: utf8mb3), the 255 is bytes. café takes 5 bytes, so you fit 51 copies.
  • In MySQL utf8mb4 (real UTF-8, includes emoji), it is still bytes but the encoding supports 4-byte sequences.
  • In Postgres VARCHAR(255), the 255 is characters (code points), not bytes.
  • In SQL Server VARCHAR, varies by collation; NVARCHAR counts 2-byte UCS-2 units.

If you size database fields by user-visible character limit, use bytes × 4 for safety in UTF-8 columns, every grapheme potentially takes up to 4 bytes per code point, with ZWJ sequences adding more.

Twitter-style character counting

Twitter counts a tweet by a custom rule: code points, but emoji and CJK ideographs count as 2. A 100% ASCII tweet can be 280 characters; a tweet with 140 emoji maxes out at 140 “characters”.

SMS counting: 160 characters in GSM 7-bit. Any non-GSM character (á, é, ñ, emoji) flips the encoding to UCS-2, and your message length drops to 70 characters.

Practical uses

  • Database column sizing, check the byte count before writing a migration.
  • API quota enforcement, most APIs count bytes, not characters.
  • Form validation, show the user an accurate character count that matches their expectation (graphemes).
  • Performance debugging, why does this regex iterate slowly? Because the input is 3x longer in code units than in graphemes.

Frequently Asked Questions

That emoji is a ZWJ sequence combining multiple code points (e.g., a family emoji is 7 code points). Twitter counts it at 2 characters per Unicode weight rule; your editor shows 1 grapheme. Both are technically right, they just measure different things.

In UTF-8 databases, allow 4 bytes per expected character for safety. A 100-character (grapheme) field should be VARCHAR(400) bytes, or if your DB counts in characters like Postgres, VARCHAR(100) with the charset handling.

In JavaScript: it depends on the composition form. NFC composed (U+00E1) has length 1; NFD decomposed (U+0061 + U+0301) has length 2. Same visible character, different byte sequences.

Family and profession emoji are long ZWJ sequences. Fonts without full support render each code point as a separate glyph, so 👨‍💻 becomes 👨+💻. Upgrading the OS font fixes it.

Related Tools

Tool available in other languages