cheat sheet

ping

Send ICMP echo requests to a host to test reachability, measure round-trip latency, and detect packet loss from the Windows command prompt.

ping — Test Network Connectivity

What it is

ping is a built-in Windows command that sends ICMP Echo Request packets to a target host and waits for ICMP Echo Reply packets in return. It reports round-trip time (RTT) per packet and summarises packet loss — the first tool to reach for when a network path is suspected to be broken. It does not diagnose where a path breaks (use tracert for that), but confirms basic reachability and latency in seconds.

Availability

ping ships as C:\Windows\System32\ping.exe on every Windows version. The Linux/macOS ping is a separate binary with different flag names (-c for count vs -n).

cmd
ping /?

Output:

ini
Usage: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]
            [-r count] [-s count] [[-j host-list] | [-k host-list]]
            [-w timeout] [-R] [-S srcaddr] [-c compartment] [-p]
            [-4] [-6] target_name

Syntax

cmd
ping [options] target

Output: (ICMP echo statistics)

Essential options

SwitchMeaning
targetHostname or IP address
-n countNumber of echo requests to send (default 4)
-tPing continuously until Ctrl+C
-aResolve IP addresses to hostnames
-l sizePacket payload size in bytes (default 32, max 65500)
-w timeoutTimeout per reply in milliseconds (default 4000)
-4Force IPv4
-6Force IPv6
-i TTLTime-To-Live for outgoing packets
-fSet Don't Fragment bit (useful for MTU testing)

Basic ping

Sending 4 ICMP requests (the default) confirms whether a host is reachable and shows RTT.

cmd
ping myhost

Output:

ini
Pinging myhost [192.168.1.100] with 32 bytes of data:
Reply from 192.168.1.100: bytes=32 time<1ms TTL=128
Reply from 192.168.1.100: bytes=32 time<1ms TTL=128
Reply from 192.168.1.100: bytes=32 time<1ms TTL=128
Reply from 192.168.1.100: bytes=32 time<1ms TTL=128

Ping statistics for 192.168.1.100:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
cmd
ping 8.8.8.8

Output:

ini
Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=14ms TTL=117
Reply from 8.8.8.8: bytes=32 time=13ms TTL=117
Reply from 8.8.8.8: bytes=32 time=14ms TTL=117
Reply from 8.8.8.8: bytes=32 time=14ms TTL=117

Ping statistics for 8.8.8.8:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 13ms, Maximum = 14ms, Average = 13ms

Controlling the count (-n)

-n sets how many requests to send. Use a large count to observe latency variance or packet loss over time; use 1 for a quick one-shot check.

cmd
ping -n 1 192.168.1.1

Output:

ini
Pinging 192.168.1.1 with 32 bytes of data:
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64

Ping statistics for 192.168.1.1:
    Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
cmd
rem Monitor packet loss over 100 pings
ping -n 100 192.168.1.1

Output:

python-repl
...
Ping statistics for 192.168.1.1:
    Packets: Sent = 100, Received = 97, Lost = 3 (3% loss),
...

Continuous ping (-t)

-t pings indefinitely until interrupted with Ctrl+C. Pressing Ctrl+Break (not Ctrl+C) prints the running statistics without stopping.

cmd
ping -t 192.168.1.1

Output:

ini
Pinging 192.168.1.1 with 32 bytes of data:
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64
...
^C
Ping statistics for 192.168.1.1:
    Packets: Sent = 12, Received = 12, Lost = 0 (0% loss),
...

Resolve IP to hostname (-a)

-a performs a reverse DNS lookup on the reply address and displays the resolved name alongside the IP.

cmd
ping -a 8.8.8.8 -n 1

Output:

ini
Pinging dns.google [8.8.8.8] with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=14ms TTL=117

Ping statistics for 8.8.8.8:
    Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
...

Packet size and MTU testing (-l, -f)

