---
title: Is this time server any good? How to test an NTP server with the NTP Server Test
description: 2FA codes get rejected, tokens are 'not yet valid', logs from two servers disagree by seconds. Before you point a fleet at a time server, test it: ask it for the time and check that it answers, is synchronised, sits at a low stratum and agrees with a good clock to within milliseconds. Here's how with the free NTP Server Test, how to read offset, delay, stratum and leap, and a ten-line script that does the same query.
canonical: https://watchfor.io/blog/how-to-test-an-ntp-server
---

# Is this time server any good? How to test an NTP server with the NTP Server Test

2026-10-04 · WatchFor Team · Guides · guides, networking, security

2FA codes get rejected, tokens are 'not yet valid', logs from two servers disagree by seconds. Before you point a fleet at a time server, test it: ask it for the time and check that it answers, is synchronised, sits at a low stratum and agrees with a good clock to within milliseconds. Here's how with the free NTP Server Test, how to read offset, delay, stratum and leap, and a ten-line script that does the same query.

To test an NTP server, send it an NTP request and look at four things in
the reply: whether it answers at all, its **leap indicator** (3 means the
server admits it isn't synchronised), its **stratum** (how many steps it is
from a reference clock; 1–3 is normal for public servers, 16 means
unsynchronised) and its **offset** against a clock you trust. A healthy
public server answers within milliseconds of correct time.

The free [NTP Server Test](/ntp-test) queries any NTP server from a WatchFor
location, three samples by default, and shows the clock offset, round-trip
delay, jitter, stratum, leap indicator and NTP version, sample by sample.
No signup.

## What this tool answers

*Does this time server answer, and can I trust its time?* Reach for it before
you set a server, router or Kubernetes node to a new NTP source, when TOTP
codes or signed tokens fail with clock errors, when logs from two machines
can't be lined up, or when you run your own NTP server and want to see it
from outside. NTP runs over UDP port 123, so a TCP port check can't tell you
any of this.

## A real example

### Testing an NTP server before pointing servers at it

The trigger is usually a symptom somewhere else: users report that their
authenticator codes are "wrong" on one server, or an API rejects JWTs with
"token used before issued". Both come down to a server clock that has
drifted. Before fixing the server's time configuration, you want a source
you can trust. We compared two common choices.

In the [NTP Server Test](/ntp-test) we entered `time.cloudflare.com` and
kept port 123 and 3 samples:

![The NTP Server Test for time.cloudflare.com: clock offset −2.7 ms, RESPONDING, stratum 3, synchronised, NTPv4; round-trip delay 1 ms, jitter 0.0 ms, 3 of 3 samples, server IP 162.159.200.1; three samples at −2.7, −2.6 and −2.7 ms offset, 1 ms delay, stratum 3, synchronised](/blog/how-to-test-an-ntp-server-result.webp)

Then the same test against `pool.ntp.org`, which handed the probe a pool
member close to it. The numbers side by side (from the saved results; the
screen rounds them):

| | time.cloudflare.com | pool.ntp.org |
| --- | --- | --- |
| Answered | 3 of 3 samples | 3 of 3 samples |
| Server IP | 162.159.200.1 | 212.59.0.1 |
| Leap indicator | 0, synchronised | 0, synchronised |
| Stratum | 3 | 2 |
| Offset | −2.65 ms | +0.07 ms |
| Round-trip delay | 0.61 ms | 0.72 ms |
| Jitter | 0.02 ms | 0.03 ms |

How to read it:

- **Both answered every sample and both report themselves synchronised**
  (leap indicator 0). That rules out the two failure modes that matter most:
  a server that doesn't answer and one that answers with time it doesn't
  vouch for.
- **Stratum 2 and 3** are normal: one or two servers between them and an
  atomic or GPS reference.
- **The offsets differ by about 2.7 ms.** The offset is measured against the
  probe's own clock, which is itself kept by NTP, so a few milliseconds
  either way between two good servers is normal. The delay of under 1 ms
  makes the measurement precise, so the difference is real, but it doesn't
  matter: TOTP codes change every 30 seconds (RFC 6238) and Kerberos
  tolerates 5 minutes of skew by default.
- **Jitter of 0.02–0.03 ms** across the samples means a steady path and a
  steady server.

**The answer:** both are fine time sources. The authenticator problem was
the server's own clock, not the choice of source. Point the server at a
pool or at two or three independent servers, make sure its NTP client runs
(`timedatectl` should say *System clock synchronized: yes*), and check the
offset with `chronyc tracking` (both in the command-line section).

## How to read the results

| What you see | What it means |
| --- | --- |
| **Clock offset (hero)** | Difference between the server's time and the probe's clock, averaged over the samples. Green within ±50 ms, amber within ±500 ms, red beyond. Negative means the server is behind the probe. |
| **RESPONDING / NO ANSWER** | Whether valid NTP replies came back. No answer usually means UDP 123 is blocked, or the server is down or rate-limiting. |
| **Stratum** | Distance from a reference clock: 1 is attached to GPS or an atomic clock, each server in between adds one. Green at 1–2; red at 0 or 16+, which mean "unsynchronised" or a refusal (kiss-o'-death) in practice. |
| **Leap indicator** | *synchronised* (0) is normal. *Leap second ahead* (1 or 2) announces a leap second. **UNSYNCHRONISED** (3) is the server saying its time can't be trusted: don't use it. |
| **NTPv4 / v3** | The protocol version in the reply. |
| **Round-trip delay** | Network round trip for the query. The offset is uncertain by up to half of it, so short delays mean precise offsets. |
| **Jitter** | How much the offset moved between samples. High jitter means a congested path or an unstable server. |
| **Samples / Server IP** | Valid replies out of requests sent, and the address that answered: useful for pool names, which return a different server each time. |
| **Samples table** | Offset, delay, stratum and leap per sample, so one bad sample stands out. |

## More ways to use it

- **Check your own NTP server from outside.** Run it against your server's
  public name. *No answer* usually means a firewall blocks UDP 123 inbound,
  or the daemon only serves the local network (`allow` in chrony.conf,
  `restrict` in ntp.conf).
- **Catch an unsynchronised server.** A server whose upstream died keeps
  answering, and a good one then sets leap 3 or stratum 16. If it doesn't,
  its offset drifts; both show up here.
- **Vet a vendor or ISP time server** before putting it in device configs.
- **Compare sources.** Run two or three candidates back to back from the
  same location, as above, and prefer the ones with low delay and jitter.
- **Before blaming the network.** If NTP answers but authentication still
  fails, the problem is the client's clock or timezone setting; check
  `timedatectl` on the machine itself.

## Tips and gotchas

- **The offset is relative to the probe.** It tells you whether the server
  agrees with another well-synchronised clock, not absolute truth. A few
  milliseconds either way between good servers is irrelevant for almost
  every use; tens or hundreds of milliseconds deserve a second look.
- **Pool names change answers.** `pool.ntp.org` returns servers close to
  whoever asks, a different one each time. Your machines will get different
  members than the test did.
- **Don't mix smearing and non-smearing servers.** Google's public NTP
  smears leap seconds over a day; standard servers insert them at once.
  Mixed sources disagree by up to a second during a leap event.
- **Use several sources.** NTP clients pick the best of several servers and
  discard outliers. With one source, a broken server goes unnoticed.
- **UDP 123 is often filtered.** Corporate firewalls and some ISPs block
  outbound or inbound NTP. If the test passes but your machine can't sync,
  test from the machine itself.
- **Consider NTS.** Plain NTP replies aren't authenticated. Network Time
  Security (RFC 8915) adds it; `time.cloudflare.com` supports it, and chrony
  enables it with the `nts` option.

## Check it from the command line too

An SNTP query is small enough to write by hand. This script sends one
version 4 client request and computes offset and delay with the standard
formulas from RFC 5905:

```python
# sntp.py — python3 sntp.py <server>
host = sys.argv[1]
pkt = b'\x23' + 47 * b'\0'            # LI=0, version 4, mode 3 (client)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM); s.settimeout(3)
t1 = time.time(); s.sendto(pkt, (host, 123)); d, _ = s.recvfrom(48); t4 = time.time()
ntp = lambda sec, frac: sec - 2208988800 + frac / 2**32
t2 = ntp(*struct.unpack('!II', d[32:40])); t3 = ntp(*struct.unpack('!II', d[40:48]))
print(f"stratum {d[1]}  leap {d[0] >> 6}  offset {((t2-t1)+(t3-t4))/2*1000:+.1f} ms  delay {((t4-t1)-(t3-t2))*1000:.1f} ms")
```

From our office, a few minutes after the example:

```bash
python3 sntp.py time.cloudflare.com
python3 sntp.py time.google.com
```

```text
stratum 3  leap 0  offset +0.4 ms  delay 9.3 ms
stratum 1  leap 0  offset -0.1 ms  delay 24.5 ms
```

Here the offset is against this machine's clock, kept by chrony. To see how
far the machine itself is from NTP time:

```bash
chronyc tracking | grep -E "Stratum|System time|Leap status"
timedatectl | grep -E "synchronized|NTP service"
```

```text
Stratum         : 3
System time     : 0.000169359 seconds slow of NTP time
Leap status     : Normal
System clock synchronized: yes
              NTP service: active
```

0.17 ms slow, synchronised. On a machine with a clock problem, *System clock
synchronized: no* or a large *System time* is the thing to fix. On Windows,
`w32tm /stripchart /computer:time.cloudflare.com /samples:3` shows the
offset against a server.

## Keep watching it

A time server that's fine today can lose its upstream tomorrow and keep
serving drifting time. An [NTP monitor](/ntp-monitoring) queries it on a
schedule (4 samples per check by default) and opens an incident when the
offset passes your **Max Offset** (100 ms by default) or the server reports
itself **not synchronised**; both rules are on from the start. **High
Stratum**, **High Network Delay** and **High Jitter** can be added.

## FAQ

**What is a good NTP offset?**
For a public server tested over the internet, within a few milliseconds is
good and under 50 ms is fine for almost everything. Above 100 ms, look for a
problem with the server or the path.

**What does NTP stratum mean?**
The number of hops from a reference clock. Stratum 1 servers read GPS or an
atomic clock directly, stratum 2 servers sync from stratum 1, and so on;
16 means unsynchronised.

**How do I check if NTP is working on my server?**
On Linux, `timedatectl` shows whether the clock is synchronised and
`chronyc tracking` (or `ntpq -p` with ntpd) the current offset and source.
[What is latency?](/blog/what-is-latency) explains why delay limits how
precise any time measurement over a network can be, and
[TCP vs UDP](/blog/tcp-vs-udp) why NTP uses UDP.

---

Canonical page: https://watchfor.io/blog/how-to-test-an-ntp-server · All articles: https://watchfor.io/blog/all.md · Site guide: https://watchfor.io/llms.txt
