Is the wheel really random?
Yes. Every spin takes its result from your browser’s cryptographic random number generator before the animation starts. Nothing is nudged on a server, and nothing is weighted unless you set the odds yourself.
const MAX = 2 ** 32
function randomInt(n) {
// drop the uneven tail so every value of n is equally likely
const limit = MAX - (MAX % n)
let value
do {
value = crypto.getRandomValues(new Uint32Array(1))[0]
} while (value >= limit)
// now the modulo is exact
return value % n
}This is randomInt from our shared random module. You can read the full script in your browser’s developer tools, under Sources.
Try it: simulate 10,000 spins
8 equal slices. A fair wheel lands near 1,250 times on each slice, with some natural wobble.
Dashed line: the count a perfectly fair wheel would expect for that slice
Equal mode calls the same randomInt function shown on the left, once per spin, entirely in your browser. The chi-square test adds up how far each bar is from its expected count. A fair generator still lands above the 5% cutoff in about one run out of twenty, so one unusual run is expected; a run that fails every time would not be.
- Running a giveawayShow viewers exactly how the winner is picked before you spin on stream.
- Cold-calling in classStudents argue less about whose turn it is when they know nobody can steer the wheel.
- Settling a group decisionRestaurant, chores or who pays: link this page when someone says the wheel is rigged.
- Checking custom oddsSee why a 30% slice should win about 3 spins in 10, and why short runs wander.
What happens when you press Spin
You press Spin
The page asks your browser for fresh 32-bit random numbers from crypto.getRandomValues, which is seeded by the operating system’s secure random source.
The stopping point is chosen
Those numbers set how many turns the wheel makes and the exact angle it stops at. At that moment the winner is already fixed: it is whichever slice will sit under the pointer.
Then it animates
The spin, the easing and the ticking sound are cosmetic. Watching longer or spinning on a faster device cannot change where the wheel was already told to stop.
Nothing leaves your device
The pick is made in your browser. Your entries are not sent to our server to decide a result, so there is no server-side switch anyone could flip.
Six things that keep every pick fair
Why plain modulo is slightly unfair, and how rejection sampling fixes it
A random generator hands out whole numbers in a fixed range. The browser gives 32-bit numbers, so 4,294,967,296 possible values. The obvious way to turn that into a choice between n entries is value % n, the remainder after dividing by n. The catch: unless n divides 2 to the 32nd exactly, a few remainders come up one extra time.
It is easiest to see with a tiny generator that only makes the numbers 0 to 7 and a choice between 3 entries. The table shows what happens.
| Method | Entry 1 | Entry 2 | Entry 3 |
|---|---|---|---|
| Plain modulo, values 0 to 7 | 0, 3, 6: 3 in 8 | 1, 4, 7: 3 in 8 | 2, 5: only 2 in 8 |
| Rejection sampling, values 6 and 7 thrown away | 0, 3: 2 in 6 | 1, 4: 2 in 6 | 2, 5: 2 in 6 |
Our randomInt computes limit = 2 to the 32nd minus the leftover, rejects any value at or above that limit and draws again. With 32-bit numbers the bias it removes is tiny, under one part in a hundred million for a class-sized list, and a redraw is almost never needed, but the result is exact rather than nearly right.
How the wheel turns a random number into a winner
The spinning wheel does not pick a list index and then pretend to spin. It picks a physical stopping angle: a random number of extra turns between five and eight plus a random final angle, both from crypto.getRandomValues. Each slice owns a share of the circle, so its chance of landing under the pointer is exactly its share of 360 degrees, to within about one part in four billion.
When you give entries custom percentages, the wheel redraws the slices so each one covers that percentage of the circle, and the percentages must add up to 100 before you can spin. A 50% slice is half the wheel and wins about half the spins. Tools that pick from a list rather than a wheel use weightedIndex, which draws a random point along the total weight and walks along the entries until it falls inside one.
- Where the wheel happens to be resting before a spin does not matter, because the final angle is uniform whatever the start.
- Spin speed and duration only stretch the animation; the angle was set before the first frame.
- Removing a winner redraws the wheel, so the circle is shared out among the entries that are left.
Streaks are normal: what true randomness looks like
The most common complaint about any random picker is that the same name came up twice. Fair randomness has no memory, so repeats are not just possible but expected. The chance that the next spin repeats the last winner is simply 1 divided by the number of entries.
| Entries on the wheel | Same winner twice in a row | At least one back-to-back repeat in 20 spins |
|---|---|---|
| 2 | 50% | almost certain |
| 4 | 25% | about 99.6% |
| 8 | 12.5% | about 92% |
| 12 | 8.3% | about 81% |
| 30 | 3.3% | about 47.5% |
If you need everyone to get a turn before anyone repeats, that is a no-repeat draw, not a fairer one. Use Remove and spin again on the name picker, or shuffle the whole list once with the list randomizer.
Where Math.random still appears, and why it does not matter
Math.random is fine for decoration, so a few animations use it: the slight tilt of rolled dice, the wobble of racing marbles and the scrambling digits before a number settles. In each case the result itself has already been drawn with the cryptographic generator, and the decoration is kept small enough that it cannot change the visible order.
The shared random module only falls back to Math.random if the browser has no Web Crypto at all, which today means very old browsers. Every current version of Chrome, Safari, Firefox and Edge supports crypto.getRandomValues.
Frequently asked questions
Is a random picker wheel really random?
Ours is. Each spin uses crypto.getRandomValues, the browser’s cryptographically secure generator, to choose where the wheel stops before the animation begins. Every slice wins in proportion to its size, and equal slices are equally likely.
Can the site owner or the person spinning rig the result?
Nothing on our server decides or changes a spin, because the pick happens in your browser. The person spinning cannot steer it either: clicking at a certain moment or holding the button does not affect the random stopping angle. You can inspect the code in your browser’s developer tools.
Why did the same name win twice in a row?
Because randomness has no memory. With 8 entries the same one wins twice in a row 12.5% of the time, and over 20 spins at least one back-to-back repeat happens about 92% of the time. If you want no repeats, remove each winner after it is picked.
Does a longer or faster spin change the odds?
No. The stopping angle is chosen the instant you press Spin. Duration, speed and easing only change how the motion looks, not where it ends.
How do custom probabilities on the wheel work?
Give an entry a percentage and its slice is drawn to cover that share of the circle. The percentages need to add up to 100. An entry set to 30% wins about 3 spins in 10 over the long run, though short runs will wander above and below that.
What do the chi-square number and the verdict in the simulator mean?
Chi-square adds up how far each observed count is from the expected count, scaled by the expected count. If it stays below the 5% cutoff for that number of slices, the run is consistent with a fair generator. A fair generator still fails about one run in twenty, so try a few runs before drawing conclusions.
Is Math.random used to pick winners?
No. Math.random is only used for visual touches such as dice tilt or marble wobble, after the result is already drawn. Results come from crypto.getRandomValues, with Math.random only as a fallback in very old browsers that lack Web Crypto.