NTP vs browser time: why your browser clock is always slightly off

Open a browser tab showing a live clock with fractional seconds. Watch the digits race. Now open a second tab with the same clock. They will not tick in unison. One lags behind the other by a frame, maybe two. Neither matches the time on a dedicated NTP-synced screen sitting on the same desk. The browser never asked the internet what time it is. It asked the operating system, and the operating system has been coasting on its last sync for anywhere from nine minutes to a week.

The chain from atomic reference to browser pixel

Your browser is the last link in a long chain. Every link adds slack. Knowing where the slack comes from tells you when to trust the screen and when to walk across the room and check a real clock.

What NTP does that a simple time request cannot

A naive time request sends a packet, gets a reply, and shows the answer. The answer is already stale by however long the reply took to cross the network. NTP measures that journey. It timestamps the outbound request, reads the server’s own timestamps on arrival and departure, and timestamps the reply when it lands. Combining those four numbers lets it calculate both the clock offset and the round-trip delay, assuming the path is roughly symmetrical. That assumption buys a few milliseconds of accuracy over the public internet and well under a millisecond on a local network.

NTP does not simply overwrite the clock when it finds an error. Small errors get slewed: the clock speeds up or slows down until it converges, so no timestamp is ever issued twice. Large errors trigger a step, but that is a last resort.

David Mills designed the protocol at the University of Delaware. It was first deployed in 1985. The current standard, NTPv4, was published in 2010. The public NTP pool at pool.ntp.org launched in 2003 and now handles billions of requests daily.

The browser’s one and only time source

When a web page calls Date.now() or new Date(), the browser asks the operating system for the current wall-clock time. That is the only move available. The browser has no independent time source, no built-in NTP client, and no way to fetch time directly from a remote server.

This is deliberate. Browsers run untrusted code. Letting a web page query a time server directly would let it measure network latency and round-trip times, data points that can infer physical location or build a tracking fingerprint. So the chain is rigid: the browser reads the OS clock. If the OS clock is wrong, the browser clock is wrong. No exception.

The OS as middleman

Your operating system runs a background time synchronisation service. Windows uses its own time service. macOS and iOS query Apple’s time servers. Linux distributions typically run chrony or systemd-timesyncd against a public pool of volunteer servers.

The OS syncs periodically. The interval varies, but it is typically between 9 and 64 minutes. Between syncs, the system relies on a quartz crystal oscillator on the motherboard. That oscillator is cheap. It drifts. Consumer hardware typically loses one to fifteen seconds per month, depending on temperature, age, and crystal quality. A desktop in a warm room drifts more than a laptop in a cool one. NTP corrects for this drift, but only when it runs. Between syncs, the clock is on its own.

This is why browser time is never exactly right. It is right to within the drift of the local oscillator plus the interval since the last sync. On a well-configured system, that is a few milliseconds. On a system that has been offline for a week, it can be seconds off.

How many hops separate your device from the reference clock

Distance from a reference clock is measured in hops. The term for each hop is a stratum level. Stratum 0 is the reference hardware itself: atomic clocks, GPS receivers, radio time signal receivers. These devices are not on the network. Stratum 1 servers connect directly to a stratum-0 device and are usually run by laboratories, universities, and large network operators. Stratum 2 servers query stratum-1 machines, and most public time server pools sit here or just below. Levels 3 and beyond serve the rest of the internet. The scheme runs to level 15; level 16 marks a clock as unsynchronised.

Your typical end-user device sits at level 3 or 4. Your browser sits at the very bottom of this chain, with no level of its own. It inherits whatever accuracy arrived at the bottom, and no more.

Higher hop counts are not automatically worse

A well-run stratum-2 server on a nearby network often beats a congested stratum-1 server on the far side of an ocean. Network path symmetry matters more than the count of hops. Choose the closest pool server your OS allows, not the one with the lowest number.

What the browser is forbidden to know

No browser API exposes synchronisation status, stratum level, or last sync time to JavaScript. There is no navigator.clock object, no performance.timeSource property. The Web Platform deliberately withholds this information for the same privacy reasons: clock offset and accuracy differ slightly on every machine, making them viable fingerprinting vectors.

The only time API available to web pages is performance.now(). It returns a monotonic clock that starts at zero when the page loads. It is not wall-clock time. It is designed for measuring elapsed intervals, not for telling the time of day. Even it gets throttled in background tabs to prevent its use as a tracking vector.

