BrawlVision

Methodology

How we build every stat you see

BrawlVision combines Supercell's official API, our own PRO-player sampling layer and several statistical smoothing steps to give you numbers that are stable, comparable, and honest about their own uncertainty. This page documents each of those steps, with the exact formulas and update cadences.

Last updated: 2026-04-30

Data sources

Everything we display comes from three sources we keep auditable: Supercell's public API (developer.brawlstars.com), the Brawlify CDN (cdn.brawlify.com), and our own Supabase database, which persists battles and aggregates that the official API doesn't expose past the last 25 matches per player.

Supercell's API is the canonical source for structural data — brawlers, gadgets, star powers, hypercharges, gears and event rotation — but it leaves out critical fields like brawler images, rarity, and long descriptions. We cross-reference those with the Brawlify CDN, which operates independently and sometimes lags Supercell by one to three days. When we detect a new brawler on the official API that doesn't exist on Brawlify yet, we keep a local rarity map (BRAWLER_RARITY_MAP) so the brawler's page renders correctly on launch day.

Our database stores two classes of rows in the meta_stats table: source=user (real battles from premium users who enabled sync) and source=global (automated sampling from the top PRO leaderboards). Every public statistic on the site is computed filtering by source=global, so personal data from any single user never leaks into public pages.

How we build the PRO data

The "PRO" layer of BrawlVision is a set of aggregates computed over recent battles from the world's top players. Every six hours a cron job (meta-poll) queries Supercell's official rankings for eleven countries — the ones that concentrate competitive activity — and builds a deduplicated pool of roughly 2,100 unique players from each top 200.

Over that pool we apply a probabilistic sampler to keep popular (map, mode) combinations from dominating the dataset and masking the rare ones. The probability of accepting an individual battle is p = min(1, (minLive + 1) / (current + 1)), where minLive is the count for the least-represented combination and current is the count for the candidate battle's combination. Under-sampled combinations get higher acceptance; saturated ones stop growing.

The cron iterates up to META_POLL_MAX_DEPTH = 1,000 players per run with a soft 270-second budget so it stays inside the serverless function's 300-second maxDuration. Each response includes an "adaptive" diagnostic block with iteration counts, players sampled, and per-mode counts, so any anomalous sampler behavior is observable in production.

Bayesian Win Rate

The naive win rate (wins divided by matches) misleads when there are few matches. A brawler with 3 wins and 0 losses on a new map shows a 100% that means nothing. BrawlVision applies Bayesian smoothing to correct that distortion and return a number comparable across brawlers with very different sample sizes.

The formula is WR_bayesian = (wins + α·μ) / (battles + α). The α parameter weighs how many imaginary matches we add and μ is the result we assign to them. We use α = 30, which amounts to adding 30 prior battles before looking at the real data.

Until September 2026 those imaginary matches were worth 50%, and that was the wrong value. Our table stores a single row per battle, the one belonging to the polled player, who is someone from the top 200 of their country and wins 71.4% of their matches (61,400 wins over 85,970 battles in the 14-day window, measured on 7 September 2026). Shrinking data centred on 71.4% towards 50% dragged down every cell with few matches, and the smaller the sample, the harder it dragged. Today μ is worth 0.714, which is the baseline we measured.

The weight of the prior decays as the sample grows. With 1,000 battles and 530 wins the result lands on (530 + 21.42) / 1,030 = 53.5%, very close to the raw 53.0%. With 3 battles and 3 wins it lands on 74.0% instead of the naive 100%. The smoothing only weighs when the sample is genuinely small.

Discounted strength

The win rate we publish mixes two things. One is how good a brawler is, the other is who it happened to face. A brawler that shows up mostly in favourable matchups comes out high without that saying much about its kit. Discounted strength separates the two and estimates how often that brawler would win against a mid-level opponent.

The calculation is a Bradley-Terry model fitted by MM over the matchup table of the last 14 days. Every pair of brawlers is symmetrised before it enters the fit, because our rows are always recorded from the side of the polled player and that side carries an advantage. Measured over the pairs with at least 30 duels in each direction, the win rate of A against B plus the win rate of B against A add up to a median of 138%, where a symmetric figure would add up to 100%. Counting each duel once from each side brings that advantage in favour of both, and it cancels out. The result is published as the expected win rate against the median brawler of the fit, so on this scale 50% is the draw.

The figure discounts the mix of opponents and the average advantage of the sampling. It does not discount who is playing the brawler. Neither meta_stats nor meta_matchups stores a player identifier, so subtracting the level of the person playing is impossible with the data we have; it would take recording the ranking of the polled player at ingestion time. That is why the lists across the site are still ordered by observed win rate and strength sits beside it. And that is also why the observed win rate hovers around 72% and not around 50%. The sample is made of matches from top 200 players across eleven countries, who win close to 72% of the ones they play, so on that scale 72% describes an ordinary brawler. We only publish the strength of brawlers with at least 400 recorded duels against 20 different opponents; below that we omit the figure instead of showing a number that does not hold up.

Comfort Score

Comfort Score is BrawlVision's in-house metric answering the question "which brawler are you actually better with than with average?". It is not a raw Win Rate: it combines three components with weights 60/30/10 to cover different dimensions of personal performance.

The main component (60 %) is the player's WR with that brawler, Bayesian-smoothed exactly like the global meta, so a rarely-played brawler doesn't game the ranking. The middle component (30 %) is the difference between that personal WR and the brawler's overall meta WR: a player at 55 % on SHELLY when the global meta sits at 48 % earns more comfort than someone at 55 % on a brawler whose meta is 53 %, because the relative lift is bigger.

The final component (10 %) is normalized usage frequency: all else equal, playing a brawler 100 times counts more than playing it 10, because consistency is rewarded. The exact formulas and weights live in src/lib/analytics/compute.ts and apply identically on every endpoint call, so the ranking is reproducible.

Update cadence

How often a piece of data refreshes affects how you should interpret it, so we document it explicitly. Static pages (this one included) use ISR (Incremental Static Regeneration) with a 24-hour revalidation. Pages with dynamic data cache the API response until the relevant job invalidates it.

Brawlers, gadgets and star powers sync from the Supercell API with a 24-hour server cache. The meta-poll (PRO data) runs every 6 hours and produces fresh meta_stats rows. The 7-day trend precomputation runs in pg_cron at "17 */6 * * *" (minute 17 of every sixth hour) to avoid colliding with the meta-poll. The in-game event rotation refreshes every 30 minutes.

Individual battles from premium users who enabled sync are downloaded right after each match in a moving window via the sync cron. Once in our database they feed meta_stats with source=user and are the basis for private analytics in the profile section; they never appear in public aggregates and never mix with source=global.

Frequently asked questions

Why isn't a brawler's WR 0 % or 100 % on small samples?+

Because we apply Bayesian smoothing with a 50 %-centered prior. With very few matches the displayed number sits close to 50 %; as the sample grows, it converges to the real WR. This is deliberate: 100 % on 3 matches is not information, it is noise.

Do public pages use data from real users?+

No. Every public aggregate filters by source=global, which only holds battles taken from automated PRO-leaderboard sampling. Private battles from premium users are stored with source=user and never cross into public pages.

What happens when Supercell ships a new brawler?+

The brawler list comes from the official API, so the full roster appears on the site the same day as the launch. Rarity and images come from Brawlify, which can lag by one to three days; we keep a local rarity map (BRAWLER_RARITY_MAP) as fallback for those first days.

Why do some trends show a dash instead of a percentage?+

We only show the trend if each half of the 14-day window has at least 3 battles in source=global. When a brawler is rarely seen, we prefer to show nothing rather than a low-signal number.

Does the site use AI to generate descriptions?+

Descriptions are generated dynamically from our own data (best map, best mode, Bayesian WR per brawler). We do not copy text from Brawlify or the wiki, and we do not use language models to inflate content.

Questions or corrections?

If you spot a methodological error or want to suggest an improvement, get in touch. We keep this page in sync with every relevant change to how we compute the data.