Contact

Tools  /  Security  /  Secure Random Number Generator

Secure Random Number Generator

Cryptographically random integers, decimals, dice rolls, list picks and coin flips -- unbiased rejection sampling via crypto.getRandomValues, not Math.random().

What this tool does

Five related ways to get a genuinely random result -- integers (single or a batch, with a true no-duplicates mode), decimals to any precision, dice rolls (full NdM+K notation), a random pick from a pasted list, and coin flips -- all built on the same cryptographically secure, unbiased core.

Why rejection sampling, not a plain modulo

A naive randomByte % range is very slightly biased toward lower values whenever 256 isn't a multiple of the range -- this tool instead draws random bytes from crypto.getRandomValues() and discards (rejects) any value that would introduce that bias, redrawing until a uniformly fair one appears. Every mode on this page -- integers, dice, list picks, coin flips -- is built on that same unbiased core, not five different approximations.

Why not Math.random()?

Math.random() is not cryptographically secure -- its internal state can be reconstructed from enough outputs on some engines, which matters for anything security-relevant (a raffle winner, a cryptographic nonce, a fair game outcome). crypto.getRandomValues() draws from the operating system's CSPRNG and gives no such foothold.

True no-duplicates batches

Generating multiple unique integers (or unique picks from a list) uses partial Fisher-Yates sampling -- each draw removes the chosen value from further consideration, so "5 unique numbers from 1-10" can never repeat a value, unlike independently generating 5 numbers and hoping none collide.

Dice notation

Supports standard tabletop notation -- 2d6 rolls two six-sided dice, 1d20+5 adds a flat modifier, and multiple terms chain together (2d6+1d4+3) -- with every individual die shown alongside the total, not just the final sum.

Picking from a list

Paste any list (raffle entrants, a shortlist, team assignments) and draw one or several unique entries at random -- the same unbiased core used for integers, applied to arbitrary items instead of numbers.

Privacy

Every random value is generated entirely in your browser via the Web Crypto API. Nothing is uploaded. Session history exists only in this tab's memory and disappears when you reload or leave the page.

Frequently asked questions

Why does this matter over just using Math.random()?
Math.random() is not cryptographically secure -- its internal state can be reconstructed from enough outputs on some engines. crypto.getRandomValues() draws from the operating system's CSPRNG instead, which matters for anything where fairness or unpredictability is actually load-bearing (a raffle, a game, a security-relevant value).
What is rejection sampling and why does every mode use it?
A plain randomByte % range is very slightly biased toward lower values whenever 256 isn't evenly divisible by the range. Rejection sampling discards any drawn value that would introduce that bias and redraws, guaranteeing a genuinely uniform result -- used underneath every mode here (integers, dice, list picks, coin flips), not just the integer generator.
How does the no-duplicates mode guarantee uniqueness?
It uses partial Fisher-Yates sampling -- each draw removes the chosen value from the remaining pool before the next draw, so a batch of unique integers (or unique list picks) can never repeat a value, rather than generating independently and hoping none collide.
What dice notation is supported?
Standard tabletop notation: NdM for N dice with M sides (2d6, 1d20), a flat +K or -K modifier, and multiple terms chained together (2d6+1d4+3) -- every individual die result is shown alongside the total.
Can I pick more than one item from my list?
Yes -- set the count and get that many unique picks (never the same entry twice) drawn via the same unbiased core used for integers.
Is this fair enough for something like a raffle or giveaway?
Yes -- it uses the same cryptographically secure, rejection-sampled randomness throughout, specifically to avoid the subtle bias a naive implementation (or Math.random()) can introduce.
Why decimals in addition to integers?
Some use cases need a fractional value in a range (a random weight, a probability threshold, a simulation input) rather than a whole number -- generated to whatever decimal precision you choose, using the same unbiased integer core scaled internally.
Is anything generated here sent anywhere?
No. Every value is generated entirely in your browser via the Web Crypto API -- this tool has no server component. Session history is kept only in this tab's memory and clears on reload.
Theme Accent