Handling BigInt Precision Loss in JSON.parse (Safe 64-bit Integers)
Prevent 64-bit ID truncation in JavaScript when parsing JSON. Learn why large Twitter/Snowflake IDs mutate beyond Number.MAX_SAFE_INTEGER and how to fix it.
JavaScript represents all numbers as IEEE 754 double-precision floats, capping safe integers at 2^53 - 1 (9,007,199,254,740,991). When an API returns 64-bit integers (such as Discord/Twitter Snowflake IDs or Postgres BIGINTs), native JSON.parse() rounds the lowest bits, mutating database keys unless parsed losslessly as strings or BigInts.
Solve this problem now with our free JSON Formatter & Validator
Try it instantly in your browser — zero tracking, 100% client-side privacy.
Specification & Architecture Reference
| Original Database Value | Native JSON.parse Result | Status |
|---|---|---|
| 9007199254740991 | 9007199254740991 | ✅ Safe (MAX_SAFE_INTEGER) |
| 9007199254740992 | 9007199254740992 | ⚠️ Edge boundary |
| 9007199254740993 | 9007199254740992 | ❌ Truncated / Mutated (-1) |
| 18446744073709551615 | 18446744073709552000 | ❌ Corrupted (+385) |
The 53-Bit Integer Limit in JavaScript
JavaScript engines allocate 64 bits per number conforming to the **IEEE 754** floating-point specification: - 1 sign bit - 11 exponent bits - 52 fraction (mantissa) bits
Because the mantissa is 52 bits (plus 1 implied leading bit), JavaScript can only represent integers up to **$2^{53} - 1$** (`Number.MAX_SAFE_INTEGER = 9,007,199,254,740,991`) with exact precision.
When your frontend receives modern 64-bit IDs—such as Discord/Twitter Snowflake IDs, Stripe event IDs, or PostgreSQL `BIGINT` primary keys—they exceed this value.
const raw = '{"id": 18446744073709551615}';
const parsed = JSON.parse(raw);
console.log(parsed.id);
// Outputs: 18446744073709552000 (Data corrupted!)Why JSON.parse Reviver Functions Fail Developers often attempt to intercept large numbers using the `reviver` argument in `JSON.parse(str, reviver)`. However, this is ineffective because the V8 engine coerces the raw string token into an IEEE 754 float **before** invoking the reviver callback. The precision is already lost before your function runs.
How to Prevent Corruption 1. **String Serialization on the Backend:** Configure your backend ORM (e.g., Prisma, TypeORM, SQLAlchemy) to serialize 64-bit numeric columns as strings (`"18446744073709551615"`). 2. **Lossless Token Replacement:** If you cannot modify the backend response, run a regex pre-pass on the raw HTTP response text:
function preserveBigInts(jsonText) {
return jsonText.replace(/:\s*(-?\d{16,})/g, ':"$1"');
}Verify your payloads using Mickytool's **JSON Formatter & Validator** to inspect raw tokens and detect precision truncation issues before they reach your database.
Solve this problem now with our free JSON Formatter & Validator
Execute this workflow immediately without saving data on remote servers.
Frequently Asked Questions
What is Number.MAX_SAFE_INTEGER in JavaScript?
Number.MAX_SAFE_INTEGER is 9,007,199,254,740,991 (2^53 - 1). Any integer larger than this cannot be uniquely represented in standard JavaScript numbers.
Can native JSON.stringify serialize BigInt objects?
No. JSON.stringify() throws a TypeError: Do not know how to serialize a BigInt. You must add BigInt.prototype.toJSON = function() { return this.toString(); } or convert them manually.