AIBOX

Random Number Generator

Draw random integers from any range — 1 to 100, 1 to 49, or ends of your own — with the one property that actually matters and that most generators quietly lack: no value is more likely than another. The draw comes from your browser's cryptographic random source, and the shortcut most sites take — a random word taken modulo the range — is refused here, because it is biased whenever the range does not divide the source evenly. Draws without repeats use a partial Fisher–Yates shuffle, dice and coin flips ride the same core, and every refusal is a sentence on the screen rather than a quiet fix.

Four modes, one unbiased core. Distinct mode is the one for raffles and classroom picks: every number comes out different. Independent mode is the one for "give me five numbers, repeats allowed".

Both ends are included. Negative ends are allowed — a random offset is a legitimate thing to draw. 1-100 and 1 to 100 mean the same thing here.

If the low end is above the high end you get an error, not a quiet swap — a generator that silently fixes your range is guessing on your behalf.

With replacement: the same number can appear more than once.

Nothing you type is sent to us: the draw runs in the tab you already have open, which is also why there is no usage limit. See our privacy policy.

How to use it

  1. Pick the mode before the numbers. The four modes answer four different questions, and they are not interchangeable: independent draws can repeat (right for "five random test IDs from a pool that may overlap"), distinct draws cannot (right for "pick 3 winners out of 48 tickets"). Dice and coin flips are the same unbiased core wearing a smaller range.
  2. Press Draw for each new batch. Unlike the converters on this site, this page does not redraw on every keystroke — a random draw is something you ask for, and the batch you are looking at should not evaporate because you touched an input. Enter, Ctrl/⌘ + Enter and the button all do the same thing.
  3. Read the two proof rows under the result. "Rejection bound" is the number that makes the draw fair; "32-bit words" is what this particular draw consumed. If you ever want to check the claim, the bound is recomputed from your range on every draw and printed right there.
  4. Use the sorted row when the order does not matter. Lottery-style draws are usually read sorted; the draw itself stays in draw order (that is the honest order — it is what came out of the source), and the sorted copy is displayed next to it.
  5. Expect streaks. A fair generator produces runs of similar numbers and gaps in others — that is what uniformity looks like in small samples. A generator whose output "looks nicely spread out" is usually a shuffled or stratified one, which is a different tool with a different promise.

How the numbers are actually calculated

There are three steps, and each one is where a class of generators goes wrong.

  1. Get random words from the cryptographic source. The page asks the browser for crypto.getRandomValues — the generator the platform maintains for cryptography — and reads it in 32-bit words, four bytes at a time, in batches. Math.random() is deliberately not used: it is a pseudorandom generator that is not built to be unpredictable, and its quality differs between engines and versions. For a mock dataset that does not matter; for a draw that has to be defensible it does, and this page treats every draw as the second kind.
  2. Reject, then map. The naive mapping is word % range. It is biased whenever the range does not divide 2^32 evenly, and the bias is not a rounding nit — it is structural. This page accepts only words below 4294967200 for a 1–100 draw: the largest multiple of 100 that fits in 2^32. Everything at or above it is discarded and a fresh word is drawn.
  3. Map the accepted word onto your range. The accepted band [0, limit) contains exactly limit / range complete passes over your range, so every number receives exactly the same count of words. That equality is the entire claim of fairness, and it holds by construction rather than by luck.

The concrete example: why modulo is biased

2^32 = 4,294,967,296. Divide by 6 for a die: 4294967296 = 6 × 715827882 + 4. Those four leftover values mean that of the 2^32 possible words, the ones mapping to 1, 2, 3 and 4 number 715,827,883 each, while 5 and 6 get only 715,827,882. One extra chance in 715 million — invisible in a hundred rolls, permanent in the mathematics, and decisive in exactly the setting where people reach for a "fair" generator: a draw with a prize attached. Narrow the source and the same arithmetic gets loud: an 8-bit source (256 words) rolling a d6 gives counts of 43 against 42, a 2.4% skew you could find with a few thousand rolls and a spreadsheet.

Rejection sampling removes the leftovers instead of tolerating them. The cost is one redraw with probability (2^32 mod range) / 2^32 — for a d6 that is 4 in 4.3 billion, and for any range the expected number of attempts stays below 2. When the range is a power of two (a coin, a d4, a d8, a d32) the remainder is zero, nothing is rejected at all, and % would have been exact — which is why the bias hides so easily in dice tools that only ever roll powers of two.

What the page shows you

Every result prints the bound it used and the words it consumed, so the fairness claim is checkable rather than cached. For "6 distinct numbers from 1 to 49" you will see the bound 4294967292 of 4294967296 words accepted — 2^32 is 4 short of a multiple of 49 — and the word count of the draw you just made. Nothing on this page asks you to trust an adjective.

