Peffercorn
Sign in

Provably fair

A pack is 12 players drawn from a fixed series of 192. The series and the seed behind every draw are published before a single pack exists, so any pack can be recomputed and checked against what was promised, and we cannot have steered your draw without you being able to tell. Your browser normally supplies part of the seed; if it cannot, the rest is derived rather than chosen — see your packs below for which applies to you.

What a pack is

8 of the 12 players are guaranteed by position, and the other 4 are flex — drawn from the running backs, receivers and tight ends still left in the pool once the guarantees are dealt.

PositionIn every packIn the series
Quarterbacks232
Running backs248
Wide receivers380
Tight ends132

Each position is drawn from its own bucket, which is the only way to guarantee those counts — one combined list would be mostly quarterbacks, because a quarterback is on the field for every dropback and a receiver only records a completion.

The series

4 of them, each cut and committed before it deals anything. The first is open before a snap is played; the rest open at 1pm Eastern on a Sunday — the moment entries close for the week being played — and each is cut from the ranking as it stood in the days before its Sunday, committed before it deals a card.

  • Series A deals week 1, and is open from pre-season.
  • Series B deals week 2, and opens Sunday, September 13.
  • Series C deals week 3, and opens Sunday, September 20.
  • Series D deals week 4, and opens Sunday, September 27.

A week can hold packs from more than one series: whoever signed up while a later series was live was dealt from whichever one was open at the time, which is why the artifact a pack verifies against is recorded on the pack itself.

The field names below are the committed artifact's own, so what this page shows lines up with what a verifier reads.

Each commitment's timestamp is anchored in Bitcoin with OpenTimestamps: an.ots proof sits beside the artifact in the public repository, and any ots client — or opentimestamps.org — can check that the file existed before its series dealt a single pack. A repository we control says when we published; Bitcoin says we cannot rewrite it.

Series A

Dealing now, so the server seed stays sealed:

  • size: 192 players
  • rankSource: consensus:2026:1
  • builtFrom: rankings-2026-1.csv — consensus snapshot (bun run rankings:snapshot), hand-curated by line order
  • seriesHash: aa686362bde7cec156be89e4e2610daedd8e92d680ab9748964416bb7e73889f
  • serverSeedHash: f3c4eca1f3822f251b1354a93f0b676cc6cab98d204bf7482ea6ca67b16f3580
  • serverSeed: Sealed until this series retires.

How a pack is drawn

  1. Before a series deals anything, we publish the ordered list of its 192 players and the SHA-256 of a secret server seed. Both land in a public commit, which is what timestamps them.
  2. Your browser generates 32 random bytes when you sign up and sends them with your handle. If it cannot — no JavaScript — that value is instead computed from your handle and the secret from step 1. Either way we never pick it: one comes from you, the other had exactly one possible answer.
  3. Each pack seeds off HMAC-SHA256(serverSeed, seriesHash | clientSeed | ordinal), where ordinal is just which of your entries it is — 1 upward. That seed drives a counter-mode byte stream, read as unbiased integers by rejection sampling — no floating point anywhere, so a verifier written in any language gets the same answer.
  4. When the series retires we publish its server seed. It must hash to the commitment from step 1, and every pack must re-derive from it exactly.

Every series is rebuildable from its committed inputs — the ranking file its rankSource names, published in the same public repository as the artifact — so you do not have to take the series hash on trust either. Run bun run series:build and compare.

Your packs

Sign in to check your own packs. The check runs in your browser against the committed pool, not on our server — a server marking its own work proves nothing.