Short answer: traceroute HOST on Linux and macOS, or tracert HOST on Windows, lists every router between you and the host: one line per hop, with three round-trip times each. A line of * * * only means that hop did not answer in time, which is usually a router that ignores probes, not a fault. What counts is the last line: loss or a jump in latency matters only when it carries on to the destination. Add -n to skip the slow name lookups, and if the trace stops early, try ICMP (-I) or TCP (sudo traceroute -T -p 443) probes.
traceroute -n example.comtracert -d example.comLinux needs the traceroute package on most minimal images: sudo apt install traceroute on Debian and Ubuntu, sudo dnf install traceroute on Rocky and AlmaLinux. Ubuntu also offers inetutils-traceroute, a different program with other flags; this guide uses the first one. Its flags below were checked against traceroute --help and the man page of traceroute 2.1.2 on Debian 12; Windows follows Microsoft’s tracert reference, macOS Apple’s traceroute man page.
traceroute, tracert and macOS side by side
| Task | Linux (traceroute 2.1) | Windows (tracert) | macOS |
|---|---|---|---|
| Default probe | UDP to ports from 33434 up | ICMP echo | UDP |
| No name lookups (faster) | -n | -d | -n |
| ICMP probes, like ping | -I | default | -I |
| TCP probes to one port | sudo traceroute -T -p 443 | no option | sudo mtr -T -P 443 (Homebrew) |
| Maximum hops | -m 40 (default 30) | -h 40 (default 30) | -m 40 (default 64) |
| Probes per hop | -q 1 (default 3) | always 3 | -q 1 (default 3) |
| Wait for each reply | -w 2 (seconds, default 5) | -w 2000 (milliseconds, default 4000) | -w 2 (seconds, default 5) |
| Start at hop N | -f 5 | no option | -f 5 |
| Force IPv4 / IPv6 | -4 / -6 | -4 / -6 | traceroute / traceroute6 |
| AS number per hop | -A | no option | -a |
How traceroute works
Every IP packet carries a time-to-live (TTL) counter, and every router on the way lowers it by one. A router that takes it to zero drops the packet and sends an ICMP time exceeded message back to the sender. traceroute uses that on purpose: it sends probes with a TTL of 1, then 2, then 3, so the first router answers for hop 1, the second for hop 2, and so on. Each answer gives away the router’s address and the time the round trip took.
The trace ends when the destination itself answers: with port unreachable for the default UDP probes (they go to ports nobody listens on), an echo reply for ICMP, or a SYN-ACK or reset for TCP. Linux traceroute sends three probes per hop, up to 30 hops, and fires up to 16 probes at once (-N), which is why it is much faster than tracert. Some routers rate-limit their answers, so a burst like that can cost a few replies; -N 1 sends one probe at a time.
How to read traceroute output
This example uses documentation addresses and invented names, but every pattern in it is one you will meet on real paths:
traceroute to example.com (203.0.113.80), 30 hops max, 60 byte packets
1 _gateway (10.0.0.1) 0.412 ms 0.387 ms 0.371 ms
2 198.51.100.1 (198.51.100.1) 1.904 ms 1.873 ms 2.011 ms
3 * * *
4 ae-3.core1.ams.example.net (192.0.2.33) 5.214 ms 5.198 ms 5.402 ms
5 ae-7.core2.fra.example.net (192.0.2.70) 11.884 ms 48.302 ms 11.902 ms
6 192.0.2.141 (192.0.2.141) 12.317 ms 192.0.2.145 (192.0.2.145) 12.290 ms 12.344 ms
7 web1.example.com (203.0.113.80) 12.512 ms 12.498 ms 12.530 ms- The header names the address the name resolved to, the hop limit and the probe size. If the address is not the one you expected, you are tracing to the wrong machine (an old DNS record, or a CDN in front of the site).
- The hop number is the TTL of the probes. Each line is one router, shown as its reverse DNS name and its address.
_gatewayis the name systemd uses for your default gateway. - The three times are three separate probes, each a full round trip in milliseconds. They are not cumulative and not an average.
- Hop 3 did not answer at all, yet hop 4 did. That router forwards traffic but does not send time exceeded messages, or not to you. Harmless.
- Hop 5 has one slow probe out of three. A single outlier is a router that was busy answering; it says nothing about your traffic (more on that below).
- Hop 6 shows two addresses. The probes took different, equally good links (load balancing), and traceroute prints every router that answered.
- The names often hint at the location: airport or city codes such as
amsorfraare common. The jump from about 5 to 12 ms between hops 4 and 5 is that distance, and it is real because it carries on to the last line.
What * * * means, and when it is a problem
An asterisk is a probe that got no answer within the wait time. Where the stars sit tells you what they mean:
- Stars on one hop, answers after it: a router that does not reply to probes. Ignore it.
- Stars on the last line only, while the site or SSH works: the destination’s firewall drops your probe type. Nothing is broken; try another probe type or test the port itself.
- Stars from some hop to the end, and the service does not work either: now the trace is evidence. The problem sits at or just after the last hop that answered, or on the way back from there.
The second pattern can start long before the last hop. Here is a real run from a Debian 12 server while it was serving its websites normally. The first hop, the server’s own gateway, is replaced with a documentation address, and hops 5 to 29 are left out because they read the same:
$ traceroute -n 1.1.1.1
traceroute to 1.1.1.1 (1.1.1.1), 30 hops max, 60 byte packets
1 203.0.113.1 0.257 ms 0.264 ms 0.259 ms
2 * * *
3 * * *
4 * * *
...
30 * * *It ran for about 30 seconds and never reached 1.1.1.1, although the server’s connection was working the whole time. The default UDP probes, or the ICMP replies to them, were filtered somewhere past the first router, which some networks do on purpose. When a trace looks like this, change the probe type before you conclude anything:
sudo traceroute -n -I 1.1.1.1 # ICMP echo, like ping
sudo traceroute -n -T -p 443 1.1.1.1 # TCP SYN to a port the target servesIf you want to know whether a service is up, a trace is the wrong test anyway: ask the port directly with nc -zv HOST 443, or see why ping fails while the website works, which is the same filtering story for ICMP.
!H, !N, !X and the other annotations
Sometimes a time is followed by a code. These come from ICMP unreachable messages, so unlike stars, somebody actively answered with a refusal. The list is from the traceroute man page:
| Code | Meaning | Usual cause |
|---|---|---|
!H | Host unreachable | The last router cannot reach the host: it is down, or nothing answers ARP on its subnet |
!N | Network unreachable | A router has no route to that network |
!P | Protocol unreachable | The target refuses the probe protocol |
!X | Communication administratively prohibited | A firewall rejects the probe with an ICMP message instead of dropping it |
!F | Fragmentation needed | The probe is larger than the MTU of a link on the way |
!S | Source route failed | Rare: only source-routed probes (-g) can get it, and most routers drop those |
!<num> | ICMP unreachable code num | Any other refusal; look the code up in the ICMP code list |
If almost every probe comes back unreachable, traceroute gives up early instead of counting to 30.
-n, -I, -T and the other flags worth knowing
traceroute -n example.com # numbers only: no reverse DNS, much faster
traceroute -I example.com # ICMP echo probes
sudo traceroute -T -p 443 example.com # TCP SYN to port 443 (default port for -T is 80)
traceroute -U -p 53 1.1.1.1 # UDP to one fixed port instead of rising ports
traceroute -q 1 -w 2 example.com # one probe per hop, 2 s wait: a quick look
traceroute -m 40 example.com # allow more than 30 hops
traceroute -A example.com # AS number of each hop, from a routing registry
traceroute -6 example.com # force IPv6 (the default is IPv4 when both exist)
traceroute --mtu example.com # find the hop where the path MTU drops
traceroute --back example.com # guess the hop count of the way back-n belongs on almost every run. Without it, traceroute looks up a name for every address, and routers without one make you wait for the lookup to time out.
-T needs root because it builds raw packets. It uses a half-open handshake: on an open port the target answers SYN-ACK and traceroute replies with a reset, so the application never sees a connection. That makes TCP to port 443 or 22 the probe most likely to get through a firewall, since it looks like the start of a normal session. -I runs without root only where the kernel allows unprivileged ICMP sockets; on the Debian 12 server used for this guide, cat /proc/sys/net/ipv4/ping_group_range printed 1 0, which allows no group, so -I needs sudo there as well.
Why a single slow hop is usually fine
Routers forward your packets in fast hardware. Answering a probe addressed to the router itself, with a time exceeded message, is a side job for its own CPU, done at low priority and rate-limited. So a router can show 80 ms or 30% loss in a trace while forwarding everything else at full speed. The proof is in the next hops: if they are fast and complete, the slow hop was only slow to talk about itself.
- Real latency persists. A jump at hop 5 that every later hop keeps is distance or congestion. Light in fibre covers roughly 200 km per millisecond, so every 100 km of cable adds about 1 ms to the round trip.
- Real loss persists. Loss that starts at one hop and shows on every line after it, including the last, is a real problem at or just before that hop.
- The way back counts too. Each time is a round trip, and the reply from hop 5 may come home over a different route than your probe took. A jump can belong to that return path, which is why traces in both directions matter.
- Some hops are invisible. Inside an MPLS core several routers can show the same time, or not show up at all.
-eprints MPLS labels where routers include them.
tracert on Windows
tracert -d example.com # no name lookups
tracert -d -h 40 -w 1000 example.com
tracert -6 example.com # IPv6Tracing route to example.com [203.0.113.80]
over a maximum of 30 hops:
1 <1 ms <1 ms <1 ms 192.168.1.1
2 8 ms 7 ms 8 ms 198.51.100.1
3 * * * Request timed out.
4 12 ms 11 ms 12 ms 192.0.2.33
5 13 ms 12 ms 12 ms 203.0.113.80
Trace complete.tracert sends ICMP echo requests, three per hop, one after another, and waits up to 4 seconds for each, so every silent hop costs 12 seconds; -w 1000 cuts that to 3. Request timed out. is the Windows form of * * * and reads the same way. Unable to resolve target system name means DNS failed before any probe was sent. For per-hop loss, pathping -n example.com traces first and then measures each hop for a while (about 25 seconds per hop by default), and in PowerShell Test-NetConnection example.com -TraceRoute prints the hop addresses only. There is no TCP mode in tracert; to check a port, use Test-NetConnection example.com -Port 443.
traceroute on macOS
macOS ships traceroute and traceroute6. They send UDP by default like Linux, take -I for ICMP, -n, -q, -w and -f as in the table, and allow 64 hops unless you set -m. For a TCP trace to a single port, install mtr with Homebrew (brew install mtr) and run it with sudo, as it needs raw sockets: sudo mtr -T -P 443 example.com.
mtr: the better tool for anything you send to someone
traceroute takes one snapshot of three probes per hop. mtr keeps probing every hop and collects loss and latency statistics, so a 30-second blip and a steady problem look different:
sudo apt install -y mtr-tiny # Rocky, AlmaLinux: sudo dnf install -y mtr
mtr -rwbzc 100 example.com # report, 100 probes per hop, names and IPs, AS numbers
sudo mtr -rwbzc 100 -T -P 443 example.com # the same over TCP to port 443The reading rules are the ones above: only loss and latency that continue to the last hop are real. A full walkthrough of an mtr report, column by column, is in testing a VPS’s network speed, and the ping guide has a real mtr run with a rate-limiting hop. tracepath, from iputils-tracepath, is the third option: no root needed, and it reports the path MTU, which helps when large transfers stall over a VPN.
Tracing to and from your server
Internet routes are often asymmetric, so a trace from your desk to the server shows only half the story. Run one in each direction:
# on your computer: towards the server
traceroute -n 203.0.113.10
# on the server: back towards you (inside SSH, your IP is the first field of $SSH_CLIENT)
echo $SSH_CLIENT
traceroute -n 198.51.100.7Your own server’s firewall rarely gets in the way of outgoing traces: UFW’s default /etc/ufw/before.rules accepts incoming time exceeded and destination unreachable messages, which are exactly the replies traceroute waits for. A hand-written nftables policy that drops all ICMP is a different matter, and it breaks more than traces.
No second machine to trace from? Our looking glass runs ping, traceroute and MTR from our Amsterdam network to your address, which shows the path towards you from outside your own network. The ping test measures your round trip to Amsterdam from the browser.
What to send to support
A traceroute alone rarely gets a network problem fixed, because one snapshot cannot tell a rate-limiting router from real loss. What your provider or ISP can act on:
- mtr in both directions, with
-nor-band at least 100 probes, taken while the problem is happening. If you only have traceroute, run it with-nand again with-T -p 443. - The time and time zone of each run, and one run from a good moment for comparison if the problem comes and goes.
- Both addresses: the server’s IP and your public IP, and what exactly is slow (downloads, SSH, one country or everyone).
The commands for collecting all of that in one go are in what to send to support in the network speed guide.
Frequently asked
What do the asterisks (* * *) in traceroute mean?
Each asterisk is a probe that got no reply within the wait time, at most 5 seconds by default on Linux. Stars on one hop followed by normal hops only mean that router does not answer probes. Stars from one hop to the end can mean a firewall drops your probe type, so repeat the trace with sudo traceroute -I (ICMP) or sudo traceroute -T -p 443 (TCP) before you decide the path is broken.
What is the difference between traceroute and tracert?
They do the same job on different systems. tracert is the Windows command and sends ICMP echo probes. traceroute on Linux and macOS sends UDP probes by default and switches to ICMP with -I, or on Linux to TCP with -T. The flags differ too: tracert -d skips name lookups where traceroute uses -n.
Is a high time on one traceroute hop a problem?
Usually not. Routers answer traceroute probes with their own CPU at low priority, so one hop can look slow or lossy while it forwards traffic at full speed. Latency or loss is real only when it continues on every hop after it, through to the destination.
How do I run a TCP traceroute?
On Linux, sudo traceroute -T -p 443 example.com sends TCP SYN probes to port 443, which most firewalls let through because it looks like the start of a normal HTTPS connection. It needs root because it builds raw packets. Windows tracert has no TCP mode; sudo mtr -T -P 443 example.com does the same on Linux and macOS.