How the numbers are built
Capster prefers working software over a complete CBA encyclopedia. Every calculator on the site uses the same pure functions, and those functions have unit tests. Read this page before you treat a dollar as gospel.
Data
- Contracts:
historical_contracts.parquetfrom the nflverse-datacontractsrelease (OTC-sourced). CSV is a flat companion and omits nested year rows — ingest uses parquet. - Timestamp:
timestamp.jsonon that same release. Currently 2026-09-05 07:13:51 EDT. - Rosters: nflverse
roster_2026.csvfor GSIS IDs, current club, and active/inactive status. Contract year-team is only the fallback when there is no roster row. - Player stats: nflverse
stats_player_week_{season}.parquetfrom thestats_playerrelease (same table asnflreadr::load_player_stats). Regular season only. As-of comes from that release'stimestamp.json. Snapshot:data/player_stats.json. Web Stats lists the full Capster roster (no volume cutoff). O-line and D-line snaps come from PFRload_snap_counts(joined on pfr_id). DL QB pressures / hurries / hits come from PFR advanced defense. OL "pressures allowed" is the team's QBtimes_pressuredtotal (unit-level, not per lineman). Pancakes and per-lineman pressures allowed are not in nflverse — those columns stay empty. An optional "Qualified only" toggle restores the old volume gates. - Refresh with
npm run ingest. Daily snap / line-stat refresh isnpm run ingest:stats(oringest:snaps) withoutCAPSTER_SKIP_DOWNLOAD. Snapshot meta records each nflverse feed name and as-of timestamp. Capster does not scrape PFF, SIS, ESPN, or NFL.com. Pancakes and per-lineman pressures allowed stay empty until a licensed dump or official API exists.
Cap math assumptions
- Year-by-year figures come from nflverse historical_contracts (OTC-sourced). Amounts are converted from millions of dollars to whole dollars.
- Current club is the nflverse roster_{season} team when a GSIS row exists. Contract season_history / OTC year-team is the fallback — it lags cutdown, waiver, and trade windows.
- Current-year cap hit is that season's cap_number. Empty years[] or a missing season row is N/A — not a fake $0 — and those contracts are excluded from roster-cap sums and top-contract lists.
- Remaining bonus = leftover prorated_bonus + option_bonus for this season and later. Remaining guaranteed salary is the sum of guaranteed_salary on those same rows.
- Standard cut: dead cap this year ≈ remaining bonus + remaining guaranteed salary. Savings = current cap hit − dead cap (can be negative).
- June 1 designation: this year takes this year's bonus + this year's guaranteed salary; leftover bonus and future guaranteed salary are booked next year.
- 1-for-1 / sandbox trade: the sending club keeps remaining bonus as dead money. The receiving club takes this year's cap hit minus this year's bonus (salary, roster, workout, other).
- Room vs league cap = published league cap − summed season cap_number for contracts that have a year row. Dead money is not modeled (estimatedDeadMoney stays 0). This is an active-cap load gap, not OTC-accurate space. LTBE, top-51, and carryover are also missing.
- season_history on each nflverse row is career-long, so inactive contract rows are not used as dead-money sources (they would double-count stars).
- Yrs Left (and the fairness yearsLeft term) counts playing seasons through the last year with cash_paid > 0. Void / poison-pill rows stay on the year table and in cut / dead-cap math.
- Option / void / injury guarantees, restructures, and splits are incomplete. Treat every dollar as a best-effort estimate pending an OTC API enrichment.
Fairness score
The fairness score is a toy heuristic — not a front office model. It blends remaining APY, years left, leftover guaranteed salary, and a position weight (quarterbacks count more; specialists less). A score of 100 is perfectly even; the lean says which locker room is asking more.
Per player: APY × yearsLeft^0.65 × positionWeight × (1 + 0.2 × guaranteedShare). Score is 100 × min(A,B) / max(A,B). Lean flips if one side is more than 8% higher.
| Position | Weight |
|---|---|
| QB | 1.85 |
| LT | 1.25 |
| EDGE | 1.22 |
| T | 1.20 |
| OT | 1.20 |
| RT | 1.15 |
| DE | 1.15 |
| WR | 1.15 |
| CB | 1.12 |
| OLB | 1.10 |
| DT | 1.05 |
| IDL | 1.05 |
| TE | 1.05 |
| S | 1.00 |
| FS | 1.00 |
| SS | 1.00 |
| NT | 1.00 |
| G | 1.00 |
| OG | 1.00 |
| C | 1.00 |
| LB | 1.00 |
| ILB | 1.00 |
| MLB | 1.00 |
| RB | 0.72 |
| FB | 0.55 |
| K | 0.35 |
| P | 0.30 |
| LS | 0.25 |
OTC enrichment TODOs
- Replace nflverse parquet ingest with an official Over The Cap API when a key is available (same CapsterDataProvider interface).
- Pull true dead-money tables, June 1 flags, void-year schedules, and option-exercise triggers.
- Add team-level carryover, top-51 offseason math, and LTBE/NLTBE incentives.
- Join more stable IDs (PFR / OTC / GSIS) and weekly roster status.
