Converting a string to an integer (Number.parseInt)

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 NaNs. 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

SourceWhat 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: NumberSafe 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: NaNUnderstanding NaN results when parsing fails.