JavaScript String codePointAt() Method

Beginner
⏱️ 10 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Instance method

What You’ll Learn

String.prototype.codePointAt() returns the full Unicode code point starting at a UTF-16 index (same API as MDN String.prototype.codePointAt()). Learn emoji / surrogate pairs, out-of-range undefined, how it differs from charCodeAt(), safe looping, five examples, and try-it labs.

01

Kind

Instance method

02

Returns

Code point / undefined

03

Emoji

Full value

04

vs charCodeAt

UTF-16 unit only

05

Mutates?

No

06

Baseline

Widely available

Introduction

Unicode code points run from 0 to 0x10FFFF (over one million). JavaScript strings store text as UTF-16 code units (065535). Characters above U+FFFF — including many emoji — use two units (a surrogate pair).

charCodeAt() always returns one unit. codePointAt() returns the full character value when you start at the leading surrogate — so "😍".codePointAt(0) is 128525, not a half-emoji number.

💡
Beginner tip

Indexes are still UTF-16 based (same as length). Out of range, codePointAt() returns undefined — not NaN.

This page is part of JavaScript String Methods. Related topics include charCodeAt() and charAt().

Understanding the codePointAt() Method

codePointAt(index) reads the Unicode code point that starts at that UTF-16 index. If the unit there is a leading surrogate with a matching trail, you get the combined code point.

  • Indexes are zero-based UTF-16 positions — same as charAt.
  • Valid results are integers from 0 to 0x10FFFF.
  • Missing position — returns undefined.
  • A trailing-surrogate-only index returns just that unit (not the full emoji).

📝 Syntax

General form of String.prototype.codePointAt:

JavaScript
str.codePointAt(index)

Parameters

  • index — zero-based UTF-16 position where the character starts. Converted to an integer (undefined becomes 0).

Return value

A number (the Unicode code point) or undefined. Special cases:

SituationReturns
Valid BMP character (e.g. "A", "★")Code point 065535 (e.g. "A".codePointAt(0)65)
Leading surrogate of a pair (e.g. emoji at index 0)Full code point (may be > 65535, e.g. "😍".codePointAt(0)128525)
Trailing surrogate only (e.g. emoji at index 1)That trailing unit alone (e.g. 56845) — not the full emoji
No argument / undefinedSame as codePointAt(0)
Index out of range (including negatives)undefined

Common patterns

JavaScript
"ABC".codePointAt(0);                 // 65
"😍".codePointAt(0);                  // 128525
"😍".codePointAt(0).toString(16);     // "1f60d"

String.fromCodePoint(128525);         // "😍"

// Iterate by code point (recommended):
[..."☃★😍"].map((ch) => ch.codePointAt(0));
// [9731, 9733, 128525]

⚡ Quick Reference

GoalCode
Full Unicode valuestr.codePointAt(i)
Hex formstr.codePointAt(i).toString(16)
Out of rangeundefined
Number → characterString.fromCodePoint(n)
Loop by code pointfor (const ch of str) or [...str]
UTF-16 unit onlystr.charCodeAt(i)

🔍 At a Glance

Four facts to remember about String.codePointAt().

Returns
number | undefined

Full code point

Out of range
undefined

Not NaN, not ""

Emoji at 0
full value

Combines surrogates

Mutates
no

Strings stay immutable

📋 codePointAt() vs charCodeAt() vs charAt()

codePointAt(i)charCodeAt(i)charAt(i)
Result typeNumber (full code point)Number (0–65535)String (1 unit)
Out of rangeundefinedNaN""
Emoji at leading indexFull code pointHigh surrogate onlyLone surrogate text
Best forTrue Unicode valueUTF-16 unit mathReading character text

Examples Gallery

Examples follow MDN String.codePointAt() patterns. Use View Output or Try It Yourself for each case.

📚 Getting Started

Read Unicode code points as numbers.

Example 1 — Basic codePointAt()

MDN demo: read the code point of a symbol by index.

JavaScript
const icons = "☃★♲";

icons.codePointAt(1);
// 9733
Try It Yourself

How It Works

Index 1 is the star "★". These symbols sit in the BMP, so one UTF-16 unit equals one code point — same number charCodeAt(1) would give.

Example 2 — Decimal and Hex

MDN-style: print both forms of a code point.

JavaScript
"ABC".codePointAt(0);              // 65
"ABC".codePointAt(0).toString(16); // "41"

"😍".codePointAt(0);               // 128525
"😍".codePointAt(0).toString(16);  // "1f60d"
Try It Yourself

How It Works

Hex is common in Unicode docs (U+1F60D). Call .toString(16) on the number you get from codePointAt.

📈 Practical Patterns

Emoji surrogates, bounds, and safe iteration.

Example 3 — Emoji: Full Point vs Trailing Surrogate

MDN note: start at the leading unit for the full character.

JavaScript
"😍".codePointAt(0);   // 128525  (full emoji)
"😍".codePointAt(1);   // 56845   (trailing surrogate only)

"😍".length;           // 2
"😍".charCodeAt(0);    // 55357   (high surrogate — not the full emoji)

String.fromCodePoint(128525);  // "😍"
Try It Yourself

How It Works

Use index 0 (the start of the character) for the real code point. Index 1 is inside the pair — you only get the trail unit.

Example 4 — Out of Range & Compare Miss Values

Missing indexes return undefined — different from charCodeAt.

JavaScript
const s = "Hi";

s.codePointAt();      // 72
s.codePointAt(0);     // 72
s.codePointAt(1);     // 105
s.codePointAt(2);     // undefined
s.codePointAt(-1);    // undefined
s.codePointAt(999);   // undefined

