| Rate | Frame time | Where you meet it | vs 60 Hz |
|---|
No browser API reports a monitor’s refresh rate. requestAnimationFrame runs once per presented frame, so timing enough of them gives the rate.
Some frames get missed and the clock is deliberately coarse. A plain average of the gaps gets both wrong at once; the median does not.
Gaps more than 25% from the median are counted as drops and reported separately, not averaged into a rate the monitor never ran at.
On G-Sync or FreeSync there may be no fixed number. When the spread is too wide to call, the page says variable rather than inventing an average.
What is timed is how often the browser presents a frame. On an idle page that equals the display’s refresh rate, but a busy machine, a power-saving profile or a browser that caps itself will all read lower than the monitor is capable of.
Browsers round performance.now() to defend against timing attacks, often to 100 µs, sometimes 1 ms. At 240 Hz a frame is 4.17 ms, so on a 1 ms clock every individual reading is 4 or 5 ms and never 4.17. Only the aggregate over many frames recovers it, which is why this page will not show a live per-frame number.
Frame time is the reciprocal of refresh rate: 60 to 120 Hz saves 8.3 ms a frame, 240 to 480 Hz only 2.1 ms.
Miss a vsync and the interval doubles. Averaging those in reports a rate the monitor never ran at: a 240 Hz panel with 3% drops averages out near 232 Hz. The estimate here uses the median and discards the outliers, then counts them separately.
Usually the browser window is on a different display, the machine is on a power-saving profile, or the browser is capping itself — some do on battery. It can also happen if the page is not the active tab. Try again with the window on the fast display and the laptop plugged in.
Yes, provided the browser is genuinely presenting that fast. The estimator works from total elapsed time across hundreds of frames rather than individual gaps, so a coarse clock averages out. What it cannot do is exceed what the browser presents — if the browser caps at 60, no measurement will find the panel's 500.
The rate corresponding to the slowest 1% of frames. A high average with a poor 1% low is what stutter feels like: the mean says smooth, the occasional long frame is what you actually notice.
Longer samples make the estimate steadier and are much better at catching occasional hitches — a 2-second run can easily miss a stutter that happens every ten seconds. For simply identifying the rate, 2 seconds is plenty at any refresh rate above 60 Hz.
That requestAnimationFrame fires once per presented frame, which is true in current browsers but is a browser behaviour rather than a guarantee. It measures the presentation rate of this page, not the display's capability: a browser that caps its frame rate, a background or occluded tab, a power-saving profile or a busy GPU will all read lower than the panel can do, and the tool cannot distinguish those from a genuinely slower monitor. Timestamps are quantised by the browser for security, so results are aggregates over many frames rather than per-frame measurements. On a variable-refresh display there may be no single correct answer to report. No result here should be taken as a hardware specification. The visualiser below is a corroboration, not a second measurement: the stutter ladder is driven by the same estimate, and what it shows is bounded by the same limits — on a variable-refresh display, or where the browser is throttling, it will agree with the number for the same wrong reason. Rows at or above your rate are all showing the same thing — your display's native motion, which is the best it can do — so they are identical by construction rather than by coincidence. Tearing is simulated for illustration and cannot tell you whether your own setup tears, since that is decided by vsync well below the browser.
Releases in which this page changed, newest last. Derived from the archived copy of every release, not from notes written afterwards — so it reflects what actually shipped. Site-wide passes are left out; they are in the full changelog.