CS2GamblingReviews

Fairness & odds11 min read

Provably Fair Explained: How to Verify a CS2 Case Roll Yourself

Server seeds, client seeds, nonces and HMAC-SHA256 in plain English, plus a full worked example that turns a revealed seed into a case roll you can check with free tools.

Orange Kilowatt weapon case floating above a dark blue grid

Almost every CS2 gambling site has a "provably fair" badge on its case pages. Very few players ever click it. That's a shame, because the check takes about ten minutes the first time and under two once you know where everything lives, and it's the one part of a site's fairness story you can confirm without taking anybody's word for it.

Below is what the system does, the math in plain terms, and a worked example with real hashes you can reproduce yourself. The red flags we keep finding on fairness pages are in here too.

What provably fair proves, and what it doesn't

Provably fair is a commitment scheme. Before you bet, the site locks in a secret value and shows you a fingerprint of it. After you bet, it reveals the secret. You check that the fingerprint matches, and that the secret combined with your own input produces the result you got. If both checks pass, the site could not have changed the outcome after seeing your bet.

That's a real guarantee. It's also narrower than the badge suggests. Provably fair does not tell you:

  • Whether the odds table is generous. A case can be perfectly provably fair and still return 85 cents on the dollar.
  • Whether the prices the site puts on items match what they'd fetch on a real market.
  • Whether the site will actually process your withdrawal.
  • Whether the item list you saw is the one your roll was mapped against. Good sites publish this per case, but it's a separate trust question.

So treat it as one box on the checklist. It rules out the crude cheat, a site quietly turning your knife roll into a P250. It says nothing about the slow, perfectly legal squeeze of a high house edge. For that side of things, read our breakdown of case odds and expected value.

The four pieces: server seed, hash, client seed, nonce

Every implementation I've seen on a CS2 site uses the same parts, even when the labels change.

PieceWho controls itWhen you see itWhat it does
Server seedThe siteOnly after you rotate itThe secret half of the randomness
Server seed hashThe siteBefore you playA SHA-256 fingerprint that locks the server seed in place
Client seedYouAny time, and you can edit itYour half of the randomness, so the site can't pre-pick outcomes
NonceAn automatic counterNext to each bet in your historyGoes up by one per bet, so every roll on a seed pair is different

The server seed is usually a long random hex string (64 characters is common). The site generates it, keeps it private and publishes its SHA-256 hash. SHA-256 is a one-way function: easy to compute from the seed, practically impossible to reverse, and nobody has ever found two different inputs that give the same output. Once the hash is public, the site is stuck with that seed.

The client seed is the part people skip. Most sites fill it in randomly by default, which is fine, but change it at least once to something you typed yourself. The site committed to its server seed before it knew yours. If it can't predict your client seed, it can't go hunting for a server seed that happens to give you bad results.

The nonce is a plain counter. Your first bet on a fresh seed pair is nonce 0 or 1 depending on the site, the next is one higher, and so on. Without it, every bet on the same seeds would produce the same roll.

Why the hash has to come first

Think of a sealed envelope. The site writes its number on a card, seals it, and hands you the envelope. Then you say your own number out loud. The result is calculated from both. At the end, you open the envelope and check the card.

The order is the whole trick. If the site could see your client seed before committing, it could keep generating server seeds until it found one that sent your next ten openings to the cheapest item. A site that only shows the server seed hash after you've played is not provably fair in any useful sense, whatever its footer says.

There's a second half to the order. You can only verify a server seed once it's been revealed, and a site will only reveal it after you rotate to a new one, because showing the active seed would let you calculate every future roll in advance. So the rhythm never changes: play on a seed pair, rotate, collect the old server seed, check.

How the seeds become a number

The standard method on CS2 sites is HMAC-SHA256. HMAC is a way of hashing a message with a secret key. Here the key is the server seed and the message is built from your client seed and the nonce, often joined with a colon, like clientseed:nonce. Some sites use a dash. Some add a round or cursor number for games that need several random values per bet. The exact format should be printed on the site's fairness page, and if it isn't, that already counts against the site.

The HMAC output is 64 hex characters, which is 256 bits of noise. The site needs a usable number from it, like a ticket between 1 and 100,000 for a case. The most common conversion goes like this:

  1. Take the first 8 hex characters of the HMAC.
  2. Convert them to a decimal integer. Eight hex characters give a number from 0 to 4,294,967,295.
  3. Divide by 4,294,967,296 (2 to the power of 32). You now have a decimal between 0 and 1.
  4. Multiply by the size of the range and round down. For a 1 to 100,000 ticket system, multiply by 100,000, round down, then add 1.

Some sites use more characters or a slightly different conversion. The logic doesn't change.

Worked example: verifying a case opening by hand

Here's the whole process start to finish. I generated these seeds for this article, they don't come from any site, but every number is real. Paste them into any HMAC-SHA256 tool and you'll get exactly what I got. The case is a made-up $5 case with a 1 to 100,000 ticket table, which is how most case-opening sites map rolls to items.

Step 1: Before you open anything, save the hash

Open the fairness settings on the site. You'll see the hashed server seed for your current pair. Copy it somewhere outside the site (a notes app is fine). In our example:

Server seed hash: 0fd86be607ce2cf0ddf3076fc334a964225f16e03817099ababde42d1d34abce

Step 2: Set your own client seed

Change the client seed to anything you made up. I used dust2-on-a-tuesday. On many sites, saving a new client seed also starts a fresh seed pair, so look at the server seed hash again afterwards and copy the new one if it changed.

Step 3: Open the case and note the nonce

Open a case. Your bet history should show the nonce for that opening. Ours is nonce 1. Write down what you won. In our made-up case, the site handed us a Glock-18 skin.

Step 4: Rotate the seed and grab the revealed server seed

Click rotate (sometimes labeled "change seed" or "reveal"). The old server seed now appears in plain text, usually in your seed history:

Server seed: 7f2c9e41b8d03a56e1f4c7b29d8a0e35f6b1c4d7e2a9f3086b5c1d4e7a2f9b03

Step 5: Hash the revealed seed and compare

Run the revealed seed through any SHA-256 tool. Hash it as text, which is what most sites do; a few hash the raw bytes instead, and the fairness page should say which. The result:

0fd86be607ce2cf0ddf3076fc334a964225f16e03817099ababde42d1d34abce

That matches the hash saved in step 1, character for character. The site didn't swap the seed. If even one character differs, stop. Either the site changed the seed or you copied the wrong hash, and you need to know which before you play there again.

Step 6: Calculate the HMAC

Now open an HMAC-SHA256 tool. Key: the server seed. Message: dust2-on-a-tuesday:1. Output:

b2ce8b11df15feef0133b035688b3cdb9292ebeff0953b0ffac72529e3b76a97

Step 7: Convert it to a ticket

The first 8 characters are b2ce8b11. In decimal that's 2,999,880,465. Divide by 4,294,967,296 and you get 0.698464. Multiply by 100,000, round down to 69,846, add 1. Your roll is ticket 69,847.

Step 8: Map the ticket to the item

Here's the case's published table:

ItemSite priceChanceTickets
Karambit (top item)$520.000.20%1 to 200
AK-47 skin$60.001.50%201 to 1,700
AWP skin$14.006.30%1,701 to 8,000
M4A1-S skin$4.2022.00%8,001 to 30,000
Glock-18 skin$1.5040.00%30,001 to 70,000
P250 skin$0.4030.00%70,001 to 100,000

Ticket 69,847 sits inside the Glock range, near the top of it. The site gave us the Glock. Verified.

Look at that table once more before moving on. Multiply each price by its chance and add the results: you get an expected value of about $4.47 on a $5 case. This case returns roughly 89% on average. Every roll can be honest and you'll still lose about 53 cents per opening over the long run. That's the gap between fair and favorable, and no amount of hashing closes it.

Variations you'll run into

The worked example is the most common pattern, but don't be thrown by these.

The five-character method

Some sites read 5 hex characters at a time instead of 8. Five characters give a number up to 1,048,575. If it's under 1,000,000, they divide by 10,000 to get a roll from 0.00 to 99.99. If it's 1,000,000 or higher, they throw it away and read the next five characters. The rejection step exists to avoid a small bias toward low numbers. It looks strange the first time you see it, but it's sound.

Crash and other shared rounds

Crash usually reads more of the hash (13 hex characters, or 52 bits, is a common choice) and runs it through a formula that turns a uniform number into a multiplier, with the house edge built in as a small chance of an instant bust. Because one crash round is shared by everyone, there's no personal client seed. Sites instead pre-generate a long chain of hashes, publish the final one, and play the chain backwards, so each round's seed hashes to the round after it. Some mix in a public value nobody controls, such as a future blockchain block hash. Our crash myths article explains why none of this lets anyone predict the next round.

