How Our Random Number Generator Works

A short technical explanation of the algorithm, statistical properties, and why it matters for fair draws.

Summary

Every number on onlinerandomnumber.com is drawn from the browser's Web Crypto API — specifically crypto.getRandomValues(), a cryptographically secure pseudo-random number generator (CSPRNG). We apply rejection sampling to convert 32-bit random words into uniform integers in your chosen range, eliminating the modulo bias that affects naive implementations. Each integer in your range has exactly equal probability.

Why Not Math.random()?

JavaScript's Math.random() is a pseudo-random generator designed for speed, not unpredictability. Its internal state can be partially reconstructed from observed outputs, which means a motivated adversary could predict future values. For games and trivial decisions this is fine. For giveaways, raffles, and anywhere the result has real consequences, it is not.

crypto.getRandomValues() uses the operating system's secure random source (e.g., /dev/urandom on Linux, BCryptGenRandom on Windows). Its output is statistically indistinguishable from true random and computationally infeasible to predict.

PropertyMath.random()crypto.getRandomValues()
PredictabilityPartially predictableComputationally infeasible
Statistical qualityGoodExcellent
SpeedVery fastFast
Suitable for fair draws?MarginalYes
Suitable for cryptographic keys?NoYes

Modulo Bias and How We Avoid It

The obvious way to turn a random 32-bit integer into a number in [min, max] is:

// BAD: introduces modulo bias
const range = max - min + 1;
const x = crypto.getRandomValues(new Uint32Array(1))[0];
return min + (x % range);

If range does not evenly divide 2³², the lower values in the range are slightly more likely than the upper values. For range = 10, the bias is negligible (~10⁻⁹). For larger ranges or higher-stakes draws, it matters.

We use rejection sampling: draw a 32-bit random word, discard it if it falls outside the largest multiple of range below 2³², and retry. This guarantees a perfectly uniform distribution.

function secureRandomInt(min, max) {
    const range = max - min + 1;
    const maxUint32 = 0xFFFFFFFF;
    const limit = maxUint32 - (maxUint32 % range) - 1;
    const buf = new Uint32Array(1);
    let x;
    do {
        crypto.getRandomValues(buf);
        x = buf[0];
    } while (x > limit);
    return min + (x % range);
}

Statistical Properties

When to Use True Random Instead

For almost every everyday purpose — giveaways, games, research sampling, naming, team assignment — CSPRNG is the right choice. It is fast, free, and statistically equivalent to true random.

Use a dedicated true-random service when you need:

For these cases, services like RANDOM.ORG (atmospheric noise) or the NIST Randomness Beacon provide certified true-random bits.

Privacy

Random number generation happens entirely in your browser. We never see your ranges or results. Analytics (Google Analytics) track page-level usage only. Shared result URLs encode range and result in the query string; only the person you send the link to can see it.

Try It

Our Other Free Tools
Age Calculator Percentage Calculator Discount Calculator Character Counter