String.prototype.charAt() returns one UTF-16 code unit at a zero-based index (same API as MDN String.prototype.charAt()). It is a classic, legacy-friendly way to read a character. This tutorial covers out-of-range "", why negatives do not work, comparisons with at() and brackets, five examples, and try-it labs.
01
Kind
Instance method
02
Returns
1 char or ""
03
Negative?
No
04
vs at()
Legacy-friendly
05
Mutates?
No
06
Baseline
Widely available
Fundamentals
Introduction
charAt() is one of the oldest ways to read a character from a string. You pass a zero-based index and get back a one-character string — or "" when that index does not exist.
It is still widely used in tutorials and older code. For new apps that need “last character” access, prefer at(-1). Keep charAt() when you want a predictable empty string for bad indexes, or when matching legacy examples.
💡
Beginner tip
Out of range, charAt() returns "" — not undefined. That is different from at() and from str[i].
charAt(index) returns a new string with a single UTF-16 code unit from the chosen position. It does not change the original string.
Indexes are zero-based — 0 is the first character.
The last character is at str.length - 1.
Missing position — returns "".
Negative indexes are not supported — use at(-1) instead.
Foundation
📝 Syntax
General form of String.prototype.charAt:
JavaScript
str.charAt(index)
Parameters
index — zero-based position of the character. Converted to an integer (undefined becomes 0).
Return value
A string with the single UTF-16 code unit at that position, or an empty string "" if the index is outside 0 … str.length - 1.
Common patterns
JavaScript
"Hello".charAt(0); // "H"
"Hello".charAt(4); // "o"
"Hello".charAt(10); // ""
"Hello".charAt("Hello".length - 1); // "o"
// Prefer at(-1) for last-character access in new code:
"Hello".at(-1); // "o"
Cheat Sheet
⚡ Quick Reference
Goal
Code
First character
str.charAt(0)
Last character
str.charAt(str.length - 1)
Out of range
""
No index argument
str.charAt() → like charAt(0)
Modern last char
str.at(-1)
Snapshot
🔍 At a Glance
Four facts to remember about String.charAt().
Returns
string
One unit or ""
Negative
not supported
Use at(-1) instead
Out of range
""
Empty string miss
Mutates
no
Strings stay immutable
Compare
📋 charAt() vs at() vs str[i]
charAt(i)
at(i)
str[i]
Negative index
Returns ""
From the end
undefined (property "-1")
Out of range
""
undefined
undefined
Index coercion
To integer (undefined → 0)
To integer
Used as property name
Best for
Legacy / empty-string misses
Readable end access
Simple positive indexes
Hands-On
Examples Gallery
Examples follow MDN String.charAt() patterns. Use View Output or Try It Yourself for each case.
📚 Getting Started
Read characters with zero-based indexes.
Example 1 — Basic charAt()
MDN demo: read a character counting from the start.
JavaScript
const sentence = "The quick brown fox jumps over the lazy dog.";
const index = 4;
`The character at index ${index} is ${sentence.charAt(index)}`;
// "The character at index 4 is q"
Many characters above U+FFFF need two UTF-16 code units. Avoid hand-pairing surrogates with charAt — use built-in code-point helpers instead.
Applications
🚀 Common Use Cases
Reading a known index — first letter, digit at position n.
Legacy last character — charAt(str.length - 1) in older samples.
Empty-string misses — when you prefer "" over undefined.
Teaching indexes — pair with length for beginners.
Migrating to at() — replace end-access patterns with at(-1).
Not for full emoji — use code points / segmenters when graphemes matter.
🧠 How charAt() Resolves an Index
1
Receive an index
Convert to an integer (undefined becomes 0).
Input
2
Check the range
Valid positions are 0 through length - 1.
Bounds
3
Read one code unit
Return that character as a new string.
Read
4
✅
Or return ""
If the index is outside the string (including negatives).
Important
📝 Notes
charAt() returns one UTF-16 code unit, not always one visible emoji.
Out-of-range indexes return "", not undefined.
charAt(-1) is not the last character — use at(-1) or charAt(length - 1).
Calling charAt() with no argument is the same as charAt(0).
Fractional indexes are truncated toward zero (like other string index methods).
Prefer at() for new code when you need relative indexing from the end.
Compatibility
Browser & Runtime Support
String.prototype.charAt() is Baseline Widely available — supported across browsers for many years (long before at()).
✓ Baseline · Widely available
String.charAt()
Safe everywhere. Prefer at(-1) when you need last-character access in modern code.
UniversalWidely available
Google ChromeSupported · Desktop & Mobile
Full support
Mozilla FirefoxSupported · Desktop & Mobile
Full support
Apple SafariSupported · macOS & iOS
Full support
Microsoft EdgeSupported · Chromium
Full support
Internet ExplorerNo native support · Use a polyfill
Polyfill
OperaSupported · Modern versions
Full support
Samsung InternetSupported · Android
Full support
BunSupported · JavaScript runtime
Supported
DenoSupported · JavaScript runtime
Supported
Node.jsSupported · Server runtime
Supported
Android WebViewSupported · Modern WebView
Full support
charAt()Excellent
Bottom line: Use String.charAt() for zero-based character access. Remember out-of-range returns "", negatives are not supported, and emoji may span two code units.
Wrap Up
Conclusion
String.prototype.charAt() is the classic way to read one UTF-16 code unit by index, returning "" when the position is missing. Learn it for legacy code — and reach for at(-1) when you want clear end access.
Use charAt(str.length - 1) when matching older tutorials
Prefer at(-1) for last-character access in new code
Pair with length when explaining zero-based indexes
Use code-point helpers for full emoji characters
❌ Don’t
Expect charAt(-1) to return the last character
Assume charAt(0) on an emoji returns the whole emoji
Treat out-of-range charAt like undefined
Hand-pair surrogates with charAt(i) and charAt(i + 1)
Forget strings are immutable — charAt never edits in place
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about String.charAt()
Zero-based character access with empty-string misses.
5
Core concepts
📝01
Returns
1 unit / ""
API
🔙02
Last
length - 1
Pattern
❌03
Negatives
not supported
Feature
⚡04
vs at
prefer at(-1)
Compare
📄05
Mutates
no
Immutable
❓ Frequently Asked Questions
String.prototype.charAt(index) returns a new string with the single UTF-16 code unit at that zero-based index. If the index is out of range, it returns an empty string "".
No. charAt(-1) returns "". To read from the end, use at(-1) or charAt(str.length - 1).
at() supports negative indexes and returns undefined when out of range. charAt() does not support negatives and returns "" for out-of-range indexes.
charAt() converts the index to an integer (undefined becomes 0) and returns "" out of range. Bracket notation uses the value as a property name and returns undefined when missing.
Not always. charAt() returns one UTF-16 code unit. Many emoji use two code units (a surrogate pair). Prefer codePointAt() / String.fromCodePoint() or [...str] for full code points.
No. Strings are immutable. charAt() returns a new one-character string (or "").
Did you know?
charAt() existed for decades before at(). Many older books still teach str.charAt(str.length - 1) for the last character — today str.at(-1) is clearer, but both remain correct.