s.charCodeAt(2);      // NaN
s.charAt(2);          // ""
Try It Yourself

How It Works

Check misses with === undefined (or optional chaining). Do not use Number.isNaN here — that is for charCodeAt.

Example 5 — Loop by Code Point (Not by Index)

MDN advice: avoid a plain for over length with emoji.

JavaScript
const str = "\ud83d\udc0e\ud83d\udc71\u2764";  // 🐎 + 👤 + ❤

// Prefer for...of or spread (iterate code points):
[...str].map((cp) => cp.codePointAt(0).toString(16));
// ["1f40e", "1f471", "2764"]

// Index loop visits trailing surrogates too — usually not what you want:
for (let i = 0; i < str.length; i++) {
  // may log half-emoji units as well as full points
  str.codePointAt(i).toString(16);
}
Try It Yourself

How It Works

for...of and spread use the string iterator, which yields one complete code point at a time. Then codePointAt(0) on each piece is safe.

🚀 Common Use Cases

  • Emoji & rare characters — get the real Unicode value, not a surrogate.
  • Hex / U+ notationcodePointAt(0).toString(16) for docs and logs.
  • Round-trip with fromCodePoint — rebuild characters from numeric IDs.
  • Safe iteration — pair with for...of / [...str].
  • Validation — check ranges for allowed symbols or scripts.
  • Not for grapheme clusters — family emoji / skin tones may need Intl.Segmenter.

🧠 How codePointAt() Resolves an Index

1

Receive an index

Convert to an integer (undefined becomes 0).

Input
2

Check the range

Outside 0length - 1undefined.

Bounds
3

Read the unit(s)

If a leading surrogate + trail, combine into one code point.

Decode
4

Return the number

Full Unicode value, a single BMP unit, or a lone trail surrogate.

📝 Notes

  • Indexes are UTF-16 code units, even though the return value is a code point.
  • Out-of-range indexes return undefined, not NaN.
  • Calling codePointAt() with no argument is the same as codePointAt(0).
  • Starting on a trailing surrogate returns only that unit — start on the leading one for the full emoji.
  • Prefer for...of / spread when iterating characters that may be emoji.
  • Visible “characters” with modifiers (ZWJ sequences) may span multiple code points — use a segmenter when needed.

Browser & Runtime Support

String.prototype.codePointAt() is Baseline Widely available — supported across modern browsers since 2015.

Baseline · Widely available

String.codePointAt()

Safe for production. Prefer this over charCodeAt() whenever emoji or full Unicode values matter.

Universal Widely available
Google Chrome Supported · Desktop & Mobile
Full support
Mozilla Firefox Supported · Desktop & Mobile
Full support
Apple Safari Supported · macOS & iOS
Full support
Microsoft Edge Supported · Chromium
Full support
Internet Explorer No native support · Use a polyfill
Polyfill
Opera Supported · Modern versions
Full support
Samsung Internet Supported · Android
Full support
Bun Supported · JavaScript runtime
Supported
Deno Supported · JavaScript runtime
Supported
Node.js Supported · Server runtime
Supported
Android WebView Supported · Modern WebView
Full support
codePointAt() Excellent

Bottom line: Use String.codePointAt() for full Unicode code points. Remember out-of-range returns undefined, and iterate with for...of when strings may contain emoji.

Conclusion

String.prototype.codePointAt() returns the full Unicode code point at a UTF-16 index — including values above 65535 for emoji — or undefined when the position is missing. Pair it with fromCodePoint() and iterate with for...of for reliable Unicode work.

Continue with includes(), charCodeAt(), or the String methods hub.

💡 Best Practices

✅ Do

  • Use codePointAt(i) for full Unicode values
  • Check misses with === undefined
  • Pair with String.fromCodePoint() for round-trips
  • Iterate with for...of or [...str]
  • Call it at the start of a character (leading surrogate)

❌ Don’t

  • Expect out-of-range results to be NaN
  • Assume every index is the start of a full character
  • Loop with i++ over length for emoji strings
  • Use fromCharCode for values above 65535
  • Forget that one visible emoji can still be several code points

Key Takeaways

Knowledge Unlocked

Five things to remember about String.codePointAt()

Full Unicode code points with undefined for missing indexes.

5
Core concepts
😀 02

Emoji

full value at 0

Unicode
03

Miss

undefined

Bounds
04

Loop

for...of / spread

Pattern
📄 05

Mutates

no

Immutable

❓ Frequently Asked Questions

String.prototype.codePointAt(index) returns a non-negative integer — the Unicode code point of the character starting at that UTF-16 index. Out of range, it returns undefined.
charCodeAt() always returns one UTF-16 code unit (0–65535). codePointAt() returns the full Unicode code point, which can be larger than 65535 when the character is a surrogate pair (many emoji).
undefined. That differs from charCodeAt(), which returns NaN, and from charAt(), which returns "".
Indexes are still UTF-16 code units (same as length and charAt). For a two-unit emoji, index 0 returns the full code point; index 1 lands on the trailing surrogate and returns only that unit.
Use String.fromCodePoint(codePoint). Prefer that over fromCharCode() when the value may be above 65535.
Prefer for...of or [...str] — they iterate by code point. Looping with for (i = 0; i < str.length; i++) visits both halves of a surrogate pair.
Did you know?

A single “character” on screen can be several Unicode code points — for example a family emoji joined with Zero Width Joiners. codePointAt reads one code point at a time; counting what a user sees may need Intl.Segmenter with granularity: "grapheme".

More String Methods

Return to the hub for slice, trim, replace, and more.

String methods hub →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful