Share links and privacy
Every wheel on this site has a Copy share link button, and every wheel remembers the list you last edited. This guide explains precisely what that button puts into a link, why the list travels in the part of the address that browsers keep to themselves, what a link cannot carry, and what stays on your device. Each encoded string, length, cap and error message below was produced at build time by the same share codec the wheels use, so the examples are real outputs rather than illustrations.
What Copy share link actually does
Pressing the button hands your current entries to the engine's encoder. The encoder takes each
entry on its own and percent-encodes it — spaces, commas, punctuation outside the plain URL
alphabet and every non-ASCII character become % sequences — then joins the encoded entries
with a | character and places the result after #items= on the page's own
address. The path is unchanged, so the link opens the same wheel page you were on; only the fragment
differs. An empty list is refused before any of that happens, with “Add at least one entry before creating a share link.”
Here is a short list run through the real encoder:
- Movie night
- Board games
- Walk, then dessert
The encoded value is Movie%20night|Board%20games|Walk%2C%20then%20dessert — 52 characters — and the full
link for the custom wheel is https://spinthatwheel.net/#items=Movie%20night|Board%20games|Walk%2C%20then%20dessert, 85 characters in all. Read it left to right and the structure is visible: the comma in the third entry became %2C, every space became %20, and the 3 entries are separated
by the 2 bare | characters between them. Decoding that value at
build time returned 3 entries identical to the originals — the round trip the
automated tests pin.
Why the list rides in the fragment
The part of an address after # is the fragment. Browsers do not include URL fragments
in web requests, so when someone opens a share link their browser asks the server for the wheel page
and its assets, and nothing in any of those requests carries the list; the list is read out of the
fragment by the page's own script, after the page has loaded, entirely on their device. That is why
a fresh share link rebuilds the wheel locally without sending the entries to the hosting server, and
why this guide can describe the mechanism rather than ask you to take a promise on trust.
Older links used a query string, ?items=, instead of a fragment. Those are still
accepted: the same extractor reads the raw value from either form, and at build time the
fragment form and the legacy form of the example above extracted to the identical value. The
difference is where the value travels. A query string is part of the requested address, so a
legacy link does reach the server as a requested URL; the privacy policy sets
out how requested URLs are handled by hosting. Every link the site produces today uses the fragment.
One detail of the extractor matters for correctness: it keeps the value percent-encoded until
the decoder has split it on |. If the value were decoded first, an entry containing
a literal | — stored as %7C — would turn back into a bare separator and
split into two entries. Splitting first and decoding each piece afterwards is what lets the separator
itself survive, as the next section shows.
The length cap, and why it refuses instead of trimming
The encoded value is capped at 1800 characters. The reason is stated in the codec's own source: the cap keeps full addresses comfortably under the limit that older browsers and some chat apps enforce. When a list will not fit, the button does not shorten it, drop the tail or produce a partial wheel. It returns an error and copies nothing.
Built at build time: a list of 40 entries, each within the 80-character entry limit, whose percent-encoded value would run to 3270 characters. The encoder's answer was “This list is too long to fit in a share link — shorten some entries or remove a few. Nothing was truncated.” The decoder guards the same boundary from the other side — a value longer than the cap is refused with “The share link is longer than this site ever produces.” — and it applies the ordinary entry rules too: at most 100 entries, at most 80 characters each, blank pieces dropped. A single piece of 81 characters decoded to “Entries are limited to 80 characters.” Decoding a link runs the same validation as typing the list by hand, so a link can never load a wheel that the entry box would have rejected.
What survives the trip
Because each entry is percent-encoded on its own, the alphabet of the entry does not matter to
the link. This list — Karaoke 🎤 / Bowling 🎳 / Stay in ☕ — encodes to Karaoke%20%F0%9F%8E%A4|Bowling%20%F0%9F%8E%B3|Stay%20in%20%E2%98%95: 67 characters for 29 characters of raw text (the entries plus the 2 separators between them), because each emoji expands into several % sequences.
Decoding it at build time returned 3 entries, each identical to the original,
emoji included. Text in any language takes the same route, since the encoder applies the same rule
to every entry: characters outside the plain URL alphabet are escaped, the rest pass through unchanged.
The separator survives as well. The 2-entry list “Tea | Coffee” and “Neither” encodes to Tea%20%7C%20Coffee|Neither: the | inside the first entry is stored as %7C, and the one bare | is the separator. Decoding returned 2 entries, the first still reading “Tea | Coffee”. Blank pieces are dropped on the way back in,
exactly as blank lines are dropped when you type: the value Tea|%20|Coffee, whose
middle piece is an encoded space, decodes to 2 entries.
Damaged links
The decoder detects one kind of damage, and it is worth being exact about which. It tries each
piece in turn, and a piece that is not valid percent-encoding — an escape sequence cut off
part-way, or a % followed by something other than two hex digits — stops the whole decode.
The value Movie%20night|Board%2 is the first 21 characters of the encoded
value above, and it ends inside an escape sequence; at build time it decoded to “The share link is damaged — part of it is not valid encoding.”
On a wheel page that message appears in the result box, prefixed “Ignored the shared list:”, and
the wheel loads the list it would otherwise have shown: your saved list for that wheel, or the
preset. Nothing from the damaged link is kept. That is the whole of the guarantee: broken
encoding is refused rather than decoded into a garbled wheel.
A cut that happens to fall between escape sequences is a different case, and the decoder cannot
tell it apart from a shorter list. The value Movie%20night|Board%20ga is the first 24 characters of the same encoded value, and it is valid encoding all the way to its end. At build
time it decoded without complaint to 2 entries — “Movie night” and “Board ga” — with the last entry clipped mid-word and 1 of the original 3 entries missing, and no error anywhere. The encoded value carries no checksum and no entry count,
so nothing in it says how long the list was meant to be. If a link arrives with fewer entries than
you sent, or with a last entry that looks clipped, the link was cut on the way, not the list on the
way out: send it again in one piece, and check that every entry arrived.
What stays in the browser
Everything, unless you carry it out yourself. The list you edit on a wheel page is saved in your browser's local storage so that it survives a reload. It sits on your device, under your control: the Reset list button removes the saved list and restores the preset, and clearing the site's data in your browser removes it too. Spins, results and the history panel exist only on the page and are discarded when the tab closes; none of them is saved and none of them is sent anywhere. There are no accounts, and nothing you type is transmitted, logged or stored by the site. What the hosting provider processes in serving pages, and what advertising or analytics services process when they are enabled, is a separate matter set out in the privacy policy.
The only exit is a link you copy
A list leaves your machine in exactly one way: you press Copy share link, the link is copied to your clipboard — or, if copying is blocked, shown in the feedback line beneath the button for you to copy by hand — and you paste it somewhere. That is a deliberate act every time. Nothing is published, synced or made retrievable by anyone who does not hold the link. The flip side is just as plain. Percent-encoding is a reversible transformation, not a secret: anyone who receives the link can read every entry, either by opening it or by reading the address. Treat a share link as the list itself, written out, and send it only where you would send the list.
How to check for yourself
You do not have to take the mechanism on trust. Open your browser's network tab, load a wheel
page, edit the list, spin, and press Copy share link — no request carries your entries. Then
open a share link in a new tab and look at the request for the page: it asks for the wheel's
path, and the part after # is not in it. That is the whole privacy claim of this site
reduced to something you can watch happen, which is the standard the methodology page holds every other claim to as well. The same check is the second of the two in Is the wheel rigged?, alongside the reduced-motion check that shows the draw without the animation.
Common misreadings
- “The link is private.” It is not sent to the server, which is a different thing. Whoever holds the link can read the list.
- “The link carries the result.” A share link carries the list, and only the list: no winner, no history, no eliminator progress, no settings. The recipient spins fresh, and their draw is as uniform as yours and independent of anything that happened on your screen.
- “Long lists get trimmed to fit.” They are refused, with the error quoted above. The codec never silently truncates, on the way out or on the way in; a link cut in transit is the one case where a shorter list can arrive, and the section on damaged links shows why.
- “A saved list is stored on the site.” It is stored in your browser's local storage, on your device. The site has no copy.
- “Reloading loses everything.” The edited list survives a reload; spins and history do not, because they were never saved.
-
“Old
?items=links stopped working.” They still open. The difference is that their value travels in the requested address rather than in the fragment.
Related reading
The methodology page documents the draw itself, eliminator mode and the test suite in one place. The other guides take each of those apart in turn: Entry lists and parsing rules covers the caps of 100 entries and 80 characters that a decoded link re-applies, and Is the wheel rigged? makes the network-tab check described above one of its two checks. To try any of this, the custom wheel accepts any list up to 100 entries and has the Copy share link button under the wheel.
Frequently asked questions
Does Copy share link upload my list to SpinThatWheel?
No. The list is placed after # in the page address as a percent-encoded items= fragment, and browsers do not include URL fragments in web requests. Opening the link asks the server for the wheel page and its assets; nothing in any request the page itself makes carries the entries, which are read from the fragment by the page's own script on the recipient's device. What analytics or advertising scripts send when they are enabled is a separate matter covered by the privacy policy. You can confirm the page's own behaviour in your browser's network tab: no request it makes carries your entries.
Can someone who has the link read my entries?
Yes. Percent-encoding is a reversible transformation, not a secret: anyone who receives the link can read every entry by opening it or simply by reading the address. Not being sent to the server and being private are two different things. Treat a share link as the list itself, written out.
Why did Copy share link refuse my list?
The encoded value is capped at 1800 characters, a cap chosen — as the codec's own source puts it — to keep full addresses comfortably under the limit older browsers and some chat apps enforce. A list that does not fit is refused with an error and nothing is copied; the button never shortens a list to make it fit. The error reads: "This list is too long to fit in a share link — shorten some entries or remove a few. Nothing was truncated."
Do emoji and other languages survive a share link?
Yes. Each entry is percent-encoded on its own under one rule, whatever its alphabet: characters outside the plain URL alphabet are escaped, the rest pass through unchanged. At build time the list Karaoke 🎤, Bowling 🎳, Stay in ☕ encoded to 67 characters and decoded back to 3 entries identical to the originals, emoji included — the same round trip the automated tests pin.
Does the link include the winner, the history, or eliminator progress?
No. A share link carries the entries as they stood when you pressed the button, and only those. No result, no spin history, no eliminator state and no settings travel with it. Whoever opens the link spins fresh, and their draw is made on their device from their own cryptographic random bytes.
What does Reset list actually delete?
It removes the list saved in your browser’s local storage for that wheel and restores the preset. It also returns the controls to their defaults — Remove duplicate entries off, the alternate-list switch off where a wheel has one, the number-range box cleared — and clears the result box and the share-link feedback line; none of those was ever saved. Spin results and history are never saved in the first place: they exist only on the page and are discarded when the tab closes. Clearing the site’s data in your browser removes saved lists too.
A share link is the list, in the open: anyone you send it to can read every entry, so share it as deliberately as you would share the list itself. Everything runs locally in your browser; see the methodology page for how the draw works.