Free Random Number Generator

Generate cryptographically random numbers in any range.

A Short History of Computer Randomness

Computers are deterministic machines, which makes "random" a strange thing for them to produce. The history of pseudorandom number generators (PRNGs) on computers begins with John von Neumann's middle-square method in 1946, square the previous number, take the middle digits as the new value, repeat. Von Neumann's own warning at the 1949 RAND symposium was sharper than the method: "Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin." Middle-square has obvious failure modes (it cycles back to zero, has short periods, and embeds patterns the seed can't escape). Lehmer's multiplicative congruential generator (Berkeley 1949, published 1951), x_(n+1) = (a × x_n) mod m: was the first family of PRNGs with reasonable statistical properties; Thomson and Rotenberg (1958) later generalised the family with an additive constant to give the full x_(n+1) = (a × x_n + c) mod m linear congruential generator (LCG). The C standard library's rand() still typically uses an LCG variant. The Mersenne Twister (Matsumoto and Nishimura, 1997-1998) gave us a generator with a period of 219937−1 (a 6,000-digit number) and 623-dimensional equidistribution; it became the default in Python, R, MATLAB, PHP and many other languages. Marsaglia's xorshift family (2003) is much faster and small enough to fit in a hardware register; modern V8 (Chrome's JavaScript engine) uses a xorshift128+ variant for Math.random(). PCG (Permuted Congruential Generator) by Melissa O'Neill (2014) is the current statistical state of the art for non-cryptographic PRNGs, combining LCG-style state advancement with output permutation for excellent statistical properties at low cost.

Cryptographically secure PRNGs (CSPRNGs) are a different beast. The defining property: even if an attacker knows every output the generator has produced, they cannot predict the next output with better than negligible advantage. Linux's getrandom() syscall (added in kernel 3.17, October 2014) and the underlying /dev/urandom use a ChaCha20-based generator seeded by hardware entropy sources (RDRAND, interrupt timing, audio noise). Windows BCryptGenRandom uses an AES-CTR-DRBG construction (NIST SP 800-90A) seeded from multiple entropy sources. macOS / iOS use the arc4random family, originally an RC4-based CSPRNG and rewritten on top of ChaCha20 around 2013. The difference between PRNG and CSPRNG matters enormously: a PRNG is fine for game randomness, A/B test bucketing or simulations; for anything an attacker might try to predict (session tokens, password generation, security IDs), only a CSPRNG is safe.

JavaScript's Two Random APIs

Math.random() is the older, simpler API, returns a floating-point number approximately uniformly distributed in [0, 1). The ECMAScript specification deliberately leaves the underlying algorithm unspecified ("approximately uniform distribution between 0 and 1, exclusive"), and engines have shifted what they use over the years. V8 (Chrome) used a multiply-with-carry generator (MWC1616) for many years, then switched to xorshift128+ in 2015 for better statistical properties. SpiderMonkey (Firefox) and JavaScriptCore (Safari) use similar fast non-cryptographic generators. Math.random() is fast and uniform enough for game mechanics, simulations and any application where unpredictability is not a security requirement. It is not cryptographically secure: the period is implementation-defined, the state can be recovered from a small number of outputs, and the sequence is not safe for password generation or security-sensitive use cases. crypto.getRandomValues() is the Web Crypto API's CSPRNG. It fills a typed array with cryptographically secure random bytes drawn from the operating system's CSPRNG (the same source TLS uses for session keys). Available in all modern browsers since approximately 2014; the maximum buffer size in a single call is 65,536 bytes. The right choice for any random number that matters, token generation, security IDs, password generation, anything an attacker might try to predict.

The Modulo Bias Trap

Generating a uniform integer in a specific range from a CSPRNG is harder than it looks. The naive approach (crypto.getRandomValues(new Uint8Array(1))[0] % 6 for a die roll) produces a biased distribution because 256 doesn't divide evenly by 6. The values 0-3 each occur 43 times in the 0-255 range; the values 4-5 occur 42 times. The bias is small for small ranges but real, and detectable in long runs. The standard fix is rejection sampling: generate a random byte, test whether it falls in the largest multiple of your range that fits (here, 252 = 42 × 6), use it if it does, throw it away and try again if not. The throwaway rate is bounded by (range / next-power-of-2), so for "1-6" you waste about 1.5% of bytes; for "1-1000000" against a 32-bit random int you waste about 0.02%. Every serious random library implements rejection sampling; Math.random()-based Math.floor(Math.random() * (max - min + 1)) + min avoids the bias because Math.random()'s precision is high enough (53 bits of mantissa) that the bias is below human-detectable levels for any reasonable range. This generator uses CSPRNG output with rejection sampling, uniform output across any integer range you request.

Use Cases, and What Level of Randomness Each Needs

RANDOM.ORG and the True-Randomness Distinction

RANDOM.ORG was launched in 1998 by Mads Haahr at Trinity College Dublin and remains the gold standard for "true randomness" online. Where every CSPRNG ultimately derives its bits from algorithmic transformations of a hardware-seeded state (a deterministic process, even if unpredictable to an attacker), RANDOM.ORG measures atmospheric noise from radio receivers and converts the analog noise directly into bits. This makes it a True Random Number Generator (TRNG) rather than a Pseudo-Random Number Generator: the bits come from a physical process that is genuinely non-deterministic, not from a deterministic algorithm. RANDOM.ORG is used by lottery operators, academic researchers running double-blind studies and games where verifiable randomness matters. The trade-off: a network round-trip per request, a daily quota for the free tier, and the philosophical question of whether you trust RANDOM.ORG's claimed entropy source over your local CSPRNG. For most use cases the local CSPRNG is sufficient; for cases where a third party needs to verify randomness independently, RANDOM.ORG provides signed certificates of randomness as a paid service.

Without-Replacement Sampling, The Fisher-Yates Shuffle

When you need N unique numbers from a range (drawing 6 numbers from 1-49 for a lottery, picking 10 winners from 1000 entrants) naive "generate and reject if duplicate" works for small N but degrades sharply as N approaches the range size (the chance of drawing a fresh number drops as the pool shrinks). The standard algorithm is the Fisher-Yates shuffle, originating in Fisher and Yates's 1938 statistical tables and given its modern computer-science form by Donald Knuth in 1969 (sometimes called the Knuth shuffle). The algorithm is dead simple: write the numbers 1 through N into an array; for i from N-1 down to 1, swap element i with a random element between 0 and i (inclusive); the array is now uniformly shuffled. Take the first K elements for K unique random numbers. The crucial detail: the random index must be in [0, i], inclusive: using [0, i-1] gives Sattolo's algorithm (Sandra Sattolo, 1986) instead, which produces uniform cyclic permutations rather than uniform random permutations and is sometimes mistakenly substituted for true Fisher-Yates. For very large ranges where allocating an array of all N values is impractical (e.g. picking 100 unique values from 1-109), reservoir sampling (Vitter, 1985) handles streaming or unbounded inputs in a single pass with bounded memory.

Dice Roll Conventions

Random number generators are dice in disguise. D6 (six-sided die) is the universal boardgame default, range 1-6. D20 (twenty-sided die) is the iconic Dungeons & Dragons die used for ability checks, attack rolls and saving throws, D&D's modifier system means a single D20 roll plus a stat bonus determines the outcome of most actions. D100 (percentile, 1-100) is used for percentile rolls in Call of Cthulhu, Warhammer Roleplay and many crit-chance systems. The notation NdM means "roll N dice with M sides each and sum"; NdM+B adds a bonus. 3d6 rolls three six-sided dice and sums (range 3-18, the classic D&D ability-score range, with a triangular distribution centered on 10-11). For a fair simulation, generating a uniform integer in [1, M] for each die and summing is exactly equivalent to rolling physical dice, the underlying CSPRNG distribution is more uniform than any physical die you could buy. Casinos and regulated gaming use certified RNGs that are tested against statistical batteries (TestU01's BigCrush, NIST SP 800-22) to prove uniformity to gaming regulators; the same standards apply to lottery RNGs.

Seeding and Reproducibility

A subtle but important property of PRNGs: they are deterministic given a seed. Set the seed to a known value, and the sequence of "random" numbers is exactly reproducible. This is invaluable for testing (a unit test that uses random data should set a fixed seed so failures are reproducible) and for verifiable raffles (publish the seed before drawing, then anyone can verify the result). Python's random module has random.seed(value) for this; Java's Random takes a seed in the constructor. JavaScript's Math.random() deliberately does not expose a seeding API (engines treat the seed as internal state) but several pure-JS libraries (seedrandom, pcg-random) provide seeded PRNGs. CSPRNGs are different by design: they don't expose seeding because the entire point is unpredictability. If you need reproducibility, use a PRNG with explicit seeding; if you need security, use a CSPRNG and accept that you cannot reproduce the sequence later.

Privacy: Why Browser-Only Even for Random Numbers

Random numbers themselves rarely contain sensitive information, so why does the browser-only architecture matter? Two reasons. First, when a random number is used as a session token, an idempotency key, an authentication challenge, or any other secret-like value, generating it on a third-party server means that server saw the value before you used it, a small but real exposure. Second, server-side generators that promise "cryptographic randomness" cannot be verified by the user; a buggy or malicious server could return non-random or biased values that look random, and you'd have no way to detect the bias without massive sampling. A browser-only generator runs the same crypto.getRandomValues() call your application would run server-side; the entropy comes from the same operating system source (Linux getrandom(), Windows BCryptGenRandom, macOS); no third party sees the output. You can verify by opening DevTools' Network tab while you click Generate, there are no outbound requests. Take the page offline (airplane mode) after it loads and the generator still works.

Frequently Asked Questions

Are these numbers cryptographically secure?

Yes. The generator uses the Web Crypto API's crypto.getRandomValues() with rejection sampling to produce uniform integers across any range. The entropy comes from the operating system's CSPRNG (Linux getrandom(), Windows BCryptGenRandom, macOS) the same source TLS uses for session keys. Suitable for security-sensitive use cases: lottery picks, session tokens, idempotency keys, password generation.

Why don't I just use Math.random()?

For game mechanics, simulations, A/B test bucketing or anything where unpredictability is not a security requirement, Math.random() is fine (fast, uniform enough, available everywhere. For anything an attacker might try to predict) session tokens, password generation, security IDs, lottery picks, Math.random() is dangerous. The state can be recovered from a small number of outputs, the sequence is reproducible from any starting point, and the period (while large in modern engines) is implementation-defined and not advertised as cryptographic. The cost of switching to crypto.getRandomValues() is essentially zero on modern hardware; default to it whenever the answer matters.

Can I generate without duplicates?

Yes, enable the "Unique only" option. This uses a Fisher-Yates shuffle (the standard algorithm since Fisher and Yates 1938; given its modern computer-science form by Knuth in 1969) to draw N unique values from your range without bias. For small N relative to the range size, the cost is negligible; for N close to the range size, the algorithm still runs in O(N) time. The classic use case is lottery-style draws (6 unique numbers from 1-49) where duplicates would be invalid.

Is there a difference from RANDOM.ORG?

Yes. RANDOM.ORG (Mads Haahr, Trinity College Dublin, 1998) is a True Random Number Generator (TRNG), its bits come from atmospheric noise measured by radio receivers, a genuinely non-deterministic physical process. This generator is a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG), its bits are deterministic given the OS entropy state, but unpredictable to any attacker without access to that state. For most use cases CSPRNG is indistinguishable from TRNG; for cases where a third party needs to verify randomness independently (regulated lottery, scientific double-blind studies), RANDOM.ORG's signed certificates of randomness are the gold standard, at the cost of a network round-trip and a daily quota.

Why might I see "modulo bias" warnings elsewhere?

Because the naive way to map a random byte (0-255) to a die roll (1-6) introduces a small bias: byte % 6 gives values 0-3 about 2.4% more often than values 4-5, because 256 doesn't divide evenly by 6. The fix is rejection sampling: discard bytes ≥ 252 (the largest multiple of 6 ≤ 256) and try again. This generator uses rejection sampling for all integer ranges, so the output is uniform with no detectable bias. The bias matters most for cryptographic applications where statistical attacks on biased output can recover key material; for game mechanics it's invisible.

Are the numbers sent anywhere?

No. Every random number is generated locally in your browser using the Web Crypto API. The generator never makes a network request, verify in DevTools' Network tab while you click Generate, or take the page offline after it loads and confirm the tool still works. Safe for generating session tokens, lottery picks, security IDs or any number where you don't want a third party to have seen the value before you use it.

Related Tools