When you need to turn text into an integer, Number.parseInt
is the precise tool for the job. It takes a string, reads as many valid digits as it can in a base you specify (the “radix”), and returns a JavaScript Number
that represents that integer—or NaN
if it can’t read any digits at the start. It’s the same function as the global parseInt
, exposed under Number
for modularity.
Number.parseInt("42", 10); // 42
Number.parseInt(" 0x2A", 16); // 42
Number.parseInt("10px", 10); // 10 ← stops at the first non-digit
Number.parseInt("px10", 10); // NaN ← nothing to parse at the start
Number.parseInt === parseInt; // true
The signature you’ll use every day
Call Number.parseInt(string, radix?)
. The first argument is coerced to a string; leading whitespace is ignored. The second argument, the radix, should be an integer between 2 and 36. If the radix is undefined
or 0
, it’s treated as 10, except when the string (after trimming and optional sign) starts with 0x
or 0X
, in which case it’s treated as 16.
Number.parseInt("1010", 2); // 10 (binary)
Number.parseInt("2A", 16); // 42 (hex)
Number.parseInt("0x2A"); // 42 (hex inferred)
Number.parseInt("42"); // 42 (decimal inferred)
Number.parseInt("0b1010"); // 0 ("b" is not a base-10 digit)
What “parsing” means here
Number.parseInt
scans from the beginning of the string using the chosen radix. If it encounters a character that isn’t a valid digit for that base, parsing stops and the value accumulated so far is returned. If the very first non-whitespace character is invalid, you get NaN
. +
and -
are recognized as an initial sign. For bases above 10, letters A–Z
(case-insensitive) represent 10–35.
Number.parseInt("7F", 16); // 127
Number.parseInt("-1111", 2); // -15
Number.parseInt("1e3", 10); // 1 ('e' ends parsing in base 10)
Number.parseInt("2", 2); // NaN ('2' is not a binary digit)
Radix rules that matter in production
Always supply the radix when you know it. Although modern engines default to 10 (unless 0x
/0X
), being explicit prevents surprises and communicates intent. The spec itself codifies the “10 unless 0x/0X” inference. If the radix is outside 2–36 after coercion, the result is NaN
.
Number.parseInt("08"); // 8 (decimal inference)
Number.parseInt("08", 10); // 8 (explicit)
Number.parseInt("08", 1); // NaN (invalid radix)
Whitespace, signs, and coercion
Before parsing, leading whitespace is ignored and an optional sign is processed. Because the first argument is stringified, passing non-strings can yield surprising results—especially with high radices. That stringify step is standard behavior.
Number.parseInt(" +15", 10); // 15
Number.parseInt("\n-0xF", 16); // -15
Number.parseInt(null, 36); // 1112745 ← parses "null" in base 36
Number.parseInt(undefined, 36); // 86464843759093 ← parses "undefined"
Not a drop-in replacement for Number()
or parseFloat()
Number()
must consume the entire string as a numeric literal or it returns NaN
. parseFloat()
parses a decimal floating-point prefix, understanding things like scientific notation. Number.parseInt()
only returns integers and doesn’t understand e
or decimal points as number parts in any radix. These differences are documented clearly.
Number("10px"); // NaN ← whole string must be numeric
Number.parseInt("10px"); // 10
parseFloat("1e2"); // 100
Number.parseInt("1e2", 10); // 1
Safe ranges and when to reach for BigInt
The return type is a Number
(IEEE-754 double). That means integers outside the safe integer range (±(2^53−1)) can lose precision. If you’re parsing big integers, construct a BigInt
from the string instead.
Number.parseInt("9007199254740993", 10); // 9007199254740992 (precision lost)
BigInt("9007199254740993"); // 9007199254740993n (exact)
Hex is special; binary and octal are not
Without an explicit radix, only the 0x
/0X
prefix is recognized as a base hint. Binary (0b…
) and octal (0o…
) prefixes are not special to parseInt
; they’re treated as ordinary characters unless you pass a radix. This is a common point of confusion.
Number.parseInt("0xFF"); // 255 (hex inferred)
Number.parseInt("0b1010"); // 0 ('b' stops parsing in base 10)
Number.parseInt("0b1010", 2); // 10 (explicit radix saves the day)
Numeric separators and BigInt suffix aren’t accepted
Underscore separators ("123_456"
) aren’t valid digits for any radix, so parsing stops before the underscore. Strings with a trailing n
(BigInt literal notation) also aren’t valid for parseInt
; the n
stops parsing, and you may lose precision if the preceding digits are huge.
Number.parseInt("123_456", 10); // 123
Number.parseInt("900719925474099267n"); // 900719925474099300 (rounded)
The classic map(parseInt)
gotcha
Array.prototype.map
calls your callback with (element, index)
. Number.parseInt
takes (string, radix)
. If you hand parseInt
directly to map
, that index becomes the radix on iterations 1, 2, … resulting in puzzling NaN
s. The fix is to pass a wrapper (or a bound radix). Both the map
callback shape and parseInt
’s signature explain the behavior.
["10", "11", "12"].map(Number.parseInt);
// [10, NaN, NaN] ← radices are 0, 1, 2
["10", "11", "12"].map(s => Number.parseInt(s, 10));
// [10, 11, 12] ← explicit radix
Practical recipes
If you’re sanitizing user input that may include units, prefixes, or stray spaces, Number.parseInt
is a forgiving first pass—as long as you pin the radix. If you need strict validation, also check that the entire string was consumed by comparing back to a canonical re-encoding or by using a targeted regexp. The behaviors shown below—trimming, stopping at non-digits, accepting only valid digits for the radix—are guaranteed by the spec and reference docs.
// Trim and parse base-10 quantity from things like " 250kg"
function readUnits(s) {
const n = Number.parseInt(String(s), 10);
return Number.isNaN(n) ? null : n;
}
readUnits(" 250kg"); // 250
readUnits("kg250"); // null
Under the hood
Per the ECMAScript spec, the global parseInt
function produces an integral Number from the string according to the specified radix, ignores leading whitespace, handles an optional sign, and applies the “10 unless 0x/0X” inference when the radix is missing or coerces to 0. Number.parseInt
is specified to be the same intrinsic as the global parseInt
.
// Same intrinsic:
Number.parseInt === parseInt; // true
References
Source | What it covers |
---|---|
MDN: Number.parseInt() | Signature, coercion to string, radix rules, return value, and examples. |
MDN: parseInt() | Detailed description of parsing behavior, radix inference, non-string inputs, numeric separators, and BigInt notes. |
ECMAScript® 2026: Global parseInt (§19.2.5) | Normative algorithm: integral Number, whitespace/sign handling, radix inference (“10 unless 0x/0X”), and radix 2–36 requirement. |
ECMAScript® 2026: Number.parseInt (§21.1.2.13) | Defines Number.parseInt as the same intrinsic as global parseInt . |
MDN: Number | Safe integer limits, differences between Number() , parseInt() , and parseFloat() , and when precision is lost. |
MDN: Array.prototype.map() | Callback parameter order (element, index, array) that explains the map(parseInt) pitfall. |
MDN: NaN | Understanding NaN results when parsing fails. |