Random Choice
9 min read

How to Run a Fair Random Draw

When a result matters to people, such as picking a presenter, drawing a prize, or deciding an order, the real question is not just whether it was random but whether it was fair. A pick can look completely random and still quietly favour certain entries if the method behind it is wrong. This guide walks through where bias creeps in and what a draw actually needs before you can call it fair.

Random and fair are different things

Random means the outcome cannot be predicted. Fair means every entry has the intended probability under a stated rule. The two words get used interchangeably, but they describe different properties. A draw can be genuinely unpredictable and still structurally favour one entry, which makes it random but not fair.

Here is a concrete example. Suppose you have a list of 30 people and the rule is: pick a number from 1 to 30, and if that person is absent, move to the next number. Nobody can predict the outcome, yet the person sitting directly after an absentee can be reached two ways, from their own number and from the number before it. Their odds are double everyone else's.

So a fair draw needs two things at once. First, a decent source of randomness. Second, an algorithm that spreads that randomness across the entries without bias. If either part is off, the results drift.

Mistake one: shuffling by sorting

The most copied shuffle on the internet is sort(() => Math.random() - 0.5), and it does not shuffle evenly. Sorting algorithms assume comparisons are consistent: if A came before B once, asking again should give the same answer. A random comparator breaks that assumption every time it is called.

When the assumption breaks, the sort skips comparisons it would otherwise make, and some items simply stay near where they started. Worse, different browsers use different sorting algorithms, so the direction of the bias is not even consistent between them.

With three or four items nobody notices. Past ten, specific positions start favouring specific items in a measurable way. It is fine for a throwaway shuffle and wrong for anything where the order or the winner carries weight.

Mistake two: modulo bias

Cutting a random number down to a smaller range with the remainder operator introduces a subtler bias. Say you get a value from 0 to 255 and take the remainder after dividing by 10 to land on 0 through 9. Dividing 256 by 10 leaves 6 over, so the values 0 to 5 each have 26 chances and 6 to 9 each have 25.

That makes 0 through 5 roughly four percent more likely than 6 through 9. With a large source range and few buckets the gap looks negligible, but in an automated system running thousands of draws it accumulates into something visible.

The correct fix is rejection sampling: discard values that fall in the leftover region and draw again. The tools on this site use that approach when narrowing a range, so every value ends up with exactly equal odds.

The right way: a Fisher-Yates shuffle

The Fisher-Yates shuffle walks the array from the back, and at each step swaps the current item with a random position drawn from the part that has not been shuffled yet. It is under ten lines of code, and it is mathematically proven to produce every possible ordering with equal probability.

The critical detail is drawing only from the remaining range. Pick from the whole array instead and the permutation probabilities stop being equal. There are n factorial orderings of n items but that naive version has n to the power of n paths through it, and unless the second divides evenly by the first, some orderings must come up more often.

The random picker, order picker, and team maker on this site all use Fisher-Yates. However long your list is, no name becomes structurally more likely than another.

Randomness quality: ordinary versus cryptographic

The browser's Math.random() is a pseudo-random generator. It computes each value from an internal state using a fixed rule, so with enough observed output the next value is, in theory, predictable. Most browsers use something in the xorshift128+ family.

The statistical quality is genuinely good. It passes tests for uniformity, period length, and correlation, which means it is entirely adequate for splitting a class into groups or picking a lunch spot. The limitation only matters when somebody has a reason to try predicting the result.

For a draw with real money attached, use cryptographically secure randomness from crypto.getRandomValues() instead. Those values are seeded from physical noise collected by the operating system, and the internal state cannot be recovered from the output.

Weighted draws can still be fair

Fairness does not have to mean equal odds. Giving someone who entered three times triple the chance, or setting different odds per prize tier, is perfectly fair as long as the rule is clear and published in advance. What is unfair is having unequal odds while claiming they are equal.

What matters is that the real probability matches what you configured. Give one option a weight of three while two others stay at one and the total is five, so the odds should be sixty, twenty, and twenty percent. The tools here display the computed probability for each entry, so you can show participants the exact numbers before you draw.

Publish the weighting rule before the draw, never after. A rule explained once the result is already known reads as a justification, however reasonable it actually is.

Drawing several winners at once

When you draw more than one, decide first whether the same entry can come up twice. Removing each pick from the pool is called sampling without replacement; putting it back is with replacement. Almost every prize draw wants the first one.

That said, if the same name appears twice in your list, those count as two separate entries. If you want one chance per person, deduplicate the list before you draw rather than after.

For multi-round draws, remove already-drawn names before the next round. The picker here can turn the current list into a share link, so you can hand a cleaned-up list to the next person as a single URL.

Being believed is part of being fair

A perfect algorithm is worthless if participants do not trust the result. In practice, three things do most of the work: publish the rule beforehand, freeze the entry list and show that state, and let people watch the moment of the draw.

Sharing your screen with the full list visible while you press the button raises credibility more than any technical explanation could. Saving the result as an image and attaching it to the announcement gives you something to point at later.

The opposite pattern, where one person draws alone and posts only the names, is the most doubted format regardless of what algorithm sits behind it. Procedural transparency matters as much as the quality of the randomness.

Try it right here

You can try what this article describes without leaving the page.

First time? Open this guide
  • Enter one item per line.
  • To use weights, add *number after the name. Example: Alex*3
  • Higher weights increase the chance of being picked.

Omitted weights are treated as 1. Use the name*number format to avoid confusion.

Result

Waiting

?

No result yet.

Open the full tool

Full screen, saving results, and the rest of the options all live on the tool page.

FAQ

Is using RAND in a spreadsheet good enough?

For everyday use, yes. Be aware that RAND recalculates whenever the sheet updates, so paste the drawn result as a value to freeze it. Sorting by RAND also depends on how the tool breaks ties, which can introduce a small bias that Fisher-Yates does not have.

The same person keeps winning. Is something wrong?

With ten entries, the same name coming up twice in a row happens ten percent of the time, and three in a row happens once every hundred draws. Randomness clusters rather than spreading evenly, so a result that looks suspiciously well distributed is the more artificial one.

How many entries can the list hold?

There is no algorithmic limit. The practical limit is what stays readable on screen. For lists in the hundreds, save the result as an image so you have a record of both the list and the outcome.

How do I prove a draw afterwards?

Capture the list, the rule, and the result at the same moment. Saving the result screen as an image gets the entries and the winner into a single file. Publish the draw time and who ran it alongside it and you can answer any later query.

Are the names I type stored anywhere?

No. Every tool here computes entirely inside your browser. Nothing you type is sent to a server or saved, so internal staff lists and student names never leave your machine.

Can weights be decimals?

Whole numbers are easier to explain to participants. If you want one and a half times the odds, scale everything up and use three against two. The probability is identical but the published rule reads far more clearly.

Tools to use with this

More articles