Computers are deterministic machines — the same instructions on the same input always produce the same output. That makes "generate a random number" a strange request to hand a computer, and the way it's actually solved is more interesting than most people assume, especially once you realize not all randomness is created equal.

Most "random" numbers aren't really random

The random number functions built into most programming languages by default are pseudorandom number generators, or PRNGs. They start from a seed value and run it through a mathematical formula that produces a long sequence of numbers which look statistically random — evenly distributed, no obvious pattern — but are, in fact, entirely determined by that starting seed. Feed a PRNG the same seed twice, and you get the exact same sequence twice. This is completely fine for most everyday uses: shuffling a playlist, generating test data, running a simulation, rolling dice in a casual game.

Where pseudorandom falls short

The problem shows up when unpredictability itself is the whole point — most obviously in security contexts. If an attacker can figure out or guess the seed a PRNG used (and older or weaker PRNGs have been broken exactly this way), they can reproduce the entire sequence of "random" numbers that came from it. That's catastrophic if those numbers were being used to generate a password, an encryption key, or a session token, because it means the attacker didn't need to guess the password at all — they only needed to guess the seed, which is a much smaller and often easier problem.

Cryptographically secure random number generators (CSPRNGs)

This is why security-sensitive randomness uses a different category of generator entirely: a CSPRNG. Instead of a mathematical formula alone, these pull entropy from unpredictable physical sources the operating system collects in the background — things like precise timing jitter between hardware interrupts, mouse movement, disk I/O timing, and other noise that's genuinely difficult for an outside attacker to observe or reproduce. Modern browsers and operating systems expose this through APIs like crypto.getRandomValues() in JavaScript, which is what a properly built password generator should be using instead of the plain Math.random() function.

Why this distinction matters for you specifically

If you've ever used an online password generator and wondered whether it's actually safe, this is the exact question to ask: is it using a cryptographic random source, or a basic pseudorandom one? A generator built on Math.random() can produce output that looks perfectly random to a human eye while still being far more predictable to a determined attacker than a 16-character password should be. The difference is invisible in the output itself — you can't tell which kind of randomness produced a given string just by looking at it — which is exactly why it matters what's happening under the hood, not just what the result looks like.

True randomness vs. "random enough"

Even CSPRNGs are technically still pseudorandom in a strict sense — genuinely uncaused randomness, sourced from something like quantum effects, exists but is rarely necessary or practical for everyday software. What matters practically is whether the randomness is unpredictable enough that no realistic attacker, with realistic computing resources, could feasibly reconstruct it. That's the bar CSPRNGs are specifically designed to clear.

A simple way to see the difference yourself

Here's a thought experiment that makes the PRNG-versus-CSPRNG distinction concrete. Imagine a basic pseudorandom generator seeded with the exact millisecond your computer's clock read when a program started. If an attacker knows roughly when that program launched — say, within a one-second window from a server log timestamp — they don't need to guess among trillions of possibilities; they only need to try roughly a thousand candidate seeds (one per millisecond in that window) and check which one reproduces the output they observed. What looked like an astronomically large random space collapses into a search an ordinary laptop can finish in well under a second. This exact class of weakness has shown up in real software over the years, including, notably, in early versions of some cryptographic libraries that seeded their randomness from timestamps alone.

A common myth: random doesn't mean "evenly spread out"

People often misjudge what genuine randomness should look like, expecting it to avoid repetition or clustering — the same instinct behind the gambler's fallacy, where someone assumes a coin is "due" for tails after several heads in a row. True randomness has no memory of what came before, so short streaks, repeated digits, or uneven-looking clusters are entirely normal and expected, not a sign that something is broken. This matters practically: if you ever test a random number generator by eyeballing its output and it looks "too patterned" to you, that instinct isn't a reliable way to judge quality — proper statistical randomness tests exist for exactly this reason, because human intuition about what randomness should look like is often wrong.

Try it yourself

Our Random Number Generator and Password Generator both run entirely in your browser using the Web Crypto API's cryptographically secure random source, and nothing you generate is ever transmitted or stored anywhere.

This article is for general informational purposes and is not a substitute for a professional security audit of any system you build.

Related reading