The documentation gap, and what closed it
Skin.club's provably fair page explains what the system does without saying how. It tells you outcomes are random and unaltered, that your roll history is complete, that seed-change history is visible. Its entire technical content is one sentence: the mechanism depends on the server seed, client seed and nonce, which create a roll that defines the result. No hash function, no string format, no conversion.
Signed out, as of October 2026, the page shows less still: two introductory sentences and a prompt to log in, with no formula and no link to one.
The formula is published, just never on that page. It appears in two places, both linked from the page as it read in September 2026, and the validator can be opened directly without an account. A Skin.Club post on Medium, dated July 2020, states the method in prose, and prose leaves gaps: three of them matter enough here to produce a wrong answer with no error message. Since May 2026 there is also a validator at roll.skin.club, backed by a public code repository that publishes the method as runnable PHP along with three worked test values.
That last part is worth more than it sounds. Published code sits at the top of the disclosure hierarchy this site uses: code beats a worked example, an example beats a description, a description beats a badge. Skin.club publishes code and examples. The oddity is purely one of placement, since a reader who opens the page marked "provably fair" finds the badge tier and has to click twice more to reach the code.
The three published test values
All three reproduce here, and they are the fastest way to check any tool, including this one.
| Check | Inputs | Expected |
|---|---|---|
| Case roll | server c4ca4238a0b92382, client my_seed, nonce 4 | 21,752 |
| Commitment | server c4ca4238a0b92382, salt 0dcc509a6f75849b | dc883b29...f493 |
| Battle roll | beacon Tt5qAdTwoTeygDdghVlfEWtNJQkGYg5q, client 12354,abgd, nonce 9 | 5,415 |
Alongside those, a real revealed roll captured from Skin.club's own Check Roll tool on 22 July 2026 confirms the method against a live account rather than a published example: server seed 1862b99dc42ce8a0c05bc458b250bd20, client seed cce4eedfa71787e499c44552981ca48a, nonce 259, roll 66,748. Published examples prove the method. An operator-produced outcome proves the method is what the site actually runs.
The formula, precisely
key = clientSeed-nonce (your seed, dash separator)
message = serverSeed (the site's secret)
|
v
HMAC-SHA512 <-- key and message are the reverse of normal
|
v
first 15 hex characters as an integer
|
v
( integer mod 100,000 ) + 1 = roll from 1 to 100,000
The three traps, in the order to check them
Each produces a plausible wrong number rather than an obvious failure. The figures below all use Skin.club's own published test seeds, so you can run them yourself.
| Wrong assumption | What it returns | Correct |
|---|---|---|
| Conventional key and message | 1,800 | 21,752 |
| Underscore separator | 88,128 | 21,752 |
| Salt fed into the roll | A different wrong number | 21,752 |
Every one of those sits inside the valid 1 to 100,000 range. Nothing about 1,800 announces itself as wrong, and nothing about 88,128 does either. That is the whole difficulty, and it is what this site calls a plausible wrong number.
The HMAC is inverted
Skin.club swaps the roles every other platform gives its seeds. Nearly every provably fair system keys the HMAC with the server seed and passes the client seed and nonce as the message. Skin.club does the opposite: the key is clientSeed-nonce and the message is the server seed.
The separator is a dash
An underscore is the obvious alternative and several platforms use one. Here it is wrong.
The salt is not in the roll
Skin.club exposes a secret salt alongside the seeds, and the obvious assumption is that it feeds the calculation. It does not. The salt exists to key the commitment instead, which is its own trap and gets its own section below.
The commitment is not a plain hash
Even the sealed envelope is sealed differently here. The public hash Skin.club shows before you play is HMAC-SHA256 keyed with the salt over the server seed. It is not a plain SHA-256 of the server seed, and it is not SHA-256 of the server seed concatenated with the salt. Neither reproduces the published hash.
This matters because the commitment check is the half of provably fair that proves the site did not swap its seed after seeing your play. Check it the ordinary way and it fails, and the natural reading of that failure is that Skin.club cheated. It did not. The commitment simply uses a construction most tools do not try. The verifier above runs the correct check automatically.
Fifteen hex characters, and why that is awkward
The awkward part is the size of the piece the formula reads. The slice is the first 15 hex characters of the digest, which is 60 bits of information. That is more than a standard JavaScript number can hold exactly, since ordinary floating-point integers stop being reliable above 53 bits.
A verifier that converts that slice using normal arithmetic will be silently wrong for a portion of rolls: correct most of the time, quietly off in the cases where the top bits matter. Ours runs the conversion through arbitrary-precision integers so the result is exact for every possible digest. Skin.club's own validator makes the same point from the other direction, refusing to run at all on a PHP build that cannot hold the intermediate value.
Where to find your seeds
Four values decide a case check, and one of them only appears after you act.
- The hashed server seed, shown before you play. Save it; this is the commitment.
- Your client seed, editable on the same page.
- The secret salt, exposed alongside the seeds. Needed for the commitment check, never for the roll.
- The nonce for the roll you care about.
All of these live on your account's Provably Fair page, behind a login, and a Verify Roll control on an inventory item shows that roll's specific inputs.
The unhashed server seed appears only for previous seeds, so rotating is what makes past rolls checkable. Skin.club also rotates automatically once the nonce reaches 500, which means a long session eventually makes its own early rolls verifiable without you doing anything. Rotation is not the site being obstructive: a server seed still in use cannot be published, because anyone holding it could compute every remaining outcome in advance.
One convention worth knowing if you use the operator's own validator: a value beginning with * means not yet revealed, and the tool will refuse to verify rather than returning something misleading.
The ticket table is public, which is the unusual part
Most platforms stop at the roll. Skin.club publishes the other half, and it does so without a login.
Open any case page and a "Check odds range" control shows the full ticket table: every item, its price, and the exact block of numbers that wins it. The ranges are contiguous and span exactly 1 to 100,000, matching the roll space.
| Item | Price | Winning range | Stated odds |
|---|---|---|---|
| AK-47 VariCamo Grey (MW) | $0.12 | 1 to 16,200 | 16.200% |
| AK-47 Olive Polycam (MW) | $0.18 | 16,201 to 35,200 | 19.000% |
| AK-47 Uncharted (FT) | $0.61 | 35,201 to 50,200 | 15.000% |
| AK-47 Redline (MW) | $152.24 | 99,951 to 99,960 | 0.010% |
| AK-47 Fuel Injector (FT) | $166.46 | 99,961 to 99,970 | 0.010% |
Read the scarce end of that table and the structure of the thing becomes obvious: a 0.010% item holds exactly ten numbers out of a hundred thousand. The published chance is not a claim about the long run, it is a literal count of the numbers that win.
The table also carries a version identifier and an odds-history link, so a changed table is visible as a change rather than a silent edit. Together with the roll check, that makes a Skin.club result verifiable end to end: the commitment, the number, and the skin the number won.
Battles are a different check
Battle rolls use the same arithmetic with one substitution: a public beacon takes the place of the server seed, so no player's own seed can decide a shared outcome. They also carry no commitment hash, because there is no secret to commit to, which means a battle check confirms the roll and has nothing to compare a commitment against. The published battle test value above is the one to check a tool with.
What a passing check settles
The case opening and upgrade modes share one engine, confirmed against both the published values and a real account roll. Rolls run 1 to 100,000 for case opening; other mechanics may use a different ceiling, which is why the verifier exposes it as an adjustable value rather than assuming.
A match proves that one roll came from values fixed before you played, and, because the ranges are public, which skin that roll was owed. That is further than most platforms let an outsider go.
It settles nothing else. On a skins platform the gap worth naming is value: a verified roll tells you which item came up, never what that item is worth, because wear tier and float do the pricing and two copies of the same skin name can be very different goods. Skin.club's reviews are polarised, and the recurring accusation in them is that results are steered, which is precisely the claim this check can settle in either direction. Whether a trade clears, how support answers, and what any case is worth opening are separate questions, and we are explicit about what verification cannot prove.