A Python library for building ICMP diagnostics with raw sockets. The current API focuses on reusable building blocks instead of wrapping platform tools, so you can compose pings, probes, and traceroute-like flows directly from Python.
- Context-managed
Clientthat takes care of raw socket setup and teardown probe()for single TTL measurements,ping()for repeated samples, andtraceroute()for hop discovery- Rich dataclasses (
EchoResult,TracerouteResult,ReceivedPacket, and friends) for post-processing and formatting - Optional reverse DNS lookup per request
- Clear
RawSocketPermissionErrorwhen the interpreter lacksCAP_NET_RAW
- Python 3.11–3.14 (prefers 3.14 when available; see
pyproject.toml) - A Linux environment with permission to open ICMP raw sockets
Grant the capability once for your Python interpreter (the helper works with uvx or inside a venv and launches the demo after verifying success):
uvx icmpx --bootstrap-capIf you cannot use the helper, apply setcap manually:
sudo setcap cap_net_raw+ep "$(realpath $(which python))"Get the sources and prepare a uv environment:
git clone https://github.com/oornnery/icmpx.git
cd icmpx
uv python install 3.14 # optional; skip if uv cannot fetch it yet
uv venv --python 3.14 # drop --python to let uv pick another 3.11+ runtime
uv sync
uv pip install .
uv run icmpx --bootstrap-cap # applies CAP_NET_RAW and starts the demo once verifiedAfter granting CAP_NET_RAW, run any of the examples:
uv run examples/ping.pyOr explore the traceroute example:
uv run examples/traceroute.pyfrom icmpx import Client
with Client(timeout=1.5) as client:
results = client.ping("8.8.8.8", count=3)
for result in results:
if result.error:
print(f"{result.request.addr}: {result.error}")
else:
print(
f"reply from {result.reply.received_packet.ip_header.src_addr} "
f"in {result.reply.rtt:.2f} ms"
)Each EchoResult carries the original request, an EchoReply with the measured RTT, and any ICMP errors returned during the exchange.
from icmpx import Client
with Client(resolve_dns_default=True) as client:
trace = client.traceroute("1.1.1.1", probes=2)
for hop in trace.hops:
addr = hop.addr or "?"
host = hop.hostname or "?"
rtts = [
f"{probe.rtt:.2f} ms" if probe.rtt != float("inf") else "timeout"
for probe in hop.probes
]
print(f"{hop.ttl:>2}: {addr:<16} {host:<32} {' '.join(rtts)}")Client.traceroute() returns a TracerouteResult with per-hop metadata, including optional reverse DNS resolution and all collected probe RTTs.
uv run examples/mtr.py 1.1.1.1 -c 10 -i 0.5This script streams probe statistics in a Rich table, updating packet loss and RTT metrics per hop across the configured cycles.
(icmpx) ➜ icmpx git:(main) ✗ uv run examples/mtr.py 8.8.8.8 -c 100
Found existing alias for "uv run". You should use: "uvr"
MTR to 8.8.8.8
┌─────────┬─────────────────────────────┬──────────────────────────────────────────────────────────────┬──────────┬──────────┬──────────────┬────────────┬───────────┬──────────┬──────────┐
│ Hop │ Address │ Hostname │ Sent │ Recv │ Loss % │ Last │ Avg │ Best │ Worst │
├─────────┼─────────────────────────────┼──────────────────────────────────────────────────────────────┼──────────┼──────────┼──────────────┼────────────┼───────────┼──────────┼──────────┤
│ 1 │ 172.19.112.1 │ _gateway │ 100 │ 100 │ 0.0 │ 0.69 │ 0.53 │ 0.30 │ 5.53 │
│ 2 │ 192.168.15.1 │ menuvivofibra │ 100 │ 100 │ 0.0 │ 3.52 │ 5.46 │ 3.07 │ 37.70 │
│ 3 │ 189.97.117.7 │ ip-189-97-117-7.user.vivozap.com.br │ 100 │ 100 │ 0.0 │ 7.77 │ 9.46 │ 5.46 │ 30.08 │
│ 4 │ 201.1.228.105 │ 201-1-228-105.dsl.telesp.net.br │ 100 │ 100 │ 0.0 │ 9.13 │ 9.58 │ 4.53 │ 28.16 │
│ 5 │ 187.100.196.140 │ 187-100-196-140.dsl.telesp.net.br │ 100 │ 72 │ 28.0 │ 13.78 │ 11.10 │ 4.97 │ 41.67 │
│ 6 │ ? │ │ 100 │ 0 │ 100.0 │ - │ - │ - │ - │
│ 7 │ 72.14.220.222 │ │ 100 │ 100 │ 0.0 │ 7.78 │ 11.94 │ 5.76 │ 46.18 │
│ 8 │ 172.253.69.243 │ │ 100 │ 100 │ 0.0 │ 10.51 │ 11.85 │ 7.07 │ 29.55 │
│ 9 │ 108.170.248.215 │ │ 100 │ 100 │ 0.0 │ 12.49 │ 10.69 │ 5.80 │ 30.14 │
│ 10 │ 8.8.8.8 │ dns.google │ 100 │ 100 │ 0.0 │ 9.79 │ 10.79 │ 5.82 │ 42.93 │
└─────────┴─────────────────────────────┴──────────────────────────────────────────────────────────────┴──────────┴──────────┴──────────────┴────────────┴───────────┴──────────┴──────────┘Launch the Textual interface to explore multiple diagnostics side by side:
uv run icmpxOr run it without cloning by using uvx:
uvx icmpxUse q (or the terminal window controls) to exit at any time. All views depend on ICMP raw sockets, so make sure CAP_NET_RAW is granted before launching the app.
The UI exposes dedicated views for:
Ping: continuous probes with aStopbutton, a live RTT/loss summary strip, and configurable TTL/timeout.MultiPing: batched targets with per-host aggregates that remain visible beneath the log of individual replies.Traceroute: hop discovery with optional reverse DNS lookup and per-probe RTT details once the run completes.MTR: rolling cycles that refresh hop statistics until stopped, mirroring the behaviour of classicmtr.
Tips:
- Switch between views through the left-hand navigation buttons without restarting an active session.
- Validation messages and permission errors surface as notifications at the bottom of the screen.
- When experimenting with rapid probes, increase the timeout if your network drops packets aggressively.
examples/ping.py— shortest path to send repeated ICMP echo requestsexamples/traceroute.py— hop-by-hop discovery using the library APIicmpx/demo.py— Textual UI bundling Ping, MultiPing, Traceroute, and MTR views (run it viauv run icmpxoruvx icmpx)examples/mtr.py— Rich-powered live table that mimics themtrworkflow
Feel free to copy these scripts as starting points for your own automation or integrate the Client directly inside existing services.
If the interpreter cannot create a raw socket, Client raises RawSocketPermissionError with guidance on granting CAP_NET_RAW. Timeouts surface as EchoResult.error == "timeout" while other ICMP responses preserve their numeric type/code so you can present detailed diagnostics.
- IPv6 probes and traceroutes
- Aggregated multiping support across multiple targets
- asyncio-compatible client implementation
- Additional examples and narrative documentation
Contributions and discussion are welcome — open an issue with your use case or ideas.



