How to Shuffle a Random List Fairly: A Practical Guide
Shuffle a list, pick winners, or split into teams with verifiably fair randomness. How Fisher-Yates works, why naive shuffles are biased, and real use cases.
How to Shuffle a Random List Fairly: A Practical Guide
Most "random name picker" pages do something subtly broken. They take your list, call Math.random(), and either sort by a random comparator or pull Math.floor(Math.random() * n). Both look fine. Both are biased. If you are drawing a raffle winner on stream or sampling support tickets for an audit, that bias is the difference between "fair" and "fair-looking."
This guide walks through how to shuffle a list correctly, what Fisher-Yates actually guarantees, and the handful of jobs where a proper list randomizer earns its place over a quick script or a coin flip.
One Item Per Line, Then Pick a Mode
The input format is the boring part that trips people up, so I'll get it out of the way first: one item per line. Names, raffle tickets, restaurant options, ticket IDs — whatever you have, each entry goes on its own line. Paste a spreadsheet column straight in and it lines up automatically. Commas don't count as separators, so alice, bob, carol on a single line is read as one long item, not three.
From there you choose what to do with the list:
- Shuffle reorders the whole list into a fair random sequence.
- Pick N draws a fixed number of items, with or without repeats.
- Split into groups deals the list into K evenly-sized buckets after a shuffle.
- Draw winner pulls a single item, with an optional reveal animation for live use.
Shuffle, group, and single-winner draw never repeat an item — each line appears exactly once. Only Pick N can repeat, and only when you explicitly turn on "allow repeats."
What Fisher-Yates Actually Guarantees
Here is the concrete claim worth internalizing: the Fisher-Yates shuffle gives every one of the N! possible orderings exactly equal probability. Not approximately equal. Exactly. For a list of 5 names there are 120 possible orders, and a correct shuffle lands on each with probability 1/120.
The algorithm walks the list from the last index down to the first. At each position i it picks a random index j from 0 through i and swaps the two. That's it. The reason it's unbiased is that every element has an equal chance of ending up in every slot, and the math works out cleanly to N! equally-likely results — no permutation is quietly more likely than another.
The naive alternative — array.sort(() => Math.random() - 0.5) — feels like it should be random, but it is provably biased. Comparison sorts assume a consistent ordering, and a random comparator violates that, so some permutations come up far more often than others depending on the sort implementation. That's the trap most picker sites fall into.
There's a second, quieter source of bias: mapping random bytes onto a range. Writing Math.floor(Math.random() * n) for an n that isn't a power of two skews the low indices slightly, because the underlying random space doesn't divide evenly. A correct randomizer uses rejection sampling — it throws away the few values that would fall in the uneven tail and re-rolls — so every index is genuinely equally likely. Toolora's tool drives this from crypto.getRandomValues, the same cryptographically-secure RNG browsers expose for security work, rather than Math.random().
A Worked Example: Pick 3 From a List
Say you're running a giveaway with these entrants:
ava
noah
mia
liam
zoe
kai
Switch to Pick N, set N to 3, leave "allow repeats" off, and run it. You might get:
zoe
ava
kai
Three distinct names, drawn without replacement. Run it again and you'll get a different three — each run re-rolls. If you'd wanted the full list reordered instead, Shuffle would hand back all six lines in a fresh random sequence; the first three of that shuffle are an equally valid "pick 3." Both paths are fair; Pick N just saves you the trim.
If you turn "allow repeats" on, Pick N switches to sampling with replacement, so the same name can come back twice. That's occasionally what you want (weighted-feel draws, Monte Carlo-style sampling) but almost never what you want for winners — which is exactly why repeats default to off.
Real Jobs This Beats a Coin Flip
The first time I reached for a list randomizer in anger was a chore rota. Four flatmates, four weeks of dish duty, and a running argument about who got stuck with the worst week. I pasted the four names, hit Shuffle, and the resulting order was the rota — order 1 took week 1, and so on. The point wasn't speed; it was that nobody could claim I'd nudged it. An unbiased shuffle means no name is more likely to land in any given slot, and that neutrality is the whole value when feelings are involved.
The same shape shows up everywhere once you notice it:
- Live raffles and giveaways. Paste one entrant per line, draw on stream, screen-record the click. Because the draw is rolled at the moment you click rather than baked into a link, the recording is genuine proof.
- Splitting a class into teams. 27 students into 6 groups: choose Split into groups, set K to 6, and the tool deals them round-robin into buckets of 5,5,5,4,4,4 after a fair shuffle.
- Breaking a decision deadlock. Five restaurants and a group chat stuck on "idk, you pick." One draw, done, and no one can say the chooser steered it.
- QA sampling. Exported 800 tickets and need to read a random 25? Pick N with repeats off gives you a proper simple random sample — not "the first 25" or "every 32nd one," both of which can hide systematic bias.
If you find yourself wanting numbers in a range instead of items from a list — dice rolls, lottery numbers, a random integer between bounds — that's a different job; reach for the random number generator and leave the strings behind.
Local Randomness and Honest Share Links
Everything here runs in your browser tab. The Fisher-Yates passes, the crypto.getRandomValues draws, the grouping, the winner selection — all plain JavaScript, no list or name or result ever sent to a server.
The one deliberate subtlety is the share link. Your input list is encoded into the URL so a shareable link reproduces the same starting list. The random result is never baked into the link — it's re-rolled fresh every time anyone runs it. That's intentional: if the winner were stored in the URL, whoever made the link could rig the outcome. So if you want a winner everyone agrees on, draw it once live and screenshot it; don't send a link and assume your friend sees your result. They'll get their own independent draw, which is the point.
A fair shuffle is a small thing that quietly matters. Get the algorithm right, source the randomness honestly, and keep the result off the link — and "let's just randomize it" stops being a place anyone can hide a thumb on the scale.
Made by Toolora · Updated 2026-06-13