String Encoding
Character Encoding
Byte Length
Text Processing
String Length

Why is the length of this string longer than the number of characters in it?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

A string can look like it contains one number of characters to a human while reporting a different length to a programming language. That is not necessarily a bug. It usually means the language is counting a lower-level unit such as bytes or UTF-16 code units instead of user-perceived characters. Once you separate bytes, code units, code points, and grapheme clusters, the mismatch becomes much easier to understand.

The Four Different Things People Call "Length"

When developers say "string length," they often mean one of four different measurements:

  • byte length in an encoding such as UTF-8
  • code unit count in the language's internal string representation
  • Unicode code point count
  • grapheme cluster count, which is closest to user-perceived characters

Those are not always the same.

A single visible character can occupy:

  • 1 code point but multiple bytes
  • 2 UTF-16 code units
  • several code points combined into one displayed glyph

That is why different languages and libraries report different values.

Example 1: Bytes Versus Characters

In UTF-8, ASCII characters use one byte, but many other characters use more.

Python makes this easy to see:

python
s = "Hello, \U0001F60A"
print(len(s))
print(len(s.encode("utf-8")))

Typical output:

text
8
11

There are 8 Unicode code points in the string, but 11 bytes in its UTF-8 encoding because the emoji uses multiple bytes.

So if one tool reports a larger "length," it may be reporting encoded byte length rather than character count.

Example 2: UTF-16 Code Units in JavaScript

JavaScript strings are indexed by UTF-16 code units, not by Unicode grapheme clusters.

javascript
const s = "\u{1F60A}";
console.log(s.length);

This prints:

text
2

To a user, U+1F60A looks like one character. But in UTF-16 it is represented by a surrogate pair, which occupies two code units. JavaScript's .length reports those code units.

That is why string length in JavaScript can look "too long" for emoji and some other non-BMP characters.

Example 3: One Visible Character, Two Code Points

Some displayed characters are formed by combining multiple Unicode code points.

For example, a visually accented e can be represented as:

  • a single precomposed code point
  • the letter e followed by a combining accent

Python example:

python
s = "e\u0301"
print(s)
print(len(s))

This often displays as one visible glyph but len(s) is 2, because the string contains two code points.

That means even counting code points is not always the same as counting what a human sees on screen.

Grapheme Clusters Are Closest to User Perception

If your requirement is "count visible characters the way a user sees them," you usually want grapheme-cluster segmentation rather than raw string length.

In Python, the standard library does not expose full grapheme-cluster counting directly, but third-party libraries can. In JavaScript, Intl.Segmenter can help.

Example in modern JavaScript:

javascript
1const s = "e\u0301\u{1F60A}";
2const segmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
3const count = [...segmenter.segment(s)].length;
4console.log(count);

That count is often closer to what users expect from "number of characters."

Why This Matters in Real Software

The distinction is not academic. It affects:

  • text box length limits
  • database column sizing
  • cursor movement and substring logic
  • truncation and preview generation
  • APIs that bill or validate based on byte size

If you limit a field to 10 "characters" but actually enforce 10 bytes, multilingual users will hit the limit sooner than expected.

Choose the Right Measurement

A good rule is:

  • use byte length for storage and protocol limits
  • use code unit length only when the language API requires it
  • use code point counts for many Unicode-aware algorithms
  • use grapheme clusters for user-facing character counts

The bug often comes from using one measure while describing another.

Common Pitfalls

The biggest mistake is assuming one visible symbol always equals one unit of string length. That is false for multi-byte encodings, surrogate pairs, and combining characters.

Another mistake is comparing lengths across languages without knowing what each runtime counts. Python len, JavaScript .length, and encoded byte size can all disagree for the same text.

Developers also often store or validate text by code unit count when the real product requirement is user-visible character count.

Finally, do not assume normalization is irrelevant. Two strings that look identical can have different underlying code-point sequences and therefore different reported lengths.

Summary

  • "String length" can mean bytes, code units, code points, or grapheme clusters.
  • A string can be longer than its visible character count because encodings and Unicode representations are layered.
  • In JavaScript, .length counts UTF-16 code units, which makes emoji appear longer.
  • In UTF-8, byte length is often larger than character count.
  • For user-facing character counts, grapheme clusters are usually the correct model.

Course illustration
Course illustration

All Rights Reserved.