How far behind real time your browser screen really is

A stratum-1 server on a good path can deliver time accurate to within a few milliseconds over the public internet. A stratum-2 server on a local network can do better than a millisecond.

A browser screen is much worse. The browser reads the OS clock, which synced several minutes ago to a server that may be multiple network hops away. The on-screen digits update once per frame, every 16.7 milliseconds at 60 frames per second, but the clock value only refreshes when the page repaints.

On a healthy system, a browser clock is accurate to within about a second. On a system that has been sleeping or offline, it can be off by minutes. The screen shows fractional seconds, but those digits are decorative. True accuracy is limited by the OS sync interval and the local oscillator drift.

What the fractional seconds actually represent

Screen resolution is not measurement accuracy. A clock showing three decimal places can still be 50 to 200 milliseconds behind real time due to rendering pipeline latency. Those digits tell you the page is alive, not that the time is exact.

What happens when you switch tabs

The clock value is correct when you return. The visual update pauses because the browser throttles requestAnimationFrame in hidden tabs to save battery. The clock did not stop; the paint cycle did.

When the gap between NTP and browser time matters

For most purposes, the gap does not matter. A browser clock is good enough to tell you when a meeting starts or when lunch is over.

Do not rely on it for financial trading, network diagnostics, or any application where a timestamp must be traceable to a national standard. If you need to know the exact time to within a few milliseconds, use an NTP client on your local machine, not a web page. If you need to know the time to within a few seconds, a browser clock is fine. If you need to know the time to within a few hundred milliseconds, check your OS sync status first. The browser cannot help you.

The stopwatch uses a different clock entirely

A correctly built stopwatch uses performance.now(), a monotonic source that only ever increases and is unaffected by system clock adjustments. A live clock uses Date.now(), wall-clock time that can jump forward or backward due to synchronisation corrections, manual changes, or DST transitions. Using wall-clock time for a stopwatch means NTP corrections or daylight saving changes could make elapsed time jump. Never use a live clock page to time a race.

Common advice to ignore

A clock showing fractional seconds is not a precision instrument. The browser rendering pipeline adds variable latency, typically 16 to 50 milliseconds depending on frame timing. The screen is for casual reference, not measurement. Setting your computer clock manually is worse: human reaction time alone puts it off by 0.5 to2 seconds, and drift begins immediately.

How to check your system’s NTP sync status directly

To check whether your system is syncing correctly, ask the OS, not the browser.

On Windows, open a command prompt and run w32tm /query /status. This shows the stratum level of your current time source and the last sync time.

On macOS, run sntp -sS time.apple.com to force a sync, or use systemsetup -getusingnetworktime to check whether network time is enabled.

On Linux, run timedatectl status to see whether synchronisation is active and which server you are using.

What the results mean

If synchronisation is active and the system has been online recently, your clock is probably within a second of true time. If synchronisation is inactive, your clock is drifting, and no browser page can fix it.

The rule of thumb

NTP is the source. The OS is the middleman. The browser is the screen. If you need accuracy, fix the source. If you need a convenient readout, the browser is fine. Just never mistake the screen for the source.

Fixes for common NTP and browser clock problems

When the browser clock is wrong but the system clock is right, the culprit is almost always a browser extension blocking timers, a throttled background tab, or a page that caches its own time value instead of reading the system clock on each frame. Reload the page. Disable extensions that block scripts. Keep the tab in the foreground.

When the system clock is wrong, force a sync using the commands above. If the clock is consistently off by hours, check the time zone setting, not the time itself. A correctly synced clock in the wrong zone looks exactly like a broken clock.

When a fullscreen clock on a monitor keeps dimming or locking, request the Screen Wake Lock API explicitly. Fullscreen mode alone does not keep the screen on. The Wake Lock API requires a user gesture and page visibility. On mobile devices, OS-level power settings may override it anyway.

When a clock shown on a TV or lobby screen drifts over weeks, the hardware matters. A Raspberry Pi running a kiosk-mode browser will drift like any other consumer device. Configure the underlying OS to sync aggressively, or use a dedicated NTP-synced display for applications where drift is unacceptable.

What NTP cannot fix

NTP corrects clock offset and drift. It cannot fix a misconfigured time zone. It cannot prevent a device from applying the wrong daylight saving rules. It cannot make a browser screen update while the tab is hidden. And it cannot turn a quartz oscillator into an atomic reference. Between syncs, every consumer device drifts. The only question is how much.