Skip to content

Codfish789/mcping

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mcping

mcping is a headless Minecraft Java latency checker. Each probe opens a real TCP connection, collects ICMP echo latency for the same resolved/connected IP, and speaks the Minecraft Java status protocol, which makes the result closer to what a player, proxy, or monitoring system experiences when reaching a server. Optional probes can also collect best-effort login/play latency. Route mode runs a standalone Minecraft TCP route trace through nexttrace.

Probe path:

SRV lookup -> A/AAAA lookup -> TCP connect -> Minecraft handshake/status -> Minecraft ping/pong -> ICMP echo to the same IP
optional: login/play probe
route mode: SRV/default/explicit port resolution -> nexttrace TCP route trace to the Minecraft port

Each probe prints realtime segmented timings. The final summary reports min / avg / max / median / p95 for every metric.

Features

  • Minecraft Java status/ping protocol probing
  • ICMP echo probing through the system ping command
  • Best-effort Minecraft login/play latency probing
  • Minecraft handshake domain override for IP/proxy targets
  • Standalone nexttrace route detection using TCP to the Minecraft port
  • _minecraft._tcp SRV lookup support
  • Domain, IPv4, IPv6, host:port, and host port target formats
  • CLI style inspired by ping and tcping
  • Continuous probing with Ctrl+C summary
  • IPv4-only and IPv6-only modes
  • JSON output for monitoring integrations
  • Cross-platform release build matrix
  • Static Go binary with no third-party dependencies

Options

Usage:
  mcping [options] host [port]

Target:
  host                 Server domain, IPv4, or IPv6
  port                 Optional port. If omitted, SRV is tried first, then 25565.

Count:
  -n count             Number of probes, tcping-style
  -c count             Number of probes, ping-style; 0 means infinite
  -t                   Probe until stopped

Timing:
  -i seconds           Interval between probes
  -w ms                Timeout per probe in milliseconds
  --timeout seconds    Timeout per probe in seconds; overrides -w

Network:
  -4                   IPv4 only
  -6                   IPv6 only
  --no-srv             Disable _minecraft._tcp SRV lookup

Minecraft:
  --protocol n         Minecraft protocol version used in the handshake, default 765
  --play               Also attempt a login/play latency probe
  --play-name name     Username for --play probes, default mcping
  --domain name        Override Minecraft handshake serverAddress/domain
  --server-address name  Same as --domain

Route:
  --route              Run only nexttrace TCP route detection to the Minecraft port
  --route-timeout sec  Timeout for --route, default 60
  MCPING_NEXTTRACE     nexttrace executable path, fallback when PATH lookup fails

Output:
  --json               Print JSON
  --version            Print version information

Output

Realtime output example:

Target: mc.hypixel.net -> mc.hypixel.net:25565 (default-port, serverAddress=mc.hypixel.net)
2026-06-26 03:22:47.891  #001  ip=mc.hypixel.net:25565(172.65.197.160:25565)  icmp=203.00 ms  tcp=205.31 ms  status=358.43 ms  pong=270.49 ms  play=fail(online-mode encryption requested; authenticated/encrypted play probing is not supported)

Field meanings:

Target         Final target used for probing
serverAddress  Address sent inside the Minecraft handshake; can be overridden with --domain
ip             Display target and actual remote address as host:port(ip:port)
icmp           ICMP echo latency to the same IP used by this probe
tcp            TCP connect time
status         Minecraft handshake + status request/response time
pong           Minecraft ping/pong round-trip time
play           Best-effort login/play latency, only with --play

status, pong, and play:

status = Minecraft handshake + status request/response phase
pong   = Minecraft ping/pong RTT after status has completed
play   = login/play probe time until login success when the server allows it

--play is intentionally conservative. Online-mode servers request encrypted authenticated login, which this tool does not perform. In that case the status/pong metrics can still succeed, while play reports a failure reason.

Domain Override

Some Minecraft servers and proxies check the hostname inside the Minecraft handshake. If you connect directly to an IP address, the TCP connection can succeed while the server rejects or misroutes the Minecraft protocol because it expected a domain.

Use --domain to connect to one host/IP while sending a different Minecraft serverAddress:

./mcping-linux-amd64-v1 203.0.113.10 --domain play.example.com
./mcping-linux-amd64-v1 203.0.113.10 25565 --domain play.example.com

--server-address is an alias for --domain.

When no explicit port is provided, --domain also supports Minecraft SRV lookup. In that case _minecraft._tcp.<domain> can provide the Minecraft port, while the TCP connection host remains the target you typed:

./mcping-linux-amd64-v1 203.0.113.10 --domain play.example.com

If play.example.com has an SRV record pointing to port 25566, mcping connects to 203.0.113.10:25566 and sends play.example.com in the Minecraft handshake.

Explicit ports still skip SRV:

./mcping-linux-amd64-v1 203.0.113.10 25565 --domain play.example.com

This affects Minecraft status/pong and --play handshakes. It does not change the TCP connection host, ICMP target, or --route target. It can change the port when --domain has an SRV record and no explicit port was supplied.

Route Detection

--route is route-only mode. It does not run ICMP ping, TCP latency probes, Minecraft status, Minecraft pong, or play probing. It resolves the Minecraft target and then runs nexttrace once:

./mcping-linux-amd64-v1 mc.example.net --route

The route trace is Minecraft-aware in target selection:

SRV/default/explicit port resolution -> first resolved A/AAAA candidate -> nexttrace --tcp --port <minecraft-port>

This means the route trace follows the TCP path to the Minecraft service port instead of a generic ICMP traceroute. For Cloudflare Anycast and other proxy/edge deployments, the traced destination is the player-facing edge IP selected by normal DNS/SRV resolution, not the hidden origin.

Important limits:

nexttrace traces the network path with TCP packets to the Minecraft port.
It cannot make every intermediate router answer a Minecraft status/pong packet.
Use normal mcping output for tcp/status/pong latency, and use --route separately for path visibility.

nexttrace is not bundled into mcping. Route lookup order is:

nexttrace in system PATH -> MCPING_NEXTTRACE environment variable -> install command

Point mcping to a custom nexttrace executable with an environment variable:

$env:MCPING_NEXTTRACE="C:\Tools\nexttrace.exe"
.\mcping-windows-amd64-v1.exe mc.example.net --route

If nexttrace is not in system PATH and MCPING_NEXTTRACE is not set, --route prints the official install command:

curl -sL nxtrace.org/nt | bash

On Linux, TCP route tracing can still require raw socket permissions because traceroute receives ICMP TTL-exceeded replies while sending TCP probes. If nexttrace reports operation not permitted, grant the executable the required capabilities:

sudo setcap cap_net_raw,cap_net_admin+eip "$(readlink -f "$(command -v nexttrace)")"
getcap "$(readlink -f "$(command -v nexttrace)")"

On Windows, TCP route tracing with nexttrace may require Administrator privileges because raw packet capture/injection is commonly needed.

Summary

Final summary example:

Summary: sent=2 received=2 lost=0 loss=0.0%
ICMP: min=200.00 ms  avg=201.50 ms  max=203.00 ms  median=201.50 ms  p95=202.85 ms
TCP: min=202.42 ms  avg=203.87 ms  max=205.31 ms  median=203.87 ms  p95=205.17 ms
Status: min=358.43 ms  avg=363.09 ms  max=367.75 ms  median=363.09 ms  p95=367.29 ms
Pong: min=261.90 ms  avg=266.20 ms  max=270.49 ms  median=266.20 ms  p95=270.06 ms
Play: min=421.33 ms  avg=424.10 ms  max=426.87 ms  median=424.10 ms  p95=426.59 ms

Summary fields:

sent       Number of probes started
received   Number of successful pong responses
lost       Number of failed probes
loss       Failure percentage
min        Minimum value
avg        Average value
max        Maximum value
median     Median value
p95        95th percentile; 95% of successful probes are <= this value

p95 is useful for understanding stability. Averages can look fine while rare spikes are still bad; p95 makes those tail-latency problems easier to see.

JSON Output

Normal probe example:

{
  "target": {
    "original_host": "mc.hypixel.net",
    "connect_host": "mc.hypixel.net",
    "port": 25565,
    "server_address": "mc.hypixel.net",
    "source": "default-port"
  },
  "samples": [
    {
      "timestamp": "2026-06-26 03:22:50.047",
      "ok": true,
      "icmp_ms": 203.000,
      "connect_ms": 208.523,
      "status_ms": 381.426,
      "pong_ms": 267.408,
      "play_ms": null,
      "ip": "172.65.197.160",
      "address": "172.65.197.160:25565",
      "error": null,
      "play_error": "online-mode encryption requested; authenticated/encrypted play probing is not supported"
    }
  ],
  "summary": {
    "sent": 1,
    "received": 1,
    "lost": 0,
    "loss_percent": 0,
    "icmp": {
      "min_ms": 203.000,
      "avg_ms": 203.000,
      "max_ms": 203.000,
      "median_ms": 203.000,
      "p95_ms": 203.000
    },
    "tcp": {
      "min_ms": 208.523,
      "avg_ms": 208.523,
      "max_ms": 208.523,
      "median_ms": 208.523,
      "p95_ms": 208.523
    },
    "status": {
      "min_ms": 381.426,
      "avg_ms": 381.426,
      "max_ms": 381.426,
      "median_ms": 381.426,
      "p95_ms": 381.426
    },
    "pong": {
      "min_ms": 267.408,
      "avg_ms": 267.408,
      "max_ms": 267.408,
      "median_ms": 267.408,
      "p95_ms": 267.408
    }
  }
}

Route-only example:

{
  "target": {
    "original_host": "mc.hypixel.net",
    "connect_host": "mc.hypixel.net",
    "port": 25565,
    "server_address": "mc.hypixel.net",
    "source": "default-port"
  },
  "samples": [],
  "summary": {
    "sent": 0,
    "received": 0,
    "lost": 0,
    "loss_percent": 0
  },
  "route": {
    "tool": "nexttrace",
    "protocol": "minecraft_tcp",
    "target": "172.65.197.160",
    "port": 25565,
    "address": "172.65.197.160:25565",
    "command": ["nexttrace", "--tcp", "--port", "25565", "--json", "172.65.197.160"],
    "ok": true,
    "duration_ms": 12034.120,
    "output": "{...nexttrace json output...}"
  }
}

The JSON summary includes grouped stats for icmp, tcp, status, pong, and play when samples exist for those metrics. Route-only JSON contains an empty samples array, a zeroed summary object, and a route object with the nexttrace command, selected target, duration, raw output, and any error or exit code.

SRV Lookup

When no explicit port is provided, mcping tries:

_minecraft._tcp.<host>

If an SRV record exists:

connect address = SRV target and port
serverAddress   = original host provided by the user

If no SRV record exists, it falls back to:

host:25565

Explicit ports skip SRV lookup:

./mcping-linux-amd64-v1 mc.example.net 25566
./mcping-linux-amd64-v1 mc.example.net:25566

Disable SRV lookup:

./mcping-linux-amd64-v1 mc.example.net --no-srv

Exit Codes

0   At least one probe succeeded
1   All probes failed
2   Invalid arguments or target resolution failed

Version v0.5.0

Highlights:

  • Added --domain / --server-address to override the Minecraft handshake serverAddress for IP and proxy targets.
  • Domain override works with status, pong, and optional play probes.
  • Domain override supports Minecraft SRV lookup when no explicit port is provided, using the SRV port while keeping the typed connection host.
  • Explicit ports still skip SRV lookup.
  • Invalid SRV ports are rejected during target resolution.
  • MCPING_NEXTTRACE documentation now correctly describes it as an executable path fallback after system PATH lookup.

Build

Build all supported release targets:

powershell -ExecutionPolicy Bypass -File .\scripts\build.ps1 -Version v0.5.0

The build script first runs:

go test -buildvcs=false ./...

Then it writes release binaries into:

dist/

It also writes SHA256 checksums to:

dist/checksums.txt

Manual single-target build:

$env:CGO_ENABLED="0"
$env:GOOS="linux"
$env:GOARCH="amd64"
$env:GOAMD64="v1"
go build -buildvcs=false -trimpath -ldflags "-s -w" -o dist/mcping-linux-amd64-v1 ./cmd/mcping

Project Layout

.
|-- cmd/mcping/       CLI source code and tests
|-- dist/             Release binaries and checksums
|-- scripts/          Build scripts
|-- go.mod            Go module definition
|-- LICENSE           MIT license
`-- README.md         Project documentation

Release Files

Platform Architecture Variant File Description
Android ARM64 - mcping-android-arm64 Android ARM64
macOS AMD64 V1 mcping-darwin-amd64-v1 Compatible AMD64 build
macOS AMD64 V3 mcping-darwin-amd64-v3 Modern AMD64 optimized build
macOS ARM64 - mcping-darwin-arm64 Apple Silicon
FreeBSD 386 V1 mcping-freebsd-386-v1 FreeBSD 32-bit
FreeBSD AMD64 V1 mcping-freebsd-amd64-v1 FreeBSD AMD64 V1
FreeBSD AMD64 V3 mcping-freebsd-amd64-v3 FreeBSD AMD64 V3
FreeBSD ARM64 - mcping-freebsd-arm64 FreeBSD ARM64
Linux 386 V1 mcping-linux-386-v1 Linux 32-bit
Linux AMD64 V1 mcping-linux-amd64-v1 Compatible AMD64 build
Linux AMD64 V3 mcping-linux-amd64-v3 Modern AMD64 optimized build
Linux ARM V5 mcping-linux-arm-5 Linux ARM v5
Linux ARM V6 mcping-linux-arm-6 Linux ARM v6
Linux ARM V7 mcping-linux-arm-7 Linux ARM v7
Linux ARM64 - mcping-linux-arm64 Linux ARM64
Linux LoongArch64 - mcping-linux-loong64 Linux LoongArch64
Linux MIPS - mcping-linux-mips Linux MIPS
Linux MIPS64 - mcping-linux-mips64 Linux MIPS64
Linux MIPS64LE - mcping-linux-mips64le Linux MIPS64 little-endian
Linux MIPSLE - mcping-linux-mipsle Linux MIPS little-endian
Linux RISC-V64 - mcping-linux-riscv64 Linux RISC-V 64-bit
Linux S390X - mcping-linux-s390x Linux IBM Z
Windows 386 V1 mcping-windows-386-v1.exe Windows 32-bit
Windows AMD64 V1 mcping-windows-amd64-v1.exe Compatible AMD64 build
Windows AMD64 V3 mcping-windows-amd64-v3.exe Modern AMD64 optimized build
Windows ARM64 - mcping-windows-arm64.exe Windows ARM64

windows/arm is not supported by the current standard Go toolchain, so mcping-windows-arm-7.exe is not generated.

Checksums

scripts/build.ps1 generates a plain SHA256 checksum file:

dist/checksums.txt

Format:

<sha256>  <filename>

Example verification on Linux:

cd dist
sha256sum -c checksums.txt

AMD64 V1 vs V3

V1  Baseline AMD64 instruction set. Best compatibility.
V3  Newer AMD64 instruction set. Potentially faster, but less compatible.

If unsure, choose V1.

Tests

go test -buildvcs=false ./...

Covered areas:

target parsing
ping/tcping-style argument parsing
VarInt encoding/decoding
IPv4/IPv6 filtering
ICMP ping output parsing
nexttrace route argument building
summary statistics

License

MIT. See LICENSE.

FAQ

Why is this different from system ping?

System ping usually uses ICMP. Minecraft Java clients use TCP and the Minecraft protocol. A server, proxy, or firewall may block ICMP while TCP 25565 works, or ICMP may be fast while Minecraft status is slow. mcping reports both ICMP and Minecraft protocol timings so you can compare the layers.

What does ICMP measure?

icmp runs the operating system ping command once per probe and parses its time=... ms result. When TCP connects successfully, ICMP is sent to the same remote IP used by that TCP connection after the Minecraft protocol timings have been collected. If TCP cannot connect, ICMP is sent to the first resolved candidate IP. ICMP may be blocked or deprioritized independently from TCP 25565.

What about Cloudflare Anycast?

When a server uses Cloudflare Anycast or another TCP proxy, mcping measures the player-facing edge/proxy path, not the hidden origin behind it. This is usually the correct latency from the player's point of view.

To avoid measuring a different Anycast edge, ICMP is aligned to the same IP used by the probe's TCP connection. ICMP is collected after the Minecraft protocol timings, so an ICMP timeout does not inflate status or pong. Still, ICMP and TCP/Minecraft traffic can be handled differently by Cloudflare, so use tcp, status, and especially pong as the authoritative Minecraft latency metrics. Treat icmp as a comparison signal.

When --route is enabled, route detection is standalone. It resolves the Minecraft target, selects the first resolved A/AAAA candidate allowed by -4 or -6, and runs a TCP trace to the Minecraft port. This is the closest route-level view of the path a Minecraft client uses, but it still cannot reveal a hidden origin behind Cloudflare or another proxy.

What does --play measure?

--play opens a separate Minecraft login connection and measures how long it takes to reach login success when the server allows an unauthenticated best-effort probe. Online-mode servers request encrypted authenticated login; when that happens, play reports an error instead of pretending to measure gameplay latency.

play is closer to player entry behavior than server-list pong, but it is not a full replacement for a real authenticated client session with Play-state keepalive handling.

Why does an explicit port skip SRV?

This follows common Minecraft client behavior. If a port is provided, the tool connects to that exact host and port instead of querying _minecraft._tcp.

About

mcping is a headless Minecraft Java latency checker. It does not use ICMP. Instead, it opens a real TCP connection and speaks the Minecraft Java status protocol, which makes the result closer to what a player, proxy, or monitoring system experiences when reaching a server.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors