Are Online Dice Rollers Truly Random? We Rolled Each Die 1,000,000 Times
Yes, a well-built online dice roller is fair. We rolled each of the seven D&D dice 1,000,000 times with the exact code our roller uses, and every face came up within a tenth of a percentage point of its expected share. Chi-square tests found no evidence of bias. The roller draws numbers from the browser's cryptographic random generator.
How does an online dice roller pick a number?
A computer cannot throw a die, so a dice roller asks a random number generator for a number and maps it onto the faces. How good the roller is depends on two things: the quality of that generator, and how the number is turned into a face.
- The generator: our roller uses
crypto.getRandomValues, the cryptographically secure random number generator built into every modern browser. It is the same source browsers use for encryption keys, and it is designed so its output cannot be predicted. Many simple rollers useMath.random, which is fine for games but is not designed to be unpredictable. - The mapping: the generator produces a whole number between 0 and 4,294,967,295. Dividing that range evenly into 20 faces almost works, but 4,294,967,296 is not a multiple of 20, so a few faces would get one extra chance in four billion. Our roller throws away the handful of numbers at the very top of the range and draws again (called rejection sampling), so every face gets exactly the same number of chances.
- Where it runs: every roll happens in your browser. Nothing is sent to a server, so nobody, including us, can change a result.
How did we test it?
We took the roller's actual dice function, the same rollDie code the d20 roller and every other roller on this site load, and ran it 1,000,000 times for each of the seven standard D&D dice, 7,000,000 rolls in total. The test ran in Node.js 24.18.0, which provides the same crypto.getRandomValues interface as a browser. For each die we counted how often every face came up and ran a chi-square goodness-of-fit test, the standard check for whether observed counts match the counts a fair die should give.
Results: every die came out fair
| Die | Average roll | Expected | Rarest face | Most common face | Expected share | Chi-square | p-value |
|---|---|---|---|---|---|---|---|
| d4 | 2.5007 | 2.5 | 24.934% | 25.042% | 25% | 3.19 (3 df) | 0.363 |
| d6 | 3.5019 | 3.5 | 16.596% | 16.692% | 16.667% | 3.7 (5 df) | 0.593 |
| d8 | 4.4923 | 4.5 | 12.443% | 12.596% | 12.5% | 15.34 (7 df) | 0.032 |
| d10 | 5.5008 | 5.5 | 9.939% | 10.053% | 10% | 10.25 (9 df) | 0.33 |
| d12 | 6.4956 | 6.5 | 8.277% | 8.364% | 8.333% | 8.55 (11 df) | 0.663 |
| d20 | 10.5025 | 10.5 | 4.966% | 5.057% | 5% | 21.22 (19 df) | 0.325 |
| d100 | 50.4958 | 50.5 | 0.972% | 1.028% | 1% | 117.96 (99 df) | 0.094 |
Every average landed within 0.01 of the true average, and every face of every die came up within a tenth of a percentage point of its fair share. On the d20, for example, the least common face appeared 4.966% of the time and the most common 5.057%, against an expected 5%.
What does a million d20 rolls look like?
| Face | Times rolled | Share | Distribution |
|---|---|---|---|
| 1 | 49,864 | 4.986% | |
| 2 | 49,897 | 4.990% | |
| 3 | 50,200 | 5.020% | |
| 4 | 50,232 | 5.023% | |
| 5 | 49,848 | 4.985% | |
| 6 | 49,948 | 4.995% | |
| 7 | 50,021 | 5.002% | |
| 8 | 50,052 | 5.005% | |
| 9 | 49,659 | 4.966% | |
| 10 | 50,190 | 5.019% | |
| 11 | 49,812 | 4.981% | |
| 12 | 49,882 | 4.988% | |
| 13 | 50,005 | 5.001% | |
| 14 | 50,321 | 5.032% | |
| 15 | 50,306 | 5.031% | |
| 16 | 49,840 | 4.984% | |
| 17 | 49,657 | 4.966% | |
| 18 | 49,881 | 4.988% | |
| 19 | 49,819 | 4.982% | |
| 20 | 50,566 | 5.057% |
A fair d20 should show each face 50,000 times out of a million. Random variation of a few hundred either way is exactly what chance predicts: the typical wobble for a count like this is about ±218.
What about the d8's low p-value?
A p-value answers the question "if the die were perfectly fair, how often would results look at least this uneven?" Six of our seven dice scored between 0.09 and 0.66, comfortably normal. The d8 scored 0.032, which would happen about 3 times in 100 with a perfectly fair die.
That sounds suspicious until you remember we ran seven tests. With seven fair dice, the chance that at least one of them scores below 0.05 is about 30%. One low score among seven is expected, and it is why statisticians correct for multiple tests. Looking at the d8 directly, its rarest face came up 12.443% of the time and its most common 12.596%, against an expected 12.5%. We are publishing the run exactly as it came out rather than rerunning until every number looks tidy.
Do streaks mean the roller is broken?
Players often suspect a roller when it gives the same number several times in a row. Real randomness is streakier than people expect. In a separate run of 1,000,000 d20 rolls:
- Natural 20s: 50,354, or 5.04%, against an expected 5%. See the odds of rolling a natural 20.
- Longest run of the same number: 6 identical rolls in a row.
- Longest wait for a 20: 229 rolls without a single natural 20.
None of these is a sign of a problem. Over a million rolls, a run of five or six identical results and droughts of a couple of hundred rolls are what a fair die produces. A short session simply doesn't contain enough rolls for the streaks to even out.
Can you reproduce the test?
Yes. Open any dice roller on this site, such as the d20 roller, and paste this into your browser's developer console; it uses the same function the rollers use and counts 100,000 d20 rolls:
const counts = Array(21).fill(0);
for (let i = 0; i < 100000; i++) counts[rollDie(20)]++;
console.table(counts.slice(1).map((n, i) => ({ face: i + 1, share: (n / 1000).toFixed(2) + '%' })));
Want the theory instead of a simulation? The dice probability calculator gives the exact odds for any roll, and our comparison of dice roller apps and physical dice covers when each is the better choice.
FAQ
Are online dice rollers rigged?
A roller built on a cryptographic random number generator is not rigged and cannot be predicted. In our test of 7,000,000 rolls, every face of every die came up at its expected rate within normal random variation.
Is Math.random good enough for dice?
For casual use it is usually fine, but it is not designed to be unpredictable, and the common Math.floor(Math.random() * sides) pattern is not guaranteed to be perfectly even. crypto.getRandomValues is built for unpredictability, and with rejection sampling every face is exactly equally likely.
Are online dice more random than real dice?
Online dice from a good generator are at least as fair as physical dice, and they cannot be worn, chipped, unbalanced by air bubbles or thrown with a practised technique. Precision-made casino dice are also very fair; cheap plastic dice can have small biases.
Can I check the results myself?
Yes. The roller runs in your browser, so you can read its code in your browser's developer tools, and the short script on this page reproduces the test.
Related
- Roll a d20
- Dice Roller App vs Physical Dice: Which Should You Use?
- Dice Probability Calculator
- Odds of Rolling a Natural 20 (and with Advantage)
Wizards of the Coast LLC is the trademark holder for Dungeons & Dragons, Wizards of the Coast, and their respective logos worldwide.
Wizards of the Coast LLC does not support, endorse, approve, or have any affiliation with DnD Dice Roller. According to the Wizards of the Coast LLC's Fan Site Policy, DnD Dice Roller may use its trademarks and other intellectual property. Please visit Wizards of the Coast's website at www.wizards.com if you want additional information about the company, its trademarks, or other intellectual property.
Contains content from the System Reference Document 5.1 and 5.2 by Wizards of the Coast LLC, used under the Creative Commons Attribution 4.0 International License.