How Our Randomness Works
How our randomness works, in one line: every tool on RandomVal draws from your browser's cryptographic random number generator and turns each value into a pick with an unbiased method. This page shows the code step by step, with a test run of 60,000 shuffles.
Sources: MDN, W3C Web Crypto Updated
The source: crypto.getRandomValues()
Browsers ship two random number generators. Math.random() is the old, fast one, meant for things like animation.
crypto.getRandomValues() is part of the Web Cryptography API and is the one browsers use when security depends on unpredictability. It is a cryptographically secure pseudo-random number generator (CSPRNG), seeded by the operating system.
Every tool on RandomVal uses the second one. A draw asks for one 32-bit unsigned integer, a whole number from 0 to 4,294,967,295:
const buffer = new Uint32Array(1);
crypto.getRandomValues(buffer);
const value = buffer[0]; // 0 … 4,294,967,295
That is the only source of randomness on the site. Nothing is fetched from a server, and the time of day, your mouse movements and earlier results play no part in our code.
How to turn a random value into one of n options
Picking one of n options means turning that 32-bit value into a whole number from 0 to n − 1 without favouring any of them. The obvious shortcut, taking the remainder after dividing by n, is slightly unfair whenever 4,294,967,296 is not a multiple of n: the low remainders get one more chance than the high ones.
The tools, from the random number generator to the dice roller, use rejection sampling instead:
- Work out the largest multiple of n that fits into 4,294,967,296. Call it the limit.
- Draw a 32-bit value. If it is at or above the limit, throw it away and draw again.
- Otherwise take the remainder after dividing by n. That is the pick.
function below(n) {
const limit = 4294967296 - (4294967296 % n);
let x;
do { x = nextUint32(); } while (x >= limit);
return x % n;
}
Every remainder is now backed by exactly the same number of possible draws, so every option has a chance of exactly 1 in n.
Worked example: a six-sided die
For n = 6, the remainder of 4,294,967,296 ÷ 6 is 4, so the limit is 4,294,967,292. The four values from 4,294,967,292 to 4,294,967,295 are rejected, which happens about once in a billion draws.
The remaining values fall into six groups of 715,827,882 each, one group per face of the die. With 32-bit values the bias of the shortcut would be far too small to notice; with a source of only 256 values it is plain to see.
Ranges wider than 4,294,967,296 values, which only the number tools allow, use the same method with 53 random bits taken from two draws.
How the Fisher–Yates shuffle makes every order equally likely
Team splits, random orders and no-repeat draws all rest on a shuffle. The team generator, the random order generator and the wheel's shuffle button use the Fisher–Yates method:
for (let i = list.length - 1; i > 0; i--) {
const j = below(i + 1); // unbiased position from 0 to i
[list[i], list[j]] = [list[j], list[i]];
}
Working from the end of the list, each item swaps places with a randomly chosen item at or before its own position. Each of the possible orders, 24 for four items and 3,628,800 for ten, comes out with the same probability.
Two tempting shortcuts do not have that property. Sorting a list with a random comparison, which some of the older tools on this site used, has been removed. Swapping every item with any position in the list looks almost the same as Fisher–Yates, but the chart shows what it does to three items.
How the picker wheel decides before it spins
On the picker wheel the animation does not decide anything. The order of events is:
- Draw the winner. The shares of all entries are added up (one share each, unless you set weights). One unbiased whole number below that total is drawn, and the entry whose shares contain that number wins.
- Draw the resting point. A second random value picks a spot inside the winner's slice, away from its edges, so that the pointer does not stop on a line.
- Animate. The wheel makes five to seven turns and slows to a stop at that spot. The number of turns is drawn at random too, but it only changes how long you wait.
Because the result exists before the wheel moves, a slow phone, a dropped frame or reduced-motion settings cannot change who wins.
How numbers without repeats are drawn
When you ask the number generator for no repeats, it behaves like a bag of numbered balls. For ordinary ranges it lists every value in the range and draws the requested quantity with a partial Fisher–Yates shuffle.
For very wide ranges, where listing every value would be wasteful, it draws numbers one at a time and redraws whenever a number has already come up. Both ways give every possible set the same chance.
How yes-or-no and percentage chances are drawn
A few tools need a chance rather than a pick, for example “add an apartment number to one address in five”. Where the chance is a simple fraction, the code draws a whole number: one in five means drawing from 0 to 4 and acting on 0.
Some older generators compare a random fraction between 0 and 1 with a threshold such as 0.5. That fraction is a 32-bit draw divided by 4,294,967,296, which is accurate to better than one part in four billion. The coin flip draws a whole number, 0 or 1, instead.
What the automated tests check
The picking logic lives in one small engine file that is shared by the wheel, the number generator, the team generator and the test data tools. It takes its random source as an input: on the site that is crypto.getRandomValues(), in the automated tests a fixed sequence of numbers.
With a fixed sequence the tests can check exact outcomes: that rejected values are redrawn, that both ends of a range are reachable, that a no-repeat draw never repeats, that team sizes differ by at most one, and that the wheel's pointer comes to rest inside the slice that was drawn.
The charts on this page and on the tool pages come from the same engine, fed by Node's Web Crypto generator each time the site is built. Each shows one run, so its numbers change slightly from build to build.
The older list-based generators, such as the word, place and name tools, do not go through that engine. They call three small helpers in the site's shared script, kitRandomInt, kitShuffle and kitPick, which apply the same rejection sampling and the same shuffle to the same source.
What RandomVal does not claim
- Not “true” random. The numbers are produced by an algorithm, seeded with entropy that your operating system collects. We describe them as cryptographically secure pseudo-random numbers.
- Not certified. The site is not audited by a regulator or testing lab and must not be used for gambling, regulated lotteries or any draw that the law requires to be certified.
- Not verifiable after the fact. No record of a draw is kept anywhere but on your screen and, for some tools, in your browser's history list.
- Only as good as your browser. The quality of the generator is the browser's and operating system's responsibility. All current browsers implement it; a browser too old to have it cannot run the tools at all.
Questions about RandomVal's randomness
Is this “true” randomness?
No, and we do not call it that. The numbers come from a cryptographically secure pseudo-random generator in your browser, seeded by your operating system, not measured from a physical process such as atmospheric noise.
For picking names, rolling dice and drawing raffle numbers the difference has no practical effect: the output cannot be predicted and shows no pattern that favours any outcome.
Can you influence or predict a result?
No. The draw happens in your browser, on your device. We do not supply the random numbers, we do not see them, and there is no setting on our side that could favour an entry.
Can I prove to others that a draw was fair?
Not with this site alone. The draw runs on your device and leaves no public record, so viewers have to trust the person sharing their screen. If you need a draw that third parties can verify afterwards, use a service that publishes signed, timestamped records of its draws.
Do any tools still use Math.random()?
No. Math.random() is fast but its output can be predictable and its quality differs between browsers, so every tool was moved to the Web Crypto generator, including decorative effects such as confetti.
Why did the same result come up twice in a row?
Because draws are independent. A fair generator repeats itself exactly as often as chance says it should: on a wheel with four entries, the previous winner wins again one time in four.
Sources
- MDN: Crypto.getRandomValues() — what the function returns and where browsers get the seed (checked October 12, 2026)
- W3C: Web Cryptography API — the specification that defines getRandomValues (checked October 12, 2026)
- Wikipedia: Fisher–Yates shuffle — the shuffle algorithm and why the naive version is biased (checked October 16, 2026)