Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mc-status - Minecraft Server Status Checker (Java & Bedrock)

CI npm license

A Node library and CLI to check whether a Minecraft server is online and get live player counts, MOTD, version, latency and favicon, on both Java and Bedrock Edition. It speaks the raw protocols directly over TCP and UDP, resolves _minecraft._tcp SRV records the way the vanilla client does, and has zero runtime dependencies.

npx mc-status play.talonmc.net
online  play.talonmc.net:25565 (java)
  players   1613 / 5000
  version   Velocity 1.7.2-1.21.10 (protocol 773)
  latency   195ms
  motd      TalonMC | COBBLEMON NOW RELEASED!
  motd      Join Now | discord.gg/talonserver
  srv       java.talonmc.net:25565

Features

  • Java Edition ping over the 1.7+ Server List Ping protocol (handshake, status, ping/pong latency)
  • Bedrock Edition ping over RakNet UNCONNECTED_PING, including gamemode and server GUID
  • SRV resolution for _minecraft._tcp.<host>, sorted by priority then weight, exactly like the client
  • MOTD handling for both legacy § strings and modern JSON chat components, with a plain-text version ready to print
  • Favicon returned as the server's original data:image/png;base64 URI
  • Timeouts and AbortSignal on every call, so a dead host can never hang your process
  • Zero dependencies, ESM, first-class TypeScript types
  • Works on Node 18 and newer

Install

npm install mc-status

Or run the CLI without installing anything:

npx mc-status play.hypixel.net

Usage

Check if a Minecraft server is online

import { status } from "mc-status";

const server = await status("play.hypixel.net");

console.log(server.players.online); // 31930
console.log(server.players.max);    // 200000
console.log(server.version.name);   // "Requires MC 1.8 / 1.21"
console.log(server.latency);        // 209
console.log(server.motd.clean);     // "Hypixel Network [1.8/26.2]\n  SB 0.27 TORRHUS & SAFARI | SUMMER EVENT"

Ping a Bedrock Edition server

Bedrock uses UDP on port 19132 by default and does not use SRV records.

import { statusBedrock } from "mc-status";

const server = await statusBedrock("play.talonmc.net");

console.log(server.edition);        // "bedrock"
console.log(server.version.name);   // "26.45"
console.log(server.gamemode);       // "Survival"
console.log(server.players.online); // 1613

Handle servers that could be either edition

statusAuto pings Java and Bedrock at the same time and resolves with whichever answers first.

import { statusAuto } from "mc-status";

const server = await statusAuto("play.hypixel.net");
console.log(`${server.edition} server with ${server.players.online} players`);

Custom ports and non-standard addresses

A port in the address string wins over SRV. You can also pass it explicitly.

import { status, statusBedrock } from "mc-status";

await status("play.example.com:25566");
await status("play.example.com", { port: 25566 });
await status("203.0.113.10", { port: 25565, resolveSrv: false });
await statusBedrock("203.0.113.10", { port: 19133 });

Uptime monitoring with a timeout and abort

import { status, McStatusError } from "mc-status";

const controller = new AbortController();
setTimeout(() => controller.abort(), 3000);

try {
  const server = await status("play.example.com", {
    timeout: 2500,
    signal: controller.signal,
  });
  console.log("up", server.players.online);
} catch (error) {
  if (error instanceof McStatusError) {
    console.log("down", error.code); // TIMEOUT, CONNECTION_FAILED, MALFORMED, ...
  }
}

Save the server favicon to a PNG

import { writeFile } from "node:fs/promises";
import { status } from "mc-status";

const server = await status("play.hypixel.net");

if (server.favicon) {
  const base64 = server.favicon.replace(/^data:image\/png;base64,/, "");
  await writeFile("favicon.png", Buffer.from(base64, "base64"));
}

Poll a list of servers concurrently

import { statusAuto } from "mc-status";

const addresses = ["play.hypixel.net", "play.talonmc.net", "play.example.com"];

const results = await Promise.all(
  addresses.map(async (address) => {
    try {
      const server = await statusAuto(address, { timeout: 3000 });
      return { address, online: true, players: server.players.online };
    } catch {
      return { address, online: false, players: 0 };
    }
  }),
);

console.table(results);

CLI

mc-status <address> [options]

Options:
  --bedrock            Ping as Bedrock Edition (UDP RakNet, default port 19132)
  --auto               Try Java and Bedrock, report whichever answers first
  --json               Print the full result as JSON
  --quiet              Print nothing, exit 0 if online and 1 if offline
  --port <number>      Override the port (disables SRV lookup for Java)
  --timeout <ms>       Milliseconds before giving up (default 5000)
  --protocol <number>  Handshake protocol version (default -1)
  --no-srv             Skip the _minecraft._tcp SRV lookup
  -h, --help           Show this help

The CLI exits 0 when the server answered and 1 when it did not, so it drops straight into a health check:

mc-status play.example.com --quiet || echo "server is down"

Pipe the JSON into jq for scripting:

npx mc-status play.hypixel.net --json | jq '.players.online'

API reference

status(address, options?): Promise<ServerStatus>

Pings a Java Edition server. address may include a port (host:port). Rejects with McStatusError if the server does not answer.