-l size changes the payload from the default 32 bytes. Combined with -f (Don't Fragment), it lets you find the maximum MTU on a path: increase -l until you see "Packet needs to be fragmented".

cmd
ping -l 1472 -f 8.8.8.8 -n 1

Output:

python
Pinging 8.8.8.8 with 1472 bytes of data:
Reply from 8.8.8.8: bytes=1472 time=15ms TTL=117
...
cmd
ping -l 1473 -f 8.8.8.8 -n 1

Output:

vbnet
Packet needs to be fragmented but DF set.

Forcing IPv4 or IPv6 (-4, -6)

When a hostname resolves to both A and AAAA records, ping may choose either. Use -4 or -6 to pin to a specific version.

cmd
ping -4 example.com -n 2

Output:

python
Pinging example.com [93.184.216.34] with 32 bytes of data:
...
cmd
ping -6 example.com -n 2

Output:

python
Pinging example.com [2606:2800:220:1:248:1893:25c8:1946] with 32 bytes of data:
...

Using ping exit codes in scripts

ping exits 0 on success, 1 on failure (all packets lost or host unreachable). Use errorlevel in batch scripts to branch on reachability.

cmd
ping -n 1 -w 1000 192.168.1.1 > NUL
if errorlevel 1 (
    echo Gateway unreachable
) else (
    echo Gateway OK
)

Output:

code
Gateway OK

Adjusting the interval (-w) and source address (-S)

-w controls how long ping waits for each individual reply before declaring the packet lost; it does not change how fast probes are sent (which is fixed at one per second). -S chooses which local IP appears as the source of the ICMP packet, which matters on multi-homed machines where routing alone would pick the wrong interface.

cmd
rem Tight 500 ms timeout for a LAN healthcheck (fail fast)
ping -n 3 -w 500 192.168.1.1

Output:

ini
Pinging 192.168.1.1 with 32 bytes of data:
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64

Ping statistics for 192.168.1.1:
    Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
cmd
rem Force the ping to leave via the 10.0.0.5 interface
ping -S 10.0.0.5 -n 2 10.0.0.1

Output:

python
Pinging 10.0.0.1 from 10.0.0.5 with 32 bytes of data:
Reply from 10.0.0.1: bytes=32 time=1ms TTL=64
Reply from 10.0.0.1: bytes=32 time=1ms TTL=64

TTL inspection and OS fingerprinting

Each Reply line ends with TTL=N, which is the remaining TTL when the packet arrived. The original TTL is operating-system specific — Windows starts at 128, Linux at 64, some network appliances at 255 — and the number of intermediate routers is originalTTL - replyTTL. Use this to estimate hop count and identify the remote OS without running tracert.

cmd
ping -n 1 8.8.8.8

Output:

ini
Reply from 8.8.8.8: bytes=32 time=14ms TTL=117

A TTL of 117 from a destination whose OS uses 128 as the initial TTL means the packet crossed 11 routers; if the destination uses 64, it would mean -53 hops (impossible), so 128 is the correct anchor here. Linux destinations typically arrive with TTLs in the 50–60 range, embedded devices with 240+.

Setting outgoing TTL (-i) and ToS (-v)

-i TTL sets the initial TTL on outgoing packets, which makes ping behave like a one-hop traceroute when set to small values. -v TOS was historically the IPv4 Type-of-Service byte; on modern Windows it is recognised but the IETF deprecated raw ToS in favour of DSCP, so its effect on routing is limited.

cmd
rem TTL=1 — only the first-hop router will reply (with "TTL expired")
ping -i 1 -n 1 8.8.8.8

Output:

yaml
Pinging 8.8.8.8 with 32 bytes of data:
Reply from 192.168.1.1: TTL expired in transit.

Ping statistics for 8.8.8.8:
    Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),

The reply comes from the first router on the path, identifying the next hop. Increment -i to probe further hops — exactly how tracert works internally.

MTU and Path MTU Discovery