Without replacement: the difference that decides raffles

"Pick 5 random numbers" and "pick 5 different random numbers" are different questions, and mixing them up is how a raffle ends up awarding two prizes to one ticket. With replacement, every draw starts from the full range — repeats are legal and informative. Without replacement, each drawn number leaves the pool, and the right question ("which 5 distinct numbers") has an exact answer that a with-replacement loop can only approximate.

The honest implementation is a partial Fisher–Yates shuffle: imagine the range laid out as a row of cells, pick one of the remaining cells uniformly, take its number, and move the last untouched value into the hole. Every ordered set of k distinct numbers comes out with exactly the same probability, 1/(range × (range−1) × … × (range−k+1)) — uniformity you can write as a formula because the algorithm never retries anything.

The popular alternative — draw, and redraw if you have already seen this number — is where tools go wrong in a way users can feel. As the count approaches the range, the chance that the next draw hits an already-seen number approaches certainty, and the loop's cost grows without bound; when the count exceeds the range it cannot terminate at all, which is the "my tab froze drawing 11 from 1 to 10" failure. This page refuses that input instead: more numbers than the range holds is an error, stated in words, not a silent reduction to what fits.

One cost note, because it is the reason the sparse variant is used: the range can be as wide as 2^32, and laying out 4.3 billion cells as an array would be absurd. Only the cells the shuffle actually touches are stored — a sparse map — so the cost is proportional to how many numbers you asked for, never to how wide the range is. Twenty distinct numbers out of a billion draws as fast as twenty out of ten.

Dice and coins: the same core, smaller ranges

A d6 is "one uniform integer from 1 to 6", which is the identical operation as "one uniform integer from 1 to 100" — so dice ride the exact same rejection sampling, with the bound recomputed for 6. A coin is the smallest interesting case: a range of 2 divides 2^32 exactly, the bound is the whole space, and nothing is ever rejected — the one setting where even the naive modulo would have been fair, and the page still tells you the bound so you can see why.

Two conventions are worth stating because they are choices rather than laws. Dice are numbered 1 to sides, not 0 to sides−1 — the number you read off a physical die. And the coin's two outcomes are named Heads and Tails on the page while the core draws 0 and 1; which word maps to which side is presentation, the half-and-half probability is the mathematics.

Custom sides are first-class, not an afterthought: a d7 (weekdays), a d12 (months), a d30 or a d100 all work through the same path, and the rejection bound is printed for each. The one refusal in this area is a one-sided die: a range of one has a single possible outcome, and presenting a constant as a random draw would be a lie with extra steps.

The limits, and where each one comes from

Every bound on this page is a stated decision with a reason, not a magic number that appeared in a config file. The same numbers are enforced by the core module, which the page and the test suite share, so the page cannot claim one thing and enforce another.

LimitValueWhy that value and not another
Range width≤ 4294967296 (2^32)One draw consumes one 32-bit word, which can name at most 2^32 distinct values; a wider range would need words stitched together, and no real draw — raffles, classrooms, dice, test IDs — comes close. Below the limit, every step is exact integer arithmetic.
Ends of the range±1000000000000000 (1e15)A double holds every integer exactly only up to 2^53−1 ≈ 9.007e15. Keeping ends at 1e15 — the largest round power of ten below it — leaves nine times headroom, so low end + offset is always an exact integer. (This module also deliberately avoids the big-integer type, because the deploy pipeline fails on it; the bounds keep everything in plain numbers.)
Numbers per draw≤ 10000The page renders every number it draws, and past ten thousand the tab spends its time painting, not drawing. Real draws — prize lists, name picks, sample IDs — are orders of magnitude below this.
Distinct count vs rangecount ≤ rangeDrawing without replacement cannot produce more numbers than exist. This is refused with a message — never clamped, because a quiet reduction changes the answer while you watch.
Dice sides2 … 4294967296Below 2 there is nothing to randomise; above 2^32 a single word cannot name the faces. Everything between is the same unbiased draw.

What this tool is not

  • Not a spinning wheel. A wheel picks from a list of names. This picks numbers; if you have a list, number it 1 to N and draw N distinct numbers — same outcome, with the range and the no-repeat guarantee visible instead of animated.
  • Not a password or key generator. Random integers in a range are not key material: a 6-digit draw carries about 20 bits of entropy, and passwords need a character-set strategy and a length you choose, not a range. When that tool exists on this site it will say so on its own page.
  • Not a statistics engine. Uniform randomness does not mean "evenly spread": streaks, repeats and gaps are what a fair source produces, and smoothing them out would make the draw less random, not more.
  • Not a lottery predictor. It draws numbers; it has no opinion about which numbers will win anything, and no page on this site will pretend otherwise.

