JS String Methods Reference

String.prototype.codePointAt(index)

codePointAt returns the full Unicode code point starting at the given position. Where charCodeAt returns a single 16-bit unit, codePointAt recombines surrogate pairs into one value between 0 and 0x10FFFF.

Basic usage

const s = "a\uD83D\uDE00b"; // "a😀b"
s.codePointAt(0); // 97       ('a')
s.codePointAt(1); // 128512   (😀, one value, not two)
s.codePointAt(2); // 56832    (low surrogate! see below)
s.codePointAt(3); // 98       ('b')

Indexing is still by UTF-16 units

The index argument counts UTF-16 positions, not characters. Calling codePointAt(2) in the example above lands on the second half of the surrogate pair, and the method dutifully returns that lone low surrogate (56832). It does not skip ahead for you.

To walk a string by code points, test the position or use the iterator:

const s = "a\uD83D\uDE00b";
let cps = [];
for (let i = 0; i < s.length; i++) {
  const cp = s.codePointAt(i);
  cps.push(cp);
  if (cp > 0xFFFF) i++;           // skip low surrogate
}
cps; // [97, 128512, 98]

[...s].map(c => c.codePointAt(0)); // same result, simpler

charCodeAt vs codePointAt

Expression (s = "😀")Result
s.charCodeAt(0)55357 (high surrogate)
s.charCodeAt(1)56832 (low surrogate)
s.codePointAt(0)128512 (the emoji)
s.codePointAt(1)56832 (lone low surrogate)

Out-of-range behavior

Like charCodeAt, an out-of-range index returns undefined — wait, no: it returns undefined for codePointAt (while charCodeAt returns NaN). This asymmetry is worth remembering when validating input:

"ab".charCodeAt(9);    // NaN
"ab".codePointAt(9);   // undefined

See also