The Maximum Transmission Unit (MTU) is the largest IP packet a link can carry without fragmentation. Ethernet defaults to 1500 bytes, PPPoE typically 1492, IPSec/VPN tunnels often 1400 or less. Path MTU is the smallest MTU on any link between source and destination. ping -l <payload> -f lets you probe it directly: the largest payload that gets through without "Packet needs to be fragmented" is the path MTU minus 28 (20 bytes IP header + 8 bytes ICMP header).

cmd
rem Find path MTU by binary search (manual)
ping -l 1472 -f 8.8.8.8 -n 1
ping -l 1400 -f 8.8.8.8 -n 1
ping -l 1450 -f 8.8.8.8 -n 1

Output:

ini
Reply from 8.8.8.8: bytes=1472 time=15ms TTL=117
...

If 1472 succeeds, path MTU is at least 1500 (1472 + 28). If 1472 fails but 1450 works, path MTU is between 1478 and 1500 — narrow further.

The Test-NetConnection -Traceroute -Hops <n> cmdlet in PowerShell can also discover MTU automatically (via -DiagnoseRouting), and netsh interface ipv4 show subinterfaces reports the configured MTU per interface.

cmd
netsh interface ipv4 show subinterfaces

Output:

sql
   MTU  MediaSenseState   Bytes In  Bytes Out  Interface
------  ---------------  ---------  ---------  -------------
  1500                1   12345678    9876543  Ethernet
  1400                1     234567     345678  VPN

Compartments (-c)

Windows network compartments are isolated routing namespaces, used for things like Hyper-V container hosts and Edge browser InPrivate sessions. -c <compartment> runs the ping inside a specific compartment, letting you test connectivity from inside a sandbox.

cmd
ping -c 1 -n 2 example.com

Output:

python
Pinging example.com [93.184.216.34] with 32 bytes of data:
Reply from 93.184.216.34: bytes=32 time=13ms TTL=58
...

List compartments with netsh interface ipv4 show compartments (Vista+).

Record route and timestamp (-r, -s)

The IPv4 Record Route option asks each router on the path to stamp its IP into the option header, returning up to nine addresses (the IP option field is limited to 40 bytes). The Timestamp option does the same with millisecond timestamps. Both are widely ignored or stripped by modern routers and firewalls, so the output is often blank — but on the rare cooperative path they reveal the forward and reverse path in a single packet.

cmd
ping -r 9 -n 1 8.8.8.8

Output:

rust
Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=14ms TTL=117
    Route: 192.168.1.1 ->
           10.0.0.1 ->
           72.14.215.165 ->
           8.8.8.8 ->
           8.8.8.8 ->
           72.14.215.165 ->
           10.0.0.1 ->
           192.168.1.1
cmd
ping -s 4 -n 1 192.168.1.1

Output:

python
Pinging 192.168.1.1 with 32 bytes of data:
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64
    Timestamp: 192.168.1.100 : 23456789 ->
               192.168.1.1   : 23456789

These options are most useful inside a controlled corporate network where the routers honour them.

PowerShell equivalent: Test-NetConnection

Test-NetConnection is PowerShell's modern replacement for ping — it does ICMP echo by default but also offers TCP port testing, route tracing, and DNS resolution in a single cmdlet. The output is a structured object, which is far easier to script against than parsing ping text.

powershell
# Basic ping equivalent
Test-NetConnection 8.8.8.8

# Quiet — returns $true/$false, ideal for if/else
Test-NetConnection 8.8.8.8 -InformationLevel Quiet

# TCP probe instead of ICMP (works through ICMP-blocking firewalls)
Test-NetConnection www.example.com -Port 443

# Full diagnostic: traceroute + MTU + route selection
Test-NetConnection 8.8.8.8 -DiagnoseRouting -InformationLevel Detailed

Output:

yaml
ComputerName     : 8.8.8.8
RemoteAddress    : 8.8.8.8
RemotePort       : 443
InterfaceAlias   : Ethernet
SourceAddress    : 192.168.1.100
TcpTestSucceeded : True

The TCP form is especially valuable when corporate firewalls block ICMP but allow application traffic — Test-NetConnection -Port 443 is the de-facto Windows replacement for nc -zv host 443 from the Unix world.

ping in scripting: parsing latency

When you need only the latency number for graphing or alerting, parse the time= field with for /f (cmd) or a regex in PowerShell.

cmd
@echo off
for /f "tokens=5 delims==m " %%a in ('ping -n 1 8.8.8.8 ^| findstr "time="') do (
    echo Latency to 8.8.8.8: %%a ms
)

Output:

css
Latency to 8.8.8.8: 14 ms
powershell
# PowerShell — cleaner, structured
$r = Test-Connection 8.8.8.8 -Count 1
"$($r.Address) latency: $($r.Latency) ms"

Output:

yaml
8.8.8.8 latency: 14 ms

Identifying ICMP error types

ping reports more than just success/fail. Each non-reply has a distinct meaning that points to a different layer of failure.

MessageMeaning
Reply from X: bytes=...Normal ICMP Echo Reply
Request timed out.No reply within timeout — firewall, host down, or extreme latency
Destination host unreachable.Local routing has no path; check route PRINT
Destination net unreachable.A router sent ICMP type 3 code 0 — upstream routing problem
TTL expired in transit.Packet bounced inside the network and ran out of TTL
Packet needs to be fragmented but DF set.Path MTU smaller than -l payload
General failure.Driver/adapter problem or IP not configured
Hardware error.Cable unplugged or NIC offline
Transmit failed. General failure.Source interface is down or has no IP

Each of these maps to an ICMP type/code on the wire — capture with pktmon if you need the raw bytes.

ICMPv6 specifics

When pinging an IPv6 address, Windows sends ICMPv6 Echo Request (type 128) instead of ICMPv4 type 8. The flags -4 and -6 choose the family explicitly; the link-local prefix fe80::/10 requires a scope ID (%InterfaceIndex).

cmd
ping -6 fe80::1a2b:3c4d:5e6f:7a8b%12 -n 2

Output:

perl
Pinging fe80::1a2b:3c4d:5e6f:7a8b%12 with 32 bytes of data:
Reply from fe80::1a2b:3c4d:5e6f:7a8b%12: time<1ms
Reply from fe80::1a2b:3c4d:5e6f:7a8b%12: time<1ms
cmd
rem IPv6 multicast — ping all routers on the link
ping -6 ff02::2%12 -n 1

Output: (one Echo Reply per responding router on the local link)

ICMPv6 also uses Neighbor Discovery (replacing ARP), so the first ping to a never-contacted IPv6 address may show a slight delay while NDP resolves the link-layer address.

Firewall and rate-limit considerations

Many corporate and cloud firewalls deprioritise or rate-limit ICMP to protect against Smurf attacks and DoS amplification. AWS security groups block all ICMP by default. Azure NSGs allow it only with an explicit rule. Linux kernels rate-limit replies via net.ipv4.icmp_ratelimit and net.ipv4.icmp_msgs_per_sec. A host that drops your ICMP but responds to TCP/443 is healthy from the application's perspective; Test-NetConnection -Port is the more reliable health check.

To allow inbound ICMP through Windows Firewall:

