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
Key terms
- Limbo
- A game where you pick a target multiplier and win when the generated result reaches or beats it.
- HMAC
- A hash function that takes a secret key; provably fair games run HMAC-SHA256 over the server seed, client seed and nonce.
- SHA-256
- A cryptographic hash that maps any input to a fixed 256-bit digest; casinos use it to commit to server seeds.
- Server seed
- The casino's secret random value that, together with your client seed and the nonce, decides each bet result.
- Hashed server seed
- The SHA-256 digest of the casino's secret server seed, published before any bet as proof the seed is locked in.
- Client seed
- The player's own input to every provably fair result, set or edited by you so the casino cannot work out outcomes in advance.
- Nonce
- A bet counter that goes up by one for each wager on the same seed pair, so no two bets share a result.
- House edge
- The average percentage of every wager that a game is built to keep for the casino.
- Return to player (RTP)
- The share of all money staked that a game is designed to return to players across a very large number of rounds.
- Volatility
- How sharply a game's results swing: high volatility brings rare big wins, low volatility brings frequent small ones.
- Crash game
- A round-based game with a multiplier that climbs from 1x until it crashes; you win only if you cash out first.
- 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.