Case battles

Battles involve several players and several cases, so a single personal client seed doesn't work either. The usual setup is a server seed committed when the battle is created, combined with a public seed that only appears after every slot fills (often a block hash), plus the round and seat number in the message. Same idea, more inputs. There's more on how battles work in our case battles guide.

Upgraders

An upgrader roll is a single number checked against your win chance. Land under your percentage (or over it, depending on which side you picked) and you win. It's the easiest game to verify. The harder question is whether the displayed chance matches the price ratio of the two items, which we cover in skin upgrader odds.

Checking without trusting the site's own verifier

Most sites have a built-in verify button. It's convenient, but think about what it is: the site's own code telling you the site is honest. Use it if you like, then do an independent check at least once on any site where you deposit real money.

You don't need special software:

  • Any SHA-256 and HMAC-SHA256 tool. There are plenty of free web ones. Only paste revealed (old) server seeds into third-party tools. The site won't show you the active one anyway.
  • A spreadsheet for the conversion. In Excel or Google Sheets, =HEX2DEC("b2ce8b11")/4294967296 returns the 0.698 from step 7.
  • Python, if you have it. The standard library covers everything. hmac.new(server_seed.encode(), f"{client_seed}:{nonce}".encode(), hashlib.sha256).hexdigest() returns the HMAC from step 6.

Check a batch, not one bet. Pick five or ten openings from the same seed pair and make sure at least one went badly for you. If a site were going to cheat, that's where it would show.

Red flags on a fairness page

If a site only shows the server seed hash after the bet, or won't let you set your own client seed, its provably fair claim is decoration. Don't deposit on the strength of the badge.

Things that cost a site points in our reviews:

  • No published formula. A verify button and "our games are provably fair", with no explanation of how a roll is computed.
  • No way to rotate the server seed yourself, or rotation only on the site's schedule.
  • A client seed you can't edit, or one the site resets without telling you.
  • A nonce that skips numbers or resets halfway through a pair.
  • Case odds hidden until after you open, or item tables that change without notice. A fair roll against a table you can't see isn't worth much.
  • Battles or crash rounds with no public seed or hash chain explained anywhere.

The bigger sites we've reviewed, including CSGOEmpire, CSGORoll and Clash.gg, publish their methods and let you rotate and verify. That doesn't make them generous. It means the rolls are checkable, which should be the floor, not a selling point. Fairness is one input to our trust score, and how we rate sites covers the rest.

Four things people get wrong about it

"I lost ten in a row, so it's rigged." Streaks happen. On a 50/50 game, ten straight losses come up about once in every 1,024 runs of ten bets. With thousands of players a day, plenty of people see one. Verify the rolls. If they check out, it was variance.

"A new client seed will change my luck." It changes which rolls you get, not the odds behind them. A new client seed is a fresh shuffle of the same deck.

"The site can still cheat by choosing which server seed I get." Only if it knows your client seed in advance, which is exactly why you set your own after the hash is shown.

"Provably fair means I'll break even eventually." No. The house edge lives in the odds table, and verification doesn't touch it. Over enough openings your results drift toward the case's expected value, and on every site we've looked at, that's below the price.

Our routine before trusting a new site

If you're about to deposit somewhere for the first time, this is what we do, and it fits in a coffee break:

  1. Read the fairness page and find the exact formula and message format. If you can't find them, go elsewhere.
  2. Copy the current server seed hash before playing anything.
  3. Set a client seed of your own.
  4. Play a few small bets, like the cheapest case or a minimum upgrade, and note the nonces.
  5. Rotate the seed, hash the revealed seed and compare it with the hash you saved.
  6. Recompute two or three rolls by hand with a tool the site doesn't control.
  7. Work out the expected value of the case from its odds table, so you know what "fair" is costing you per opening.

Then set a budget you're fine losing, because step 7 tells you that's where things trend. Gambling on these sites is 18+ only, and if it has stopped feeling like entertainment, our responsible gambling page lists free, confidential help.

Keep reading

Treat it as entertainment, not income

Every game on these sites has a house edge, so over time the site wins. Decide on a budget before you deposit, use deposit limits where they exist, and step away the moment it stops being fun.

Responsible gambling tools and help