powershell
# Enable ICMPv4 Echo Request inbound (Administrator)
New-NetFirewallRule -DisplayName "Allow ICMPv4 Echo Request" -Protocol ICMPv4 `
    -IcmpType 8 -Direction Inbound -Action Allow

Output:

yaml
Name      : {GUID}
DisplayName : Allow ICMPv4 Echo Request
...
Enabled   : True

Common pitfalls

  1. Firewall blocks ICMP — "Request timed out" can mean the host is up but the firewall drops ICMP; try tracert, Test-NetConnection -Port, or another TCP-based test.
  2. -n vs -c — Windows uses -n count; Linux/macOS use -c count. Don't mix them when writing cross-platform scripts.
  3. Loopback always repliesping 127.0.0.1 confirms the TCP/IP stack is loaded but proves nothing about network connectivity. Pinging localhost follows the hosts file, not DNS.
  4. Large -l values need -f for MTU tests — without -f, fragmentation hides the true MTU boundary.
  5. Continuous -t in a script — a script containing ping -t will hang; use -n count in automated contexts.
  6. > NUL to silence output — redirect to NUL when you care only about the exit code and don't want ICMP lines polluting script output.
  7. -w is per-reply, not total-w 1000 -n 100 may take up to 100 s if every probe times out, not 1 s; use a script timeout if you need a hard upper bound.
  8. errorlevel is 1 when ANY packet is lost on some Windows versions — older builds return non-zero if even one of N packets fails; check the Received = N line for partial success.
  9. TTL=0 packets are silently droppedping -i 0 is invalid; use 1 or higher.
  10. -a adds significant delay — reverse DNS may take 1–2 s per address; skip it when you already know the IP.
  11. Cached results in scripts — DNS resolution in ping honours the local resolver cache, so a recent ipconfig /flushdns may not be enough if Windows has cached the negative response.
  12. -l 0 is valid — sends a 0-byte payload (28 bytes of IP+ICMP headers only); useful for testing whether absolutely tiny packets traverse the path.
  13. IPv6 link-local without scope ID failsping fe80::1 returns "Destination host unreachable" unless you append %<ifindex>.
  14. -S srcaddr requires the address to already be assigned — you cannot spoof a source IP that the local stack doesn't own.

Real-world recipes

Wait until a host is reachable before proceeding

cmd
@echo off
:wait
ping -n 1 -w 2000 192.168.1.100 > NUL
if errorlevel 1 (
    echo Waiting for 192.168.1.100...
    goto wait
)
echo Host is up. Continuing.

Output:

csharp
Waiting for 192.168.1.100...
Waiting for 192.168.1.100...
Host is up. Continuing.

Bulk-check a list of hosts

cmd
@echo off
for %%h in (192.168.1.1 192.168.1.100 8.8.8.8) do (
    ping -n 1 -w 1000 %%h > NUL
    if errorlevel 1 (echo %%h UNREACHABLE) else (echo %%h OK)
)

Output:

code
192.168.1.1 OK
192.168.1.100 OK
8.8.8.8 OK

Measure average latency to a server

cmd
ping -n 20 example.com | findstr "Average"

Output:

ini
    Minimum = 13ms, Maximum = 18ms, Average = 14ms

Continuous ping with timestamps

The bare ping does not include timestamps, which makes correlating loss with other events painful. Wrap it in PowerShell to prepend a wall-clock time to each reply.

powershell
ping -t 8.8.8.8 | ForEach-Object { "{0:HH:mm:ss}  {1}" -f (Get-Date), $_ }

Output:

python
14:32:01  Pinging 8.8.8.8 with 32 bytes of data:
14:32:01  Reply from 8.8.8.8: bytes=32 time=14ms TTL=117
14:32:02  Reply from 8.8.8.8: bytes=32 time=15ms TTL=117
14:32:03  Request timed out.
14:32:04  Reply from 8.8.8.8: bytes=32 time=14ms TTL=117

TCP-based reachability with Test-NetConnection

When the target blocks ICMP but accepts TCP — typical of cloud-hosted services — use Test-NetConnection with the relevant port.

powershell
@(
    @{Host='api.example.com'; Port=443},
    @{Host='db.internal';     Port=1433},
    @{Host='cache.internal';  Port=6379}
) | ForEach-Object {
    $r = Test-NetConnection -ComputerName $_.Host -Port $_.Port `
        -InformationLevel Quiet -WarningAction SilentlyContinue
    "{0}:{1}  {2}" -f $_.Host, $_.Port, ($(if($r){'OK'}else{'FAIL'}))
}

Output:

makefile
api.example.com:443  OK
db.internal:1433     FAIL
cache.internal:6379  OK

Latency dashboard with CSV logging

Sample latency every second and write to CSV — feed into Excel or Grafana for a 24-hour view.

powershell
$path = "C:\Logs\latency.csv"
"Timestamp,Target,LatencyMs" | Out-File -Encoding ascii $path
while ($true) {
    $r = Test-Connection -ComputerName 8.8.8.8 -Count 1 -ErrorAction SilentlyContinue
    $ms = if ($r) { $r.Latency } else { -1 }
    "{0:o},8.8.8.8,{1}" -f (Get-Date), $ms | Add-Content -Encoding ascii $path
    Start-Sleep -Seconds 1
}

Output:

css
(none — appends to CSV continuously)

Find the path MTU automatically

A binary search wrapper finds the largest payload that traverses the path without fragmentation in O(log n) probes.

cmd
@echo off
setlocal enabledelayedexpansion
set TARGET=%1
if "%TARGET%"=="" set TARGET=8.8.8.8
set LOW=0
set HIGH=1500
:loop
set /a MID=(LOW+HIGH)/2
ping -n 1 -w 1000 -l !MID! -f %TARGET% >NUL 2>&1
if !errorlevel! equ 0 (set LOW=!MID!) else (set HIGH=!MID!)
set /a DIFF=HIGH-LOW
if !DIFF! gtr 1 goto loop
set /a MTU=LOW+28
echo Path MTU to %TARGET%: !MTU! bytes
endlocal

Output:

css
Path MTU to 8.8.8.8: 1500 bytes

Detect intermittent loss over a long window

A scripted 1000-ping run with the loss percentage extracted gives a quantitative measure of an unstable link.

powershell
$ping = ping -n 1000 -w 500 8.8.8.8 | Select-String "Lost ="
$ping

Output:

ini
    Packets: Sent = 1000, Received = 988, Lost = 12 (1% loss),

A loss rate above 0.5% on Internet paths warrants escalation to the ISP; on a LAN, anything above 0% indicates cabling, NIC, or switch problems.

Verify ICMP is allowed inbound

A quick self-test: ping yourself by name from another host, or check the local firewall directly.

powershell
Get-NetFirewallRule -DisplayName "*Echo Request*" |
    Select-Object DisplayName, Direction, Action, Enabled

Output:

scss
DisplayName                                          Direction Action Enabled
-----------                                          --------- ------ -------
File and Printer Sharing (Echo Request - ICMPv4-In)  Inbound   Allow  True
File and Printer Sharing (Echo Request - ICMPv6-In)  Inbound   Allow  True

If Enabled is False, enable with Enable-NetFirewallRule -DisplayGroup "File and Printer Sharing".

Sweep a /24 to find live hosts

A quick host discovery sweep using parallel pings — faster than running them sequentially.

powershell
1..254 | ForEach-Object -Parallel {
    $ip = "192.168.1.$_"
    if (Test-Connection $ip -Count 1 -Quiet -TimeoutSeconds 1) {
        "$ip UP"
    }
} -ThrottleLimit 50

Output:

code
192.168.1.1 UP
192.168.1.10 UP
192.168.1.50 UP
192.168.1.100 UP
192.168.1.254 UP

-Parallel requires PowerShell 7+; in PowerShell 5.1 use a Workflow or Start-Job for the same effect.

See also

  • ipconfig — view interfaces, gateways, and DNS
  • tracert — locate where a path fails
  • pathping — per-hop loss measurement
  • arp — Layer 2 (ARP cache) view
  • nslookup — resolve names to test before pinging
  • netstat — see established TCP connections
  • Linux ping — cross-platform comparison (most flags are inverted: -c N instead of -n N, etc.)

Sources