Provably fair
Provably fair is a way to prove a round’s result was fixed before you bet and not swapped afterwards. Kapitan publishes the SHA-256 fingerprint of a secret seed in advance, mixes that seed with yours, and reveals it once its rounds are played. Anyone can then redo the math and compare it with the recorded result.
How it works
- A fingerprint before you bet. The server picks a random secret seed for the next 100 rounds and publishes its SHA-256 hash straight away. Changing the seed later would change the hash.
- Your seed. Results in every game but Crash also depend on a seed you choose, so the server can’t pick an outcome for you. Crash rounds are shared by everyone, so they use one public seed:
crash. - The reveal. Once the seed’s rounds are played (or the server restarts), the secret seed is published, and anyone can recompute each of those rounds from it. A Mines game still going on the seed keeps it locked until it ends.
The formula
Each round computes HMAC-SHA256, keyed with the secret seed, of the string your_seed:round_number. The round number is one counter shared by all games and players. The first 4 bytes of the result divided by 232 give a number r between 0 and 1.
- Crash: multiplier = (1 − house edge) / (1 − r), rounded down to two decimals, at least 1.00x and at most 1000x. The edge is 10% unless the round recorded another.
- Dice: roll = ⌊r × 100⌋ + 1, from 1 to 100.
- Plinko: for row i, byte 4 + i decides the bounce: even goes left, odd goes right. The bucket is the number of right bounces; its multiplier comes from the chosen board’s table.
- Limbo: result = (1 − house edge) / (1 − r), rounded down to two decimals, at least 1.00x and at most 1000x: the Crash formula with your seed. The edge is recorded with every round (10% now).
- Mines: the tiles are numbered 0 to 24, row by row from the top left. Mine k (from 0) takes rk from the HMAC of
your_seed:round_number:kand picks tile ⌊rk × tiles left⌋ among the tiles not drawn yet, in order.
Check it yourself
This code for Node.js 18+ checks the fingerprint and recomputes a result. Fill in the revealed seed, your seed and the round number: the Provably fair panel shows them under “What we checked”.
const crypto = require('crypto');
// The revealed secret seed and its published fingerprint
const serverSeed = '...';
const fingerprint = '...';
// Your seed ("crash" for Crash) and the round number
const clientSeed = 'crash';
const roundNumber = 123456;
// Does it match the fingerprint published before the round?
console.log(crypto.createHash('sha256').update(serverSeed).digest('hex') === fingerprint);
const hmac = crypto.createHmac('sha256', serverSeed).update(`${clientSeed}:${roundNumber}`).digest();
const r = hmac.readUInt32BE(0) / 2 ** 32;
// Crash
const edge = 0.1;
console.log(Math.min(Math.max(Math.floor(((1 - edge) / (1 - r)) * 100) / 100, 1), 1000));
// Dice
console.log(Math.floor(r * 100) + 1);
// Plinko: 0 is left, 1 is right; the bucket is the number of 1s
const rows = 16;
console.log([...hmac.subarray(4, 4 + rows)].map(b => b % 2));
// Limbo: the result is worked out like a crash point, at the house edge the round recorded
const limboEdge = 0.1;
console.log(Math.min(Math.max(Math.floor(((1 - limboEdge) / (1 - r)) * 100) / 100, 1), 1000));
// Mines: tiles 0-24 row by row from the top left; mine k comes from the HMAC with ":k" on the end
const mines = 3; // How many mines the board had
const left = [...Array(25).keys()];
const board = [];
for (let k = 0; k < mines; k++) {
const rk = crypto.createHmac('sha256', serverSeed).update(`${clientSeed}:${roundNumber}:${k}`).digest().readUInt32BE(0) / 2 ** 32;
board.push(left.splice(Math.floor(rk * left.length), 1)[0]);
}
console.log(board.sort((a, b) => a - b));
One-click check
Every game has a Provably fair panel under it. Tap one of your recent results or type a round ID: the panel checks the revealed seed against the published fingerprint right in your browser and shows whether recomputing the round gives the recorded result. For a fully independent check, use the code above.
Play Crash · Dice · Plinko · Mines · Limbo
Frequently asked questions
Why isn’t the secret seed revealed straight away?
While a seed is in use, it could be used to work out the rounds still to come. So it is only revealed once all of its 100 rounds are played, or the server restarts, and not while a Mines game played on it is still going, since it would give away where the mines are.
Could the casino pick a seed to suit my bet?
No. The seed’s fingerprint is published before you bet, and the seed can’t be changed without changing the fingerprint. Every game but Crash also mixes in your own seed, which you can change whenever you like.
How is the round number different from the round ID?
The round number is the counter shared by all games and players, and it goes into the formula. The ID is the record of your bet, used to look the round up in the panel. The panel shows both.