Provably fair limbo explained step by step
What you will be able to do
Limbo is one of the simplest provably fair games. You pick a target multiplier, the game draws a result multiplier, and you win if the result reaches your target. By the end of this guide you will be able to take a limbo bet's seeds and nonce and work out the result yourself, and see exactly where the house edge sits in the formula.
We use the scheme BC.Game publishes on its own help centre, because it documents every step. Other casinos use different conversions, covered further down, so always check the casino's own fairness page before you rely on a formula. You can run the numbers in our verifier.
The scheme in one block
- Random value:
HMAC-SHA256with the server seed as key andclientSeed:nonceas the message, output as hex. - Float: the first 13 hex characters as a number, divided by 2^52 (4,503,599,627,370,496).
- Raw multiplier:
99 / (1 - float). - Result: anything below 100 becomes 100, then drop the decimals and divide by 100.
The 99 in the numerator is the 1% house edge. Without it, the formula would be 100 / (1 - float) and the game would return 100% over time.
The inputs
| Input | Value |
|---|---|
| Server seed (revealed after rotation) | 5f0c9a2e71d84b36ae19c07f4d62b8e135a7f90c2d4e6b81f3a5c79e0b2d4f61 |
| Hashed server seed (shown before play) | 4c579aec56867abda520509a69195ccce33f614b735e55d0e498e6c502b9a1b1 |
| Client seed | harbour-light-77 |
| Nonce | 0 |
| Target multiplier | 1.50 |
These are example seeds made up for this guide. We computed every number below in Python with the standard hmac and hashlib modules.
Step 1: check the commitment
Hash the revealed server seed as text with SHA-256:
SHA-256("5f0c9a2e...0b2d4f61") = 4c579aec56867abda520509a69195ccce33f614b735e55d0e498e6c502b9a1b1
It matches the hashed server seed shown before play, so the casino used the seed it committed to. If this fails, stop: nothing after it means anything. Our guide on server seed hashing explains the usual causes of a false mismatch, such as hashing the wrong seed from the list.
Step 2: compute the HMAC
Build the message by joining the client seed and nonce with a colon:
harbour-light-77:0
Compute HMAC-SHA256 with the server seed as the key and that message. The result is 64 hex characters. The first 13 are:
66ce29aa3d425
BC.Game's page writes the call as HMAC_SHA256(clientSeed:nonce, serverSeed). Notation for which argument is the key differs between libraries, so if your first attempt does not match, swap key and message once before assuming anything is wrong.
Step 3: turn the hex into a float
Thirteen hex characters hold 52 bits. Convert them to a whole number:
0x66ce29aa3d425 = 1,808,570,373,100,581
Divide by 2^52:
1,808,570,373,100,581 / 4,503,599,627,370,496 = 0.401583293974
That is your float, a number between 0 and 1.
Step 4: apply the limbo formula
99 / (1 - 0.401583293974) = 165.436558
Step 5: floor and scale
The value is above 100, so no floor applies. Drop the decimals to get 165, then divide by 100:
Result: 1.65x
BC.Game's text says the number is rounded, but its own worked example turns 170.46 into 1.70, which is truncation. We follow the example. The difference only matters when the raw value ends in .5 or more, so if your answer is 0.01 higher than the casino's, this is the reason.
Step 6: compare with your target
The target was 1.50. The result 1.65 is at or above it, so the bet wins and pays 1.50 times the stake. A result of 1.49 would lose. The casino's own rules decide whether a result exactly equal to the target wins; at most casinos it does, but check.
The next bets in the same seed pair
Each new bet adds 1 to the nonce. Same server seed and client seed:
| Nonce | First 13 hex | Float | Raw | Result |
|---|---|---|---|---|
| 0 | 66ce29aa3d425 | 0.401583 | 165.44 | 1.65 |
| 1 | b77f5bb0f06f4 | 0.716787 | 349.56 | 3.49 |
| 2 | 6ec79a3568bf2 | 0.432733 | 174.52 | 1.74 |
| 3 | f53a17979cba6 | 0.957918 | 2,352.53 | 23.52 |
| 4 | a81cdeb7e9be2 | 0.656691 | 288.37 | 2.88 |
| 5 | 1df18e3eb288c | 0.116967 | 112.11 | 1.12 |
Notice how a float near 1 (nonce 3) produces a large multiplier. As the float approaches 1, 1 - float approaches zero and the multiplier grows without a fixed ceiling. In practice casinos cap the maximum payout in their terms.
Where the house edge shows up
The result reaches a target t when 99 / (1 - float) is at least 100 x t. Rearranged, the float must be at least 1 - 0.99 / t. Since the float is uniform between 0 and 1, the chance of winning is:
win chance = 0.99 / t
| Target | Fair chance (1 / t) | Actual chance (0.99 / t) |
|---|---|---|
| 1.50x | 66.67% | 66.00% |
| 2.00x | 50.00% | 49.50% |
| 10.00x | 10.00% | 9.90% |
| 100.00x | 1.00% | 0.99% |
At every target, the chance is 99% of the fair chance, and the payout is the target itself. So the expected return on each bet is 99% of the stake, a 1% edge, whatever target you pick. Changing the target changes the volatility, not the RTP.
The floor at 1.00 matters too. Any float below 0.01 gives a raw value under 100, which becomes 1.00. A 1.00 result never beats a target above 1.00, so about 1% of all rounds lose at every target. That is the same edge, seen from the other side.
Other limbo formulas you will meet
Not every casino uses BC.Game's conversion. Thrill's help centre, for example, documents limbo as:
multiplier = 1.0 / ((1.0 - randomFloat) x houseEdge), where houseEdge = 2.0 - rtp
with the result truncated to two decimals and a win when the result exceeds the player's guess. With an RTP of 0.99 this divides by 1.01 instead of multiplying by 0.99, which gives almost the same edge. Its limbo section does not show a floor at 1.00, though its crash section on the same page does.
Other casinos build the float from four bytes instead of 13 hex characters, the way our dice walkthrough does, or scale it by a large constant before dividing. The principle is the same each time: a uniform float, a division that turns it into a long-tailed multiplier, and a constant just below 1 that sets the edge. The details decide whether your numbers match, so take them from the casino's own page.
Limbo and crash
Limbo uses the same kind of formula as a crash game. The difference is that limbo gives each player a separate result from their own seeds, while crash usually draws one result per round for everyone, often from a chain of hashed seeds. A limbo result can therefore be checked with your own client seed, which you can change at any time. Our guide on changing your client seed explains why that matters.
The code we used
import hmac, hashlib, math
server_seed = "5f0c9a2e71d84b36ae19c07f4d62b8e135a7f90c2d4e6b81f3a5c79e0b2d4f61"
client_seed = "harbour-light-77"
print(hashlib.sha256(server_seed.encode()).hexdigest())
for nonce in range(6):
msg = f"{client_seed}:{nonce}".encode()
h = hmac.new(server_seed.encode(), msg, hashlib.sha256).hexdigest()
f = int(h[:13], 16) / 2**52
raw = 99 / (1 - f)
result = max(100, math.floor(raw)) / 100
print(nonce, h[:13], round(f, 6), round(raw, 2), result)
Common reasons your result does not match
- Wrong seed. You hashed the seed for a different session. Match the hash first.
- Nonce offset. Some casinos start at 1. Try the neighbouring nonce.
- Key and message swapped. Try once with the arguments reversed.
- Rounding. Truncation versus rounding moves the result by 0.01.
- Different scheme. The casino uses its own conversion. Read its fairness page.
Our guide on verifying a provably fair bet covers the full checklist.
What a match proves, and what it does not
A matching result proves the casino did not change the outcome after you placed the bet, and that it used the formula it published. It does not prove the published formula is fair. That is why the house edge section above matters: read the constant, work out the win chance, and make sure it matches the RTP the casino advertises.
Play within limits
Limbo rounds are fast, and high targets can produce long losing streaks. Set a deposit limit before you play, and use self-exclusion if you need a break.
Sources
Conditions clés
- Limbo
- Un jeu où vous choisissez un multiplicateur cible et gagnez lorsque le résultat généré l'atteint ou le dépasse.
- HMAC
- Une fonction de hachage qui utilise une clé secrète; les jeux provably fair appliquent HMAC-SHA256 à la seed serveur, à la seed client et au nonce.
- SHA-256
- Un hash cryptographique qui transforme n'importe quelle entrée en un condensé fixe de 256 bits; les casinos l'utilisent pour s'engager sur les seeds serveur.
- Seed serveur
- La valeur aléatoire secrète du casino qui, avec votre seed client et le nonce, détermine le résultat de chaque pari.
- Seed serveur hachée
- Le condensé SHA-256 de la seed serveur secrète du casino, publié avant tout pari comme preuve que la seed est figée.
- Seed client
- La contribution du joueur à chaque résultat provably fair, définie ou modifiée par vous pour que le casino ne puisse pas calculer les résultats à l'avance.
- Nonce
- Un compteur de paris qui augmente d'une unité à chaque mise sur la même paire de seeds, pour que deux paris ne partagent jamais le même résultat.
- Avantage de la maison
- Le pourcentage moyen de chaque mise qu'un jeu est conçu pour conserver au profit du casino.
- Taux de retour au joueur (RTP)
- La part de l'argent misé qu'un jeu est conçu pour reverser aux joueurs sur un très grand nombre de parties.
- Volatilité
- L'ampleur des variations des résultats d'un jeu : une volatilité élevée donne de rares gros gains, une volatilité faible de petits gains fréquents.
- Jeu crash
- Jeu par manches avec un multiplicateur qui monte à partir de 1x jusqu'au crash; vous ne gagnez que si vous encaissez avant.
- Target multiplier
- The multiplier a player chooses in limbo or auto cash-out crash; the bet wins if the result reaches it.
- Win chance
- The probability that a bet wins, shown by many provably fair games next to the payout multiplier.
- Random float
- A number between 0 and 1 derived from a provably fair hash, which a game formula turns into a result.