What leaves this page

Nothing. The page is a static file that imports one module of pure functions: the draw, the rejection sampling, the shuffle and the tallies all run in the tab you already have open. There is no request to our server, no analytics event carrying your range, no cookie and no storage — reload and it is gone, because it was never anywhere else. That matters more here than on a converter: the range people type is often a proxy for something they would rather not announce — the size of a shortlist, the number of tickets sold, a team roster.

The randomness source itself is the browser's, not ours: we never see the words, only the numbers you are shown, and we do not see those either.

Common questions

Is this random number generator actually fair?
It is uniform in a way you can check rather than take on trust. The obvious implementation — take a 32-bit random word and use "word mod 100" for a 1–100 draw — is biased, because 2^32 is not a multiple of 100: the leftovers give 96 of the 100 numbers one extra chance in about 43 billion. This tool refuses those leftover words instead: it accepts only words below 4294967200, the largest multiple of 100 that fits in 2^32, and redraws on anything higher. Inside the accepted band every number gets exactly the same count of words, so no value is more likely than another — and the bound is printed under your result every time, so you are never asked to believe a claim you cannot see.
Can I draw 20 numbers with no repeats?
Yes — pick "Distinct numbers (no repeats)" and set the count. It draws without replacement using a partial Fisher–Yates shuffle, so every number leaves the pool once drawn and all 20 come out different. The cost is proportional to the count, not the range, so asking for 20 out of a range of a billion is as fast as 20 out of ten. If you ask for more numbers than the range holds — 11 distinct numbers from 1 to 10 — that is refused with a message. The alternative behaviour, quietly giving you 10, would change your answer without telling you.
Is "1-100" the same as "1 to 100" here?
Yes. The two boxes are the two ends of the range, so "1-100", "1 to 100", "1 to 49" and "1-10" all mean the same thing on this page: put the small end in From and the large end in To. Nothing else about the range is assumed — both ends are included, negative ends are allowed (useful for drawing a random offset), and a range of exactly one value is legal and will always return that value.
Is this the same as Excel's RAND() or RANDBETWEEN()?
Not the same source, and the difference is worth knowing. Excel's random functions are a pseudorandom generator that was designed for speed and statistical spread, not for being unpredictable, and its exact quality varies with the version and the platform. That is fine for mock data and quick estimates — most spreadsheets have no fairness promise to keep. A draw that has to be defensible — a raffle, a classroom pick, assigning review order — is better served by a cryptographic source whose method is written on the page, which is what this tool uses. We state the method; we cannot audit Microsoft's.
Can I pick giveaway winners with it, and can I draw one at a time?
You can, and the one-at-a-time habit is the one thing to get right. Drawing winners one at a time in independent mode is not the same as drawing N winners at once in distinct mode: drawn independently, the same entrant can win twice and later draws are not conditioned on earlier ones. If each entrant may only win once, use "Distinct numbers" for the full list in one press, or keep drawing in distinct mode with a shrinking count. As for fairness of the draw itself: the sampling is uniform and the method is printed on this page so it can be audited, but whether a particular contest allows this kind of selection is a question about your rules, not about the numbers.
Does it have a spinning wheel?
No, and that is deliberate rather than missing. A wheel is a way of picking from a list of names, and this tool picks numbers. If you have a list — names, tickets, teams — number the entries 1 to N, draw N distinct numbers from 1 to N here, and the numbers select the entries. That is the same job with the mechanics written out: you can see the range, see that no entry repeats, and re-run the check, which a spinning animation does not let you do.
How is this different from random.org?
Both are uniform; the difference is where the randomness comes from and what has to be trusted. random.org generates its numbers from atmospheric noise on their servers, so the page depends on a network service and on their account of their hardware. This page draws from the cryptographic generator already inside your browser, in the tab you have open, with no request to anyone. For a classroom draw the two are interchangeable; for "I do not want to send anything to anyone" the local one is the only one that qualifies.
Are the numbers uploaded, logged or stored anywhere?
No. The page is a static file that imports one module of pure functions; the draw, the rejection sampling and the tally all run in the tab you already have open. There is no request to our server, no analytics event carrying your range, no cookie and no storage, which is also why there is no usage limit — a draw costs us nothing. Reload the page and everything is gone, because it was never anywhere else.

No sampling code ships in this page. Every draw, every bound and every rejection above comes from the same module of pure functions the test suite runs against a fixed byte source, so the numbers on your screen and the numbers in the tests cannot disagree.