How it works · privacy and the maths
Is a Secret Santa generator safe? Here is exactly what this one does
The short version: the draw runs in your browser, there is no server of ours, and an organizer who goes looking can still learn who drew whom. The table below shows how, mode by mode.
This page lists everyone who could learn something, says which protections come from how the tool is built and which are only decisions we made, gives you three tests to run yourself, and sets out the maths of the draw. The decoder below takes a real sealed link apart in front of you.
A real sealed link, made in your browser a moment ago by the same two files the generator uses. This page loads those files directly and keeps no copy of its own, so the link below is in the generator's real format. The people in it are invented.
—
The box below takes apart any sealed link you paste. A pasted Quick link is decrypted in this tab and its fields are listed with their lengths and their contents withheld; a Locked link shows only its shape. Someone else's Quick link would still tell you how long each name in it is, so paste your own.
What we claim
There are four claims, and they are not equally strong.
The whole draw runs in your browser. Nothing you type is transmitted by this site, and the tool works with your wifi switched off. There is no account, no database, and no server of ours to store anything on. Only two things are kept on your device. One is the site's own code, cached so the tool works offline. The other, while a draw tab is open, is your own sealed links and the names they are for, so a reload does not wipe out a half-sent draw. That copy holds no pairings, the Forget this draw button clears it, and the privacy policy describes it in full. It is the one disclosed exception to the site's zero-storage default.
Each assignment exists only inside its own link, in the part of a URL after the #. Browsers leave that part out of the request they send to a web server, so it does not appear in our logs, our host's logs or a chat app's link-preview fetch.
The draw is uniformly random over every assignment your rules allow, and this page publishes the algorithm.
In a Locked draw, each assignment is sealed to a key the recipient's own device made and sent to nobody. This is the only one of the four that rests on mathematics; the others rest on how we built the tool. The next section lists where it stops.
Who can learn what
Read the last column first. Architecture means the information is not there to be had: no request carries it and no store holds it. Our choice means the information exists and the way we built the page decides when it is shown, so weigh it as you would a promise. Nothing means nothing stops it.
| Who | In a Quick draw | In a Locked draw | What stops it |
|---|---|---|---|
| This site | Nothing. No name, rule or pairing ever enters a request. | Nothing, for the same reason. | Architecture |
| Our host and CDN | That some browser fetched some pages, with an IP address and a time. They never see a name or the part after the hash. | The same. | Architecture |
| Your chat app | The whole message, key included: Slack or Gmail holds something that opens that assignment. | The sealed message only. The key that opens it never left the recipient's device. | Quick: nothing Locked: architecture |
| The organizer | Any assignment they open, one link at a time, past a screen naming whose it is. Printed slips and developer tools in the draw's tab show them the whole draw, and a drop-out repair shows one pairing. | Nothing from the envelopes. Slips, drop-out repairs and developer tools work as in a Quick draw. | Quick: our choice Locked: architecture, with exceptions |
| Another participant | Their own assignment, plus anyone else's whose link they are handed. | Their own only. | Quick: nothing stops it Locked: architecture |
| Someone who finds a link | That one assignment, from a forward, a screenshot or a shared screen. | Nothing without that person's keep link. | Quick: nothing Locked: architecture |
There is no server of ours, so this site learns nothing about your draw, as the first row says. The cost of that design lands in the organizer's row, which shows what they can learn.
Where those claims stop
The organizer holds every envelope. In a Quick draw the key that opens a link travels inside it, so the person handing the links out can open any of them. Opening someone else's link means clicking past a screen that carries that person's name. That stops an accidental glance, and it does not stop an organizer who means to look. The send list never names anyone's recipient, and no database holds the pairings.
The organizer's browser holds the draw. In either mode the draw runs in the organizer's browser and stays in that tab's memory until they close it, so an organizer with developer tools can read it. Printing fold-over slips puts every pairing on paper, and repairing a drop-out shows the organizer one pairing. A Locked draw makes the envelopes opaque to whoever hands them out, and all three of these still apply. If you would rather nobody had that access, hand the draw to someone who is not playing; the organizer-blind guide runs its four tests on this site first.
Your chat app keeps the message. No server of ours holds a link, but once you send one, Slack, Gmail or WhatsApp stores it, and it will still be in that thread in February. Deleting it is their job.
A Quick link can be forged. The key ships with the ciphertext, so anyone can make a link that decrypts perfectly, including one carrying your draw ID. The encryption protects against damage: a mangled link fails with an error and cannot decrypt to a plausible wrong name. Against a fake it does nothing. The draw ID shows that two links came from one run, and it tells you nothing about fairness, validity or whether anyone looked. Its one use is the sentence the drop-outs guide relies on: any link showing the old ID is dead.
Your browser and its extensions sit outside the page. With Enhanced Spell Check turned on, Chrome (behavior as of August 2026) can pass whatever is in a text box to Google for checking. That happens below our page, where our Content-Security-Policy cannot block it and our own meter cannot count it, and it is why the generator's names box has spell-checking off. Any extension can read a page you have open, this one included.
Small groups give pairings away by arithmetic. Three people have only two possible draws, so anyone who opens their own link knows the rest. The generator prints the number of possible draws and turns it amber below five people. On tightly constrained lists it switches to a second method, described below, whose output obeys every rule and is not claimed to be uniform; the readout says which method you got.
Three ways to check this, strongest first
1. Turn your wifi off. This is the strongest test, because it runs outside our code and no version of this page could fake a pass. Load the generator with a connection, switch on airplane mode, then type names, set rules and seal the whole draw. If it completes, the work happened on your device, because with no network there is no server to do it. The reveal page works offline only on a return visit, since a participant opening it for the first time has nothing cached yet.
2. The devtools Network tab. This also runs outside our code, and it watches the whole time. Press F12, or Command-Option-I on a Mac, switch to Network, set the filter to All so websocket traffic is not hidden, and reload. You will see this page's own files arrive. After that, typing a roster and sealing a draw should add nothing. An upload is easy to spot: a POST or PUT, a size that grows with your input, and a server as the destination.
3. The meter on this page. This is the weakest of the three, which is why it comes last: it is a counter we wrote, in a page we serve, reporting on requests we made. On the reveal page it is weaker still. The sealed payload was already in the address bar when the page was requested, before any of its JavaScript ran, so no counter on the page could have been watching when it arrived. What keeps the payload off a server there is how URLs work. The fragment, everything after the #, is excluded from the request-target by RFC 3986 section 3.5 and is not carried in a Referer header, so it never reaches a web server. That is what browsers do, and it does not depend on our conduct.
The draw itself
A draw here is a uniform random derangement: a pairing in which everyone gives exactly one gift, receives exactly one gift, and nobody draws themselves. There are 9 such pairings for four people, 44 for five, and 1,334,961 for ten, and this tool is equally likely to produce any of them. The familiar party shortcut, where everyone is shuffled into a circle and gives to the next person, produces only pairings that form a single loop; it is Sattolo's algorithm under a friendlier name. Every result it gives is valid, but it can never produce the three four-person draws where two pairs simply swap, and at twenty people it can reach only about one possible draw in seven. This tool does not use it.
The method here is rejection sampling, published because it is the only one whose distribution can be stated in a single line. The tool shuffles the list with a Fisher–Yates shuffle driven by your browser's cryptographic random number generator and checks the result against every rule: self-draws, household exclusions and last year's pairs. If any rule is broken, it throws the whole shuffle away and starts again. Conditioning a uniform distribution on a rule leaves it uniform over whatever survives, so the draw you keep is exactly uniform over the draws your rules allow. Little is wasted. With no exclusions beyond self-draws, the expected number of shuffles is 2 for two people, 3 for three, and between 2.6 and 2.8 for every larger group at any size, converging on e ≈ 2.72. Fewer than one draw in a thousand needs more than sixteen shuffles. Exclusions cost more, roughly a factor of e for each person everyone is excluded from: a group of ten made of five couples takes about eight shuffles. The random numbers come from crypto.getRandomValues through a rejection step of their own, so no name is even fractionally likelier than another. The modulo shortcut, which favours the low numbers, is not used. There is no seed, because a printed seed would let anyone who had it reproduce the draw.
This approach has three limits, and the tool reports each one. First, exclusions can make a draw impossible, and when they do, the tool says which rule is the problem before you press anything. A household can never be larger than half the group, because every one of its members has to give to someone outside it; that is Hall's marriage theorem applied to a party. Where the cause is less obvious, the tool finds the smallest set of people whose combined rules leave them too few recipients, and names them and the rules involved. Second, on very tightly constrained lists rejection sampling would take impractically long: two households of ten inside a group of twenty would need roughly 185,000 shuffles. So after 20,000 attempts the tool switches methods. It builds one valid pairing by direct matching, then randomises it with swaps that are accepted only when the result is still valid. That output obeys every rule, but it is not proven to give every valid draw an even chance, so it is not claimed to. The readout says uniform or constrained for the draw you got, and those two words mean what this paragraph says. Third, a draw can be uniform across whole draws and still leave some people likelier to draw certain others. Lopsided exclusion rules skew those individual odds, and no draw method can undo that.
Several other methods were considered and not used. Sattolo's algorithm, above, is the popular one. Two more look correct and are not: resampling only the position that broke the rule, and fixing the fixed points by swapping self-draws away after a shuffle, which is not uniform however reasonable it looks. Martínez–Panholzer–Prodinger is a sound alternative: it is exactly uniform, runs in linear time and needs no rejection step. It was passed over because it needs careful ratio arithmetic, overflows double precision past about 170 people, and saves 1.7 shuffles. The exclusion-rules guide has the verified counts.
What is inside a link
The decoder at the top of this page shows this section on a real link. A Quick link carries a version byte, a 16-byte key, a 12-byte initialisation vector, then the ciphertext and its 16-byte tag, base64url-encoded after the #. Inside sits a small frame: version, flags, a four-byte draw ID, then five length-prefixed fields (opener, recipient, event, note, hint). A link that sets an event date or a gift budget carries one more thing: a fixed 5-byte block, ahead of those five fields, for the date, the budget amount and its currency — fixed-width for the same reason the fields themselves are padded below, and present only when the draw actually used one of those two optional fields. Each link gets a fresh key and vector, so a link that goes astray exposes exactly one assignment.
The frame is then padded with zeros to a constant length, and the padding protects the draw. AES-GCM does not change the length of what it encrypts, so without padding a link's length minus a known constant is the recipient's name length. On a twelve-name roster that alone narrows 176,214,841 candidate draws to a few hundred and recovers several pairings exactly, with nothing opened and no key used, which gets straight past the name screen the rest of the design relies on. Every link in one draw is padded to a single length taken from the longest name in the roster, and a test checks that they all come out exactly the same length.
So link length does not grow with the group. A Quick link is about 200 characters for four people or for fifty, and every link in one draw is the same length. The exact figure depends on your longest name plus the event and note, never on the size of the group. A Locked reveal link that sets a date or a budget is 285 characters, a participant code 92 and a keep link 161. What grows is the number of messages, which is why the generator prints "25 people means 25 separate messages". The comparison guide weighs that against the alternatives.
Two modes, and how to pick one
Quick draw is one round with nothing to set up first: type names, seal, send. Nobody waits on a participant who has not set up yet, and its privacy limit is the organizer's row in the table above.
Locked draw adds a round first. Each participant opens the key maker on their own device, keeps the link it gives them, and sends back a 92-character code; every envelope you then hand out is sealed to that person's key. It costs everyone a job before the draw can happen. Someone who loses their keep link has to make a fresh code, and then you seal the draw again, which gives everyone new links. In twelve people, expect one.
Delegation is the third option and needs no cryptography: hand the draw to somebody who is not playing, with a roster link carrying the names and rules and no pairing, because none exists yet. Your delegate must be able to message everybody, and in a family draw that person is usually a participant. The guides cover all three.