jsondecode.com logo

Fix: JSON Number Precision

JavaScript parses all JSON numbers as float64. Integers larger than Number.MAX_SAFE_INTEGER (9007199254740991) are silently rounded — no error, just wrong data. This affects Twitter/X IDs, database snowflake IDs, and any 64-bit integer from a server.

The Precision Loss in Action

// Twitter-style ID — 19 digits, exceeds MAX_SAFE_INTEGER
const json = '{"id": 1234567890123456789}';

const parsed = JSON.parse(json);
console.log(parsed.id);
// => 1234567890123456800   ← WRONG — last digits changed!

// Verify the problem
console.log(Number.MAX_SAFE_INTEGER);
// => 9007199254740991

console.log(1234567890123456789 > Number.MAX_SAFE_INTEGER);
// => true  → precision loss is guaranteed

Float64 Number Range Reference

ConstantValueMeaning
Number.MAX_SAFE_INTEGER9007199254740991Largest exact integer (2^53 − 1)
Number.MIN_SAFE_INTEGER-9007199254740991Smallest exact integer (−2^53 + 1)
Number.MAX_VALUE~1.8 × 10^308Largest finite float64
Number.EPSILON~2.2 × 10^-16Smallest difference between adjacent floats
BigInt maxNo limitArbitrary precision integer (not JSON-native)

Solutions

Solution 1 — Use Strings for Large IDs (Recommended)

The simplest and most portable fix: serialize large integers as JSON strings. All clients receive the exact digits regardless of their number type.

Lossy (number)

{"id": 1234567890123456789}

Exact (string)

{"id": "1234567890123456789"}

Solution 2 — BigInt Reviver

If you receive JSON you cannot change, parse numbers as strings first then convert to BigInt:

// Replace large integers with quoted strings before parsing
function parseWithBigInt(jsonString: string) {
  // Match integers with more than 15 digits (safely over MAX_SAFE_INTEGER)
  const safe = jsonString.replace(
    /:\s*(-?\d{16,})/g,
    ': "$1"'
  );
  return JSON.parse(safe, (key, val) => {
    if (typeof val === "string" && /^-?\d{16,}$/.test(val)) {
      return BigInt(val);
    }
    return val;
  });
}

const result = parseWithBigInt('{"id": 1234567890123456789}');
console.log(result.id);         // 1234567890123456789n (BigInt, exact)
console.log(typeof result.id);  // "bigint"

Solution 3 — json-bigint Library

The json-bigint npm package is a drop-in replacement that handles large integers automatically:

import JSONbig from "json-bigint";

const parsed = JSONbig.parse('{"id": 1234567890123456789}');
console.log(parsed.id.toString());
// => "1234567890123456789"  — exact

Inspect Your JSON Below

Paste JSON containing large numbers to see how JavaScript parses them.

Input JSON
Formatted Output
Formatted JSON will appear here

Frequently Asked Questions

Why does JSON.parse() change my large number?

JavaScript uses IEEE 754 double-precision (float64) for all numbers. It can only represent integers exactly up to Number.MAX_SAFE_INTEGER (9007199254740991, or 2^53 - 1). Numbers larger than this are silently rounded to the nearest representable float64 value. The JSON text is syntactically valid, but the parsed JavaScript number is imprecise.

What is Number.MAX_SAFE_INTEGER?

Number.MAX_SAFE_INTEGER is 9007199254740991 (2^53 - 1). Any integer within the range -(2^53 - 1) to (2^53 - 1) is represented exactly in float64. Integers outside this range may be rounded. For example, 9007199254740993 rounds to 9007199254740992 — a difference of 1 that can corrupt database IDs.

How should APIs return large integer IDs?

The safest approach is to return large integers as JSON strings rather than numbers: {"id": "1234567890123456789"}. This is what Twitter / X does — their API returns both a numeric id field and a string id_str field. The string representation is always exact regardless of the client language.

Can I use BigInt with JSON.parse()?

Standard JSON.parse() does not support BigInt natively. You can write a custom reviver that converts large number strings to BigInt, or use a library like json-bigint which patches JSON parsing to use BigInt for numbers exceeding MAX_SAFE_INTEGER. Note: JSON.stringify() also does not serialize BigInt by default — you need a replacer.

Does float precision affect decimal numbers too?

Yes. Float64 cannot exactly represent many decimal fractions. The classic example is 0.1 + 0.2 = 0.30000000000000004 in JavaScript. For financial calculations, store amounts as integers (cents, not dollars) or use a decimal library. JSON itself has no concept of decimal precision — all numbers are float64 once parsed by JavaScript.

If jsondecode.com saved you time, share it with your team

Free forever. No ads. No sign-up. Help other developers find it.