Random Number Generator

Every value equally likely — and a distribution table to prove it.

Runs locally

Set a range and press Generate

Runs entirely in your browser — open DevTools and check the Network tab

Pick a range, choose how many numbers you want, and generate. What separates a correct generator from a plausible-looking one is not the interface but two details underneath: where the randomness comes from, and how it gets folded into your range. Most online generators get the second part wrong in a way that is invisible unless you go looking for it.

Modulo bias, and why almost every online generator has it

The standard one-liner for a random integer is Math.floor(Math.random() * n). It looks unimpeachable and it is subtly wrong. The underlying source produces values from a fixed pool, and that pool size is essentially never an exact multiple of n. When you fold the pool onto n outcomes, the first few outcomes receive one extra slot each, so they come up slightly more often than the rest. That is modulo bias.

How much it matters depends on how close n gets to the size of the pool. For a range of six it is far below anything you could ever notice. For ranges that occupy a meaningful fraction of the source’s span it becomes measurable, and the numbers at the low end of your range are the ones that win.

The fix is rejection sampling, and it is what this page does. Before folding, we compute the largest value that divides evenly by the size of your range. Anything at or above that boundary gets thrown away and redrawn. The discarded region is tiny, and what remains partitions perfectly — so every value in your range has exactly the same probability, not approximately the same.

Check the spread yourself

A claim about probability that you cannot test is not worth much, so this page keeps every number it draws for the current range and shows you where they landed. The range is split into equal bands, and each band should hold roughly the same count. The panel also tells you the size of the wobble you should expect, because a table of counts is useless without knowing how much variation is normal.

What you are looking for is not perfectly level bands — that would be a red flag rather than a reassurance. You are looking for the absence of a specific pattern: the lowest bands running consistently high, throw after throw. That is the fingerprint of modulo bias, and it is exactly what the naive one-liner produces.

Change the range and the running statistics start over from zero. That is intentional. Pooling draws from one to six with draws from one to a hundred would produce a distribution table that describes nothing at all, and a statistic that describes nothing is worse than no statistic, because it looks like evidence.

Drawing without repeats, and where it gets subtle

With no-repeats switched on, the generator draws without replacement: once a value comes out it cannot come out again. This is what you want for a raffle, for assigning positions, or for picking lottery numbers, and it is a genuinely different operation from drawing several independent numbers.

It also imposes a hard limit that a lot of tools handle badly. If you ask for fifty distinct numbers between one and ten, there is no answer — and the honest response is to say so rather than to loop forever, silently return duplicates, or quietly hand back ten numbers. This page tells you the range only holds ten and stops.

Underneath, two strategies are used depending on the shape of the request. When you want a small handful from a wide range, values are drawn and repeats rejected. When you want a large share of a narrow range, a partial Fisher–Yates shuffle is used instead, because rejection would spend most of its time redrawing values it has already seen. Both are uniform over the set of possible results; the choice is about speed, not fairness.

Why this should not run on a server

Randomness is one of the few things a browser is unambiguously better placed to provide than a server. crypto.getRandomValues reaches your own operating system’s entropy pool, which is seeded from hardware on your own machine. Routing the request through somebody else’s computer adds a network round trip, a log entry, and a party who knows what you drew — while making the result no more random.

For anything with a stake attached, that log entry is the part to think about. If a draw decides who wins something, the fact that a third party saw the result before you did is a property worth avoiding. Here there is no request at all: open the Network tab in developer tools and generate as much as you like, and the list stays empty.

Frequently asked questions

What is modulo bias in one sentence?

When a random source’s pool of values cannot be divided evenly by the size of your range, the first few values in the range get one extra chance each, so they come up more often. Rejection sampling removes the uneven remainder before folding, which eliminates the bias entirely.

Are the numbers cryptographically secure?

The source is: crypto.getRandomValues is backed by your operating system’s CSPRNG. Combined with rejection sampling there is no bias introduced afterwards. Note that a number you display on screen is not a secret — if you need one, use the password generator, which never shows a history.

Why did my statistics reset?

Because you changed the range. Mixing draws from different ranges into one distribution table produces a chart that describes nothing while looking like evidence, so the tally starts over whenever the range changes.

Can I use this to pick lottery numbers?

Yes — set the range to match your game and switch on no-repeats, since lottery draws are without replacement. It will not improve your odds. Every combination is equally likely, which is exactly why no method of choosing can be better than any other.

What is the largest range I can use?

Up to 2^53 values, which is where JavaScript integers stop being exact. Past that point the generator refuses rather than silently returning numbers that skip values, because a generator that quietly cannot produce some of its own outputs is worse than one that says no.

Is anything sent to a server?

No. Every number is produced by your own browser. You can confirm it in the DevTools Network tab, and the site’s Content-Security-Policy restricts connections to its own origin regardless.