statusBedrock(address, options?): Promise<ServerStatus>

Pings a Bedrock Edition server over UDP. Defaults to port 19132. Never performs an SRV lookup.

statusAuto(address, options?): Promise<ServerStatus>

Races a Java and a Bedrock ping, resolving with the first success. Rejects with code UNREACHABLE only if both fail. Accepts javaPort and bedrockPort in addition to the normal options.

isOnline(address, options?): Promise<boolean>

Convenience wrapper around statusAuto that never throws.

pingJava(host, options?) / pingBedrock(host, options?)

Lower-level entry points that take a bare hostname rather than an host:port string.

parseAddress(address): { host, port }

Splits host, host:port, [ipv6]:port and scheme-prefixed strings. port is undefined when the address did not carry one.

resolveMinecraftSrv(host): Promise<SrvRecord | null>

Looks up _minecraft._tcp.<host> and returns the highest-priority record, or null if there is none. Returns null immediately for literal IP addresses.

stripFormatting(text): string

Removes legacy § colour and style codes, including BungeeCord §x§r§r§g§g§b§b hex sequences.

componentToLegacy(component): string

Flattens a modern JSON chat component (with extra, color, bold, and friends) into a legacy §-coded string.

Bedrock helpers

parseAdvertisement(string), buildUnconnectedPing(timestamp, guid) and readUnconnectedPong(buffer) are exported so you can build your own RakNet tooling or unit test against captured packets.

Options

Option Type Default Applies to Description
port number 25565 Java, 19132 Bedrock both Explicit port. Setting it disables the SRV lookup.
timeout number 5000 both Milliseconds before the ping is abandoned.
protocolVersion number -1 Java Handshake protocol version. -1 means "undefined", which every modern server accepts.
resolveSrv boolean true Java Set to false to skip the SRV lookup.
signal AbortSignal - both Aborts the ping early.
javaPort number - statusAuto Port used for the Java attempt only.
bedrockPort number - statusAuto Port used for the Bedrock attempt only.

ServerStatus

Field Type Description
edition "java" | "bedrock" Which protocol produced this result.
host string The hostname you asked for, before SRV resolution.
port number The port actually connected to.
srvRecord { host, port } | null The SRV record that was followed, if any.
version.name string Version string as the server reports it. Often a brand name, not a number.
version.protocol number | null Numeric protocol version.
players.online number Players currently online.
players.max number Slot limit as advertised.
players.sample { name, id }[] Sample player list. Java only, and frequently empty or spoofed.
motd.raw string MOTD with § codes intact.
motd.clean string MOTD with all formatting stripped.
motd.json unknown | null The original chat component, when the server sent one.
favicon string | null data:image/png;base64,... URI. Java only.
latency number Round-trip milliseconds.
gamemode string | null Bedrock only.
serverGuid string | null Bedrock only.
raw unknown The untouched payload, for fields this library does not model.

McStatusError

Thrown for every failure. Carries code, host and port.

Code Meaning
TIMEOUT No reply within timeout milliseconds.
CONNECTION_FAILED DNS, refused connection or socket error.
CONNECTION_CLOSED Server hung up before sending a status.
MALFORMED Reply was not valid protocol or valid JSON.
ABORTED The supplied AbortSignal fired.
UNREACHABLE statusAuto only, both editions failed.

How it works

Java Edition uses the Server List Ping flow introduced in 1.7. The client sends a handshake packet with next-state 1, then an empty status request. The server replies with a JSON document describing itself. A ping packet carrying a timestamp is then exchanged to measure latency. Packets are length-prefixed with VarInts, so this library buffers until a complete frame has arrived rather than assuming one packet per TCP read.

Bedrock Edition uses RakNet's offline UNCONNECTED_PING packet: a 33-byte UDP datagram containing a timestamp, the 16-byte RakNet magic, and a client GUID. The server answers with UNCONNECTED_PONG carrying a semicolon-separated advertisement string:

MCPE;<motd line 1>;<protocol>;<version>;<online>;<max>;<server guid>;<motd line 2>;<gamemode>;<gamemode id>;<port v4>;<port v6>

SRV records let a server advertise play.example.com while running on a different host and port. Java clients look up _minecraft._tcp.play.example.com before connecting, and so does this library. Bedrock clients do not, so statusBedrock skips it.

Notes and limitations

  • Servers below 1.7 use the older legacy ping and are not supported.
  • players.sample is under the server's control. Many networks spoof it or leave it empty, so do not treat it as a real player list.
  • players.online reflects whatever the server chooses to advertise. Proxies commonly report a whole network's count on every backend.
  • Query protocol (GameSpy, port 25565 UDP) is not implemented. Server List Ping covers what most tools need.

Related

Built and maintained by Best Minecraft Server Lists. Every ranking below is ordered on player counts taken from a direct server ping, never on numbers a server reports about itself.

Sister libraries:

Contributing

Issues and pull requests are welcome. Run the test suite with:

npm install
npm test

License

MIT

About

Minecraft server status checker for Java and Bedrock Edition. Live player count, MOTD, version, latency and favicon, with SRV resolution. Node library and CLI, zero dependencies.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages