What Your Percentile Rank Actually Means
"Faster than 73% of people" is a computed description of a model, not a measurement of people. That distinction is worth understanding, because the number looks far more empirical than it is.
Your scores on this site are stored in your own browser and are never sent anywhere. There is no database of user results. That is a privacy decision, and it has a consequence worth being honest about: we cannot compute your rank against other people, because we have not measured any.
What is computed instead
Each mode carries an assumed mean and standard deviation. Your raw result is turned into a z-score, and the upper tail of a normal distribution is evaluated at that point:
z = (ms - mean) / sd
tail = 1 - Φ(z)
result = clamp(round(100 × tail), 1, 99)Φ is the cumulative normal distribution, evaluated through an error-function approximation taken from Abramowitz & Stegun’s Handbook of Mathematical Functions (formula 7.1.26, maximum absolute error about 1.5×10⁻⁷ — seesources). The approximation is accurate to far better than a millisecond, so the interesting part is not the arithmetic. It is the inputs.
The assumptions
| Mode | Mean | SD | Measures |
|---|---|---|---|
| Ruler Drop | 250 ms | 50 | Simple visual reaction |
| Colour Change | 250 ms | 50 | Simple visual reaction |
| Fake-Out | 300 ms | 60 | Impulse control |
| Speed Click | 150 ms | 40 | Ms per tap — not a reaction time |
| 5-Trial Challenge | 250 ms | 40 | Visual, averaged over 5 |
These are assumptions baked into the scoring model. They are not derived from this site’s users. The Speed Click row is a useful warning: 150 ms there is milliseconds per tap, so comparing its percentile against Ruler Drop’s is a units error the model itself invites.
A worked example you can verify
Using the Ruler Drop parameters of 250 ms mean and 50 ms SD, here is what the function above returns. These are computed by the same code the result screen runs.
| Your time | z | Percentile |
|---|---|---|
| 170 ms | -1.60 | 95 |
| 190 ms | -1.20 | 88 |
| 200 ms | -1.00 | 84 |
| 220 ms | -0.60 | 73 |
| 240 ms | -0.20 | 58 |
| 250 ms | 0.00 | 50 |
| 270 ms | 0.40 | 34 |
| 300 ms | 1.00 | 16 |
| 330 ms | 1.60 | 5 |
Check the anchors: 250 ms is exactly the assumed mean, so it lands on the 50th percentile. One SD faster (200 ms) gives 84, one SD slower (300 ms) gives 16. Those three are structural consequences of the assumed distribution, not empirical findings — which is precisely the point.
You can also check this against a different assumption. Set the mean to 200 ms with the same SD and your 250 ms result becomes the 50th percentile instead of the 16th. The model changed; the measurement did not. That is how much authority the percentile carries.
Why the clamp exists
A normal distribution has no hard bounds, so a sufficiently fast result would compute to a percentile above 100 — implying you beat everyone, which is not a thing a model can establish. The value is clamped to 1–99 so the number stays on a scale that reads like a rank without overstating what an assumption can support. It is a small honesty measure, and it is the same reason a very fast browser score should make you check for anticipation rather than celebrate.
What to use instead
Your own history, by a wide margin. The percentile compares your result against a set of parameters chosen by whoever built the scoring model. Your history compares it against the same setup, the same device, and the same you — which is the only comparison that reliably tracks a real change.
- 1.Use the mean of five attempts, not your best single attempt.
- 2.Discard the first attempt — the practice effect is real and front-loaded.
- 3.Compare across weeks on an unchanged setup.
- 4.Treat a single percentile as a rough description, never as a measurement of other people.
Compare against yourself
The history panel stores every attempt in your browser and charts the last twenty, which is a far better basis for judging progress than any modelled rank.
The percentile function quoted here is this site’s own, implemented insrc/engine/percentile.ts. Baseline constants are in src/engine/types.ts. The error-function approximation is fromAbramowitz & Stegun (1964), formula 7.1.26. No user data is collected, so no percentile here is derived from real users.