Skip to content
Randomize List

How Randomize List Works

Every draw starts from a seed, a 12-character code produced by your browser’s cryptographic random generator. The seed starts a small generator called sfc32, and a Fisher–Yates shuffle turns its numbers into an order. Nothing goes to a server: a share link carries the list and the seed, and the result is recomputed when it opens.

Last updated

From seed to order

A draw has three steps. First your browser asks its cryptographic generator, crypto.getRandomValues, for 60 random bits and writes them as twelve characters of Crockford base 32, such as K7Q2-9MXD-4HCZ. That alphabet leaves out I, L, O and U, so a seed is hard to misread aloud or from a projector, and if someone types it as printed, in groups of four with dashes, an O is read as 0 and an I or L as 1.

Second, the seed text is hashed into four 32-bit words with cyrb128, a string hash that bryc published in an answer on Stack Overflow for seeding generators. Those words start sfc32, a small, fast generator that passes the PractRand statistical tests, as described in bryc’s notes on JavaScript generators. The first fifteen outputs are thrown away so that similar seeds do not start out similar. For the sample seed the starting state is e7545833 1587d92c d447b048 5fd54d28 and the next three outputs are 289310140, 1266939494, 2131672963; your browser computes the same numbers for the same seed, every time, on every device.

Third, those numbers drive a Fisher–Yates shuffle: walk the list from the end, and swap each position with a position chosen uniformly from the ones not yet fixed. Every order of the list is then equally likely, as long as each choice is uniform. Teams, pairs and running orders are built on this shuffle; the team generator, for one, deals the shuffled names round the table like cards. Picks use the same swaps walking from the front and stop after the number of names asked for, so the winner is the first name chosen, not the first name of a full shuffle with the same seed.

Choosing a position without bias

The generator gives whole numbers from 0 to 232 − 1. Turning one into a position among n by taking the remainder would favour the low positions slightly whenever n does not divide 232. Instead, the few values at the top of the range that would cause the imbalance are rejected and a new number is drawn, the method described in “Efficiently Generating a Number in a Range”. A retry is rare:

Values rejected out of 232, and how often a draw is retried
Positions (n)Values rejectedChance of a retry
311 in 4,294,967,296
511 in 4,294,967,296
741 in 1,073,741,824
1061 in 715,827,883
2,147,483,6492,147,483,6471 in 2

The last row is the worst case: for a range just over 231, almost half the values are redrawn, and the result is still exact. The same step picks every value on the random number list generator, so numbers from a range do not lean towards either end.

What a seed proves, and what it does not

A seed makes a draw reproducible. Anyone with the same list, the same settings and the same seed gets the same result, so a posted result can be checked rather than taken on trust. A seed does not prove that the person running the draw did not try several seeds and keep the one they liked. The remedy is to fix the seed before the draw: announce it, or derive it from something public, then type it into “Use your own seed”. The name picker page turns this into a step-by-step giveaway procedure.

There is also a counting limit. Seeds made by your browser are 60 bits: twelve characters hold 260 of them, about 1.15 × 1018. A list of n names has n! orders, and from n = 20 upwards n! is larger than the number of generated seeds, so not every order can come out of a generated seed. Below that, more seeds than orders makes every order possible in principle; it does not guarantee that each one comes from some seed, because a seed only chooses where the generator starts. A seed you type yourself can be any text up to 64 characters and is hashed into 128 bits, which moves the same limit to n = 35. Each name is still equally likely to land in each position, which is what fairness means for a draw; the limit only says that the set of possible orders is a very large sample, not all of them.

Possible orders of a list compared with the 260 seeds a browser generates
NamesPossible orders (n!)More generated seeds than orders?
103,628,800Yes
151,307,674,368,000Yes
191.22 × 1017Yes
202.43 × 1018No
251.55 × 1025No
302.65 × 1032No

A share link carries the list, the mode, its settings, the seed and the algorithm version (currently 1), never the result. Opening the link runs the draw again, and that recomputation is the check. Before the list goes into the link it has already been cleaned (spaces trimmed, blank lines dropped), so the link does not depend on how the list was pasted. For three names the text looks like this:

v=1
m=shuffle
p=
s=K7Q29MXD4HCZ
--
Ana
Ben
Chloe

It is compressed with the browser’s own CompressionStream (raw deflate) when that makes it shorter, and written in URL-safe base 64. Short lists gain nothing from compression: the link for the eight-name sample is stored uncompressed and is 124 characters long. Links over 2,000 characters get a warning, because some messengers shorten long links; over 8,000 characters no link is made and you can download the list and seed as a text file instead.

Privacy of a draw

Everything happens in the browser: the list is parsed, shuffled and shown without a request to any server. The part of a link after # is the URL fragment, which browsers do not send to the server or pass on in the Referer header. The last ten draws are kept in your browser’s local storage so you can reopen them, and Clear history removes them. Anyone who receives a share link can read the list in it; the privacy policy lists what the link does and does not reveal.

Secret Santa without anyone drawing themselves

A gift exchange, the Pairs mode of the list randomizer, needs an order in which nobody gives to themselves, which mathematicians call a derangement. The tool draws a uniform shuffle and keeps it only if it breaks no rule, otherwise it draws again; this is rejection sampling, and keeping the first valid draw from uniform draws is itself uniform over the valid ones. About 37% of all orders are valid, so a few tries are enough:

Gift exchanges in which nobody draws themselves, out of all orders
PeopleValid exchangesAll ordersShare valid
32633.3%
492437.5%
54412036.7%
626572036.8%
814,83340,32036.8%
101,334,9613,628,80036.8%
208.95 × 10172.43 × 101836.8%

Exclusions, such as partners who should not draw each other, remove more orders. When the tool runs out of tries it checks whether any valid exchange exists at all, using Hall’s marriage theorem: if a group of people together can only give to fewer people than the group has, no arrangement works, and the message names that group. If arrangements exist but are rare, a search finds one and the result is marked as a constrained, non-uniform draw.

Sources

How a Randomize List draw works: seed, generator, shuffle and share link
The preview image that appears when this page is shared, built from the page title.