String.prototype.codePointAt()

Returns the full Unicode code point at an index, keeping surrogate pairs such as emoji intact.

Signature
codePointAt(index)
  • Added in JavaScript ECMAScript 2015

Parameters

ParameterTypeDescription
$indexnumberZero-based index of the character whose code point is returned. Converted to an integer; undefined becomes 0.

Return value

number | undefinedA non-negative integer: the code point at the given index, or undefined when the index is outside 0 – str.length - 1.

codePointAt() is the Unicode-correct counterpart to charCodeAt(). When the code unit at index is a leading surrogate (U+D800–U+DBFF) and a trailing surrogate follows, it combines both and returns the real code point — up to 0x10FFFF. In every other case it returns the same value charCodeAt() would.

Index arithmetic is the catch

The index is still measured in code units. Reading a code point at index 0 of an emoji does not make index 1 the next character — index 1 is the trailing surrogate, and asking for it returns that lone surrogate value rather than undefined. A manual loop must advance by cp > 0xFFFF ? 2 : 1. Iterating with for...of or spreading the string does that stepping for you and is almost always the better choice.

Where you actually need it

Reach for it when a code point number is the goal: building a U+ label, checking whether a character sits in an emoji or CJK block, or feeding String.fromCodePoint() to round-trip. Note that a code point is still not a user-visible character — flags, skin tones and ZWJ sequences are several code points glued together, and only Intl.Segmenter counts those as one.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Print a character's U+XXXX identifier in a debugging tool
  • Test whether input contains astral characters before storing it
  • Round-trip a character through String.fromCodePoint()
  • Step through text one real code point at a time in a lexer

Frequently asked questions

What is the difference between codePointAt() and charCodeAt()?

codePointAt() combines a surrogate pair into the real code point (up to 0x10FFFF), while charCodeAt() only ever returns a single 16-bit code unit and hands back half of an emoji.

How do I get the Unicode code point of an emoji?

Use emoji.codePointAt(0), then .toString(16) for the hex form used in U+1F600 style labels. Spread or iterate first if the emoji is not at the start of the string.

Why does codePointAt(1) return a strange number for a 2-character string?

Index 1 lands on the trailing surrogate of a pair, and the method returns that surrogate value verbatim. Advance by 2 after a code point above 0xFFFF, or iterate with for...of.

More examples

Labelling every code point

for...of walks code points, so each ch is a complete character and codePointAt(0) on it always gives the full value. The two length readings show the code-unit / code-point gap.

Example · javascript
const text = "a\u{1F600}b";
for (const ch of text) {
  const cp = ch.codePointAt(0);
  console.log(ch, "U+" + cp.toString(16).toUpperCase().padStart(4, "0"));
}
// a U+0061
// 😀 U+1F600
// b U+0062

console.log(text.length); // 4 code units
console.log([...text].length); // 3 code points

Detecting astral characters

Anything above 0xFFFF needs a surrogate pair, which is the practical test for "will a code-unit API mangle this". The family emoji shows the remaining gap: 5 code points that render as one glyph.

Example · javascript
const hasAstral = (s) => [...s].some((ch) => ch.codePointAt(0) > 0xffff);

console.log(hasAstral("plain ascii")); // false
console.log(hasAstral("café")); // false — é is U+00E9
console.log(hasAstral("ship it \u{1F680}")); // true

// A code point still is not a visible character:
const family = "\u{1F468}‍\u{1F469}‍\u{1F467}";
console.log(family.length, [...family].length); // 8 5

Discussion

  • Be the first to comment on this lesson.