A casino feed told us it paid back 46%. It pays back about 95%.
Most online casinos publish a live feed of bets as they settle. It is a marketing surface: a scrolling ticker of other people winning, meant to be watched rather than read. We read them anyway, because a settled round carries a stake and a payout, and enough of those is a measurement of what a game actually returns.
We collect from six operators. Three of those feeds are usable. The other three lie, and they lie in different ways, which is the part worth writing down.
The easy lie: showing only the wins
Stake publishes a win=1 style window, and so does Winna. Over the last 120 days our collector banked 1.4M rounds from Stake averaging a 13.2x return, and 7.9M from Winna averaging 3.2x.
No casino returns 320% of stake. These are not returns, they are a highlight reel, and the correct thing to do with them is publish the number as an upper bound with the curation stated, or not publish it at all.
That one is easy because it is obvious. A mean above 1.0 on a large sample is self-refuting. The feed is lying and it is lying loudly.
The quiet lie: being right about the wrong population
Cloudbet is the interesting one.
Cloudbet's feed does publish losing rounds, which makes it one of only three we have that can estimate a return rather than bound it. Drop the win parameter and losses arrive: multiplier: "0", returnAmount equal to the negated stake.
It read 0.4541 across 8 million rounds.
Everything else honest clusters between 0.91 and 1.00. Roobet 0.9863 over 15.6M rounds. Shuffle 0.9859 over 5.0M. BC.Game 1.0052 over 1.0M. Those are where real slot returns sit. A feed at 0.45 is either an operator running at a 55% house edge, which no one would survive publishing, or a measurement error.
It was a measurement error, and it was ours.
The control group did the work
The thing that cracked it was not staring at the aggregate. It was splitting by game and noticing which games were fine.
| game | our figure | other feeds |
|---|---|---|
| Limbo (house) | 0.9743 | 0.9881 |
| Keno (house) | 0.9665 | 0.9960 |
| Dice (house) | 0.9591 | 1.0448 |
| Plinko (house) | 0.9148 | 0.9895 |
| Mines (house, multi-step) | 0.6465 | 0.9793 |
| Le Prechaun (slot) | 0.2435 | 0.9734 |
| Duck Hunters 2 (slot) | 0.2084 | 0.8967 |
| Big Bass Bonanza 1000 (slot) | 0.3068 | 1.0075 |
Cloudbet's own instant-settling house games were accurate. Third-party slots read at about a third of truth. And Mines, which settles when the player cashes out rather than immediately, sat exactly between the two.
That is not a pattern that survives any explanation involving the operator. It is a pattern about time.
What was actually happening
Cloudbet emits each round twice under one uuid. First when it is placed, carrying multiplier: "0" and a returnAmount of exactly the negated stake. Again on settlement, with the real figures.
A losing round is never re-emitted. So the announcement of a round and a total loss are indistinguishable from the fields alone.
Our reader held the stream open for 8 seconds and returned what arrived. Nothing settles that fast. So the announcement was banked as a total loss, and the settlement, arriving in a later read, was discarded by the collector's first-write-wins dedupe as a duplicate bet_id. The round was permanently a loss.
Instant games were unaffected because they have no gap. Slots lose seconds to bonus rounds. Mines loses however long the player takes to cash out.
The fix is not "wait longer", it is "wait much longer than you think"
The obvious repair is to hold a placed round until its settlement arrives, and release it as a loss only once a settlement is no longer plausible. The question is how long.
We measured the gap over 12 minutes of live stream: median 18s, p90 88s, longest 317s.
A reasonable engineer sets the grace period near the p90, call it 180 seconds, and declares victory. We did exactly that, and slots went from 0.38 to 0.89. Inside the plausible band. It would have shipped.
It was still wrong, because of what the long tail contains:
317s -> 126.2x Floating Dragon New Year Fes
220s -> 250.1x Floating Dragon New Year Fes
107s -> 25.2x Bigger Bass Splash
The settlement delay correlates with the payout. A bonus feature is announced when the spin starts and settled when it has finished playing out, so the longer a round takes, the more it tends to pay. Truncating the tail does not trim a random sample. It removes the wins specifically.
Pricing each candidate against payout mass rather than round count:
| grace | rounds lost | payout mass lost | resulting mean |
|---|---|---|---|
| 8s (the bug) | 86 | 60.1% | 0.4075 |
| 30s | 37 | 45.7% | 0.5547 |
| 60s | 23 | 25.8% | 0.7579 |
| 180s | 2 | 16.3% | 0.8551 |
| 300s | 1 | 5.4% | 0.9654 |
| 600s | 0 | 0.0% | 1.0210 |
At 180 seconds, two rounds out of 2,268 still carried 16.3% of all payout mass. That is the shape of the distribution: a handful of rounds are most of the money, and they are exactly the slow ones.
The model also reproduced both numbers we had already measured independently — 0.4075 against the 0.4541 sitting in our database from the 8-second window, and 0.8551 against the 0.869 a live run produced at 180s. Predicting measurements taken before it is the only reason we trust it.
We set the grace period to 900 seconds.
What we take from this
A number inside the plausible band is not a correct number. The 180-second version looked fixed. It passed every sanity check we had, because our sanity checks were "is it between 0.80 and 1.00".
Find a control group inside your own data. The entire diagnosis came from Cloudbet's house games being right while its slots were wrong. Without that split we would have been arguing about the aggregate for a week.
Price errors in the units that matter. Counting rounds lost made the 180-second grace look excellent: two out of 2,268, 0.09%. Counting payout mass lost showed 16.3%. Same cut, two orders of magnitude apart in significance.
A feed that publishes losses is not thereby honest. It just fails differently. Cloudbet was not hiding anything; we were reading an announcement as a result.
Our published figures are windowed at 7 and 30 days, so the corrupted history ages out rather than needing a purge. The collector now holds a placed round for 900 seconds before giving up on it.
Every score we publish is computed from recorded data by the same algorithm for every operator, and the inputs are hashed into an append-only ledger so the arithmetic can be rechecked. How we score. The per-game figures are at niekie.app/games, and the machine-readable version is a plain anonymous GET at /api/v1/game-rtp.
Maj Jan Krošl, Developer, Niekie.
Offshore casinos ranked · Safest online casinos · Casino licenses explained