Dice and Coin Roller

Roll any combination of tabletop dice or flip up to 1000 coins. The notation is standard: 2d6, 1d20+5, 4d6kh3 to roll four six-sided dice and keep the best three. Every result is drawn from the browser's cryptographic random source, with modulo bias stripped out by rejection sampling, so the odds are exactly what they should be.

Explain like I'm 5 (what even is this calculator?)

It rolls dice for you, or flips coins, when you can't be bothered to find a real one or you don't trust whoever did. The result is fair, you can see how the page got there, and nothing about the roll leaves your device.

Roll something

Browser-only. The roller never calls a server. Picks come from the Web Crypto API.

Format: count d sides ± modifier, optionally kh or kl for keep-highest / keep-lowest. Caps: 100 dice, sides 2-1000.

Quick rolls

A preset replaces the notation field and rolls immediately.

Pick a mode and roll.

Prove it

Every die face and every coin flip is drawn from crypto.getRandomValues, the browser's cryptographic random source. The same primitive your bank's website uses to generate session keys.

The naive rand % n reduction introduces bias: if 2^32 is not an exact multiple of n, the lower remainders show up slightly more often. We avoid that with rejection sampling. Any draw above the largest multiple of n that fits in 2^32 is discarded and re-drawn. The expected number of redraws per face is at most 1, even on a d1000.

For dice, every individual die's face is shown alongside the sum so you can audit the result. If you used kh or kl, the kept dice are highlighted: the others were rolled and discarded, exactly as the notation specifies.

For coins, the page does the same trick on a 2-sided draw: the H/T sequence is the raw output, and the heads/tails counters are derived from it.

// Unbiased integer in [0, n)
function randomInt(n) {
  const max = 0xFFFFFFFF;
  const limit = max - ((max + 1) % n);
  const buf = new Uint32Array(1);
  while (true) {
    crypto.getRandomValues(buf);
    if (buf[0] <= limit) return buf[0] % n;
  }
}

// d-sided die
const face = randomInt(sides) + 1;

// Coin flip
const flip = randomInt(2) === 0 ? 'H' : 'T';

Nothing leaves the device. The page makes no network requests after it loads, so the result is unpredictable to the operator and the user alike: it is whatever the browser's RNG happened to produce, and nobody else gets to see it. Disconnect your network and roll again to confirm.

Useful? Save this calculator: press Ctrl + D to bookmark it.

Roll history

The last 20 rolls in this session. Cleared when you refresh.

    No rolls yet.

    When a fair roll actually matters

    Tabletop roleplaying is the obvious case. A D&D character's ability scores are traditionally 4d6, drop the lowest, repeated six times. A loaded RNG that quietly favours the top of the range hands the player a paladin who is good at everything and breaks the campaign's balance for the next year. The same applies to to-hit rolls, saving throws, damage dice, and the dramatic d20 at the table. If you forgot your dice bag at home, this page is a clean substitute that nobody at the table can accuse of fixing the result.

    Classroom probability lessons are the other strong fit. Asking a class to predict the distribution of 100 d6 rolls and then actually doing the experiment in front of them is a better lesson than any textbook chart. The roll history makes it easy to read the results back. Same for coins: 1000 flips, count the heads, plot it. The point of the demo, that the empirical distribution converges to the theoretical one as N grows, lands harder when the students see it happen on a tool that they know is fair.

    Settling decisions is the underrated use. Two reasonable choices, neither side budging, the discussion going round in circles. Open this page, flip a coin, get on with the day. The tool removes the social cost of someone "deciding": the coin decided. If the loser feels strongly enough to argue with the result, the question wasn't actually 50/50 and you have new information.

    Why Web Crypto for a dice tool

    It is overkill, and that is the point. Math.random in modern browsers is a high-quality pseudo-random sequence, perfectly fine for animation timing and shuffle effects. It is not, by spec, cryptographically secure. A determined operator could in theory predict the next output from a sequence of past outputs. For a casual roll on a casual page that does not matter. For a tool where someone might use the result to settle a small bet, allocate the last slice of cake, or generate a character that will define a year of weekly Friday-night sessions, it does. Web Crypto plus rejection sampling is the cheap, audited, by-the-book way to make the result genuinely uniform. The Prove it panel above shows the exact code so a sceptical user can read it and decide for themselves.

    Common mistakes to avoid

    Misreading the notation is the most frequent. 2d6 is two six-sided dice (range 2 to 12). d12 is one twelve-sided die (range 1 to 12). They look similar and produce very different distributions: 2d6 is bell-shaped and centred on 7, d12 is flat. If you are rolling for a game where the curve matters, double-check which one you actually wanted.

    Using keep-highest with the wrong number is the second. 4d6kh3 rolls four dice and keeps the best three: it is the classic D&D 5e ability-score roll. 4d6kh4 would be the same as plain 4d6: there is nothing to drop. The page will reject 3d6kh4 outright because you cannot keep four out of three.

    Asking for a million coins is the third. The cap is 1000 per flip session for sanity reasons, both for the page DOM and to keep the on-screen sequence readable. If you genuinely want to simulate a million coin flips for a probability demo, run the page in a script (the library is exported on window.DiceAndCoinRoller) or run it in batches and add up the totals.

    Edge cases this page handles

    • Modifier of zero. 1d20+0 works and resolves to 1d20.
    • Negative modifier. 1d20-2 subtracts 2 from the roll. Total can be 0 or negative on a low roll.
    • Keep more than rolled. Rejected at parse time with a clear message.
    • Single coin. One H or one T, no statistical waffle.
    • 1000 coins. Summary stats only; per-flip sequence omitted to keep the page responsive.
    • 50-or-fewer coins. Per-flip sequence shown alongside the summary.
    • History full. Oldest roll drops off as the 21st roll lands, so the list never grows past 20.

    Related calculators

    Dice and coins are one kind of random. These cover the others.

    Frequently asked questions

    Is the roll actually random?

    Yes. Every die face and coin flip is drawn from crypto.getRandomValues, the cryptographically strong random source the browser uses for session keys. Modulo bias is removed with rejection sampling, so a d6 face is exactly 1-in-6 and a coin flip is exactly 50/50. There is no Math.random anywhere in the page.

    What dice notation does it understand?

    Standard tabletop notation: count d sides, with an optional modifier and an optional keep-highest or keep-lowest. Examples: d6 (one six-sided die), 3d8 (three eight-sided), 1d20+5 (a d20 with a +5 bonus), 4d6kh3 (four six-sided dice, keep the best three, used for D&D ability scores). Hard caps: 100 dice, 1000 sides per die.

    Does anything I roll get sent anywhere?

    No. The page makes no network calls during a roll. You can disconnect from the network and the roller still works. Open your browser's network tab and watch nothing happen as you roll.

    Why use Web Crypto for a dice roller?

    It is overkill for a casual roll, and the right call for one people might use to settle a real bet, allocate sweets, or generate a tabletop character. Math.random is a non-cryptographic pseudo-random sequence: fine for shuffling visuals, not fine if anyone might suspect the result is rigged. Web Crypto plus rejection sampling produces a draw that is provably uniform.

    How is roll history stored?

    In memory for the life of the page. The last 20 rolls are kept and displayed in the History panel. Refresh the page or click Clear history and the list is gone. Nothing is persisted to disk and nothing is sent off the device.