Guides

True Randomness vs Pseudorandomness: What a Computer Is Actually Doing

By the Laborilo team. Last updated August 20, 2026.

Building a raffle picker, a game, or a token generator and reaching for Math.random() raises an uncomfortable question: is this actually random enough, or could someone with the right knowledge predict every result? The honest answer depends entirely on what's at stake. A computer rolling a virtual die looks random. Underneath, it's usually running a completely deterministic formula. And whether that's a problem depends entirely on what the randomness is being used for.

Most "random" numbers are just a hidden formula

A typical pseudorandom number generator (PRNG), including JavaScript's plain Math.random(), produces its sequence from a deterministic algorithm seeded by some starting value. Feed it the same seed twice and it produces the exact same sequence twice, which means the output is, in principle, fully predictable to anyone who knows or can guess the seed and algorithm. That's a real limitation for anything security-sensitive, even though the output looks statistically random to a casual observer.

Cryptographically secure randomness is a different, stricter design

A cryptographically secure PRNG (CSPRNG). Like the Web Crypto API's crypto.getRandomValues, which is what a properly-built random generator tool should use. Is specifically engineered so that knowing part of the output sequence gives no practical advantage in predicting the rest. It's typically seeded from real hardware entropy sources: precise timing of mouse movement, disk I/O, thermal sensor noise, or a dedicated hardware random-number circuit built into modern CPUs (like Intel's RDRAND).

Genuinely physical randomness sources

Some systems go further and source randomness from physical, not computational, unpredictability. Atmospheric radio noise (the actual method random.org uses), or radioactive decay timing in specialized hardware devices. These aren't PRNGs at all; they're measuring an inherently unpredictable physical process directly, rather than computing a sequence from a formula.

This is the point where "is Math.random() good enough" actually has a concrete answer instead of a vague one. A raffle winner, a session token, or a password-reset code is exactly the kind of case where predictability is the whole risk: if the seed or algorithm is guessable, someone doesn't need to hack anything, they just need to predict the next output. A dice roll in a single-player game has no such attacker, so the same "weak" PRNG that would be a real problem in one case is completely irrelevant in the other.

A real case where the distinction mattered

In 1995, security researchers Ian Goldberg and David Wagner discovered that early versions of Netscape's browser seeded its supposedly-random SSL encryption keys using predictable values. Things like the time of day and process ID. Rather than genuine entropy. Because the seed was guessable, the "random" encryption keys turned out to be crackable in practice, a well-documented real-world case showing that output which merely looks random is not the same guarantee as output that's actually unpredictable to an attacker.

What to actually do about it

If the goal is anything protecting money, access, or fairness that could be challenged, a raffle winner, a security token, a password-reset code, use a CSPRNG (the Web Crypto API's crypto.getRandomValues) and never plain Math.random(). If the goal is a casual game, a shuffle, or a dice roll with no attacker who benefits from predicting the outcome, Math.random() is fine; there's nothing at stake if it were technically predictable. And if there's any doubt about which category something falls into, the safer default is to treat it like the first case: the cost of using a CSPRNG unnecessarily is basically nothing, while the cost of using a weak PRNG where it mattered is the whole point of the Netscape case above.

Roll dice, flip a coin, or pick randomly with the random generator, built on the Web Crypto API.