String.fromCharCode()
The inverse of charCodeAt, and 16-bit like its partner. For any code point above 0xFFFF it silently produces the wrong character — use fromCodePoint instead.
Demo
Each number becomes one UTF-16 code unit, so 72 and 105 spell 'Hi'. The fourth case is how you build an emoji with this method — by supplying both halves of the surrogate pair yourself, which is exactly the arithmetic fromCodePoint does for you. Passing the single code point 128512 instead would NOT work: it is above 0xFFFF, so it gets truncated to its low 16 bits and yields an unrelated character with no warning at all.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| ...codes | number | no (none) | Any number of UTF-16 code units. Each is taken modulo 65536 — no error is raised for a larger value. With no arguments you get an empty string. |
Return value
string — A string built from the given UTF-16 code units. Values above 0xFFFF are TRUNCATED to their low 16 bits rather than rejected.
Common patterns
String.fromCodePoint(0x1f600);
const text = String.fromCharCode(...bytes);
let out = ""; for (let i = 0; i < b.length; i += 8192) out += String.fromCharCode(...b.subarray(i, i + 8192));
Examples
Pitfalls
String.fromCharCode(128512).codePointAt(0)
String.fromCodePoint(128512).codePointAt(0)
String.fromCharCode(...hugeArray)
new TextDecoder().decode(bytes)
'a'.fromCharCode(65)
String.fromCharCode(65)
String.fromCharCode(195, 169)
new TextDecoder().decode(new Uint8Array([195, 169]))
When to use
- Building a string from UTF-16 code units you already have
- ASCII or Latin-1 byte data, where one byte is one character
- Round-tripping with charCodeAt
- Any code point above 0xFFFF → fromCodePoint
- Decoding UTF-8 or unknown byte encodings → TextDecoder
- Very large arrays → chunk it, or TextDecoder
- You have characters, not numbers → concat or a template literal
Notes
FAQ
fromCodePoint, unless you specifically hold UTF-16 code units. It accepts the full Unicode range, builds surrogate pairs for you, and throws RangeError on an invalid value instead of silently truncating.
String.fromCodePoint(0x1f600); // an emoji String.fromCharCode(0x1f600); // a different character entirely