Query is a UDP protocol introduced in beta 1.9pre4 for the purpose of querying server properties. It's meant to be compatible with the UT3 (or GameSpot) Query Protocol

A slightly simpler alternative to the query protocol involves connecting to the main minecraft TCP port and sending a Server List Ping packet, which returns motd, number of users and number of slots. More details on the main protocol page.

Server to Client Packet Format

Handshake

Generating a Session ID

The session ID is used identify your requests. The following examples use session ID = 1 (encoded as 00 00 00 01 on the hex dumps).

Only the lower 4-bits on each byte of the session ID should be used as Minecraft does not process the higher 4-bits on each byte. To convert any 4-byte session ID to a valid Minecraft session ID, simply mask the bits with sessionId & 0x0F0F0F0F.

Request

Send a request with an empty payload.

Field name

Field Type

Example

Magic

byte, byte

FE FD

Type

byte

09

Session ID

int32

00 00 00 01

Payload

(empty)

Dump:

FE FD 09 00 00 00 01

Response

The response payload will be a challenge token encoded as a null-terminated string. You should convert it to an int32 and store it

Field name

Field Type

Example

Type

byte

09

Session ID

int32

00 00 00 01

Challenge token string

Null-terminated string

"9513307\0"

In this example, after parsing the string "9513307\0" as an integer and packing it as a big endian int32, the result should be 00 91 29 5B

Dump:

09 00 00 00 01 39 35 31 33 33 30 37 00 | .....9513307.

Expiration of the challenge token

Note that the challenge token is bound to your IP and port (as opposed to the [session ID]), and lasts up to 30 seconds. You read that right, it's up to; it's not "your token will expire after 30 seconds", it's "every token ever" is expired every 30 seconds. This means it's entirely possible that you may get a token and use it within the same second and have it expire.

Additionally:

You'll need to provide your challenge token, or you will not receive any reply. If you provide a token and it's wrong, you still won't receive a reply. With that in mind, if you're going to store your challenge token and use it later then you may want to do some kind of timeout on waiting for a reply, in case the server restarted and your token is no longer valid. It's impossible to identify between an offline server and a server that refused your challenge without any additional requests, so you'll want to try for another challenge token and if that fails then flag them as unavailable

Full stat

Request

The request is the same as in a basic stat, except the payload must be padded to 8 bytes. Sending 0x00 0x00 0x00 0x00 at the end works.

Field name

Field Type

Example

Magic

byte, byte

FE FD

Type

byte

00

Session ID

int32

00 00 00 01

Challenge token

int32

00 91 29 5B

Padding

00 00 00 00

Dump:

FE FD 00 00 00 00 01 00 91 29 5B 00 00 00 00

Response

The response is in two parts. The first part is a list of null-terminated strings, representing (key1, value1, key2, value2 ...). The second part is another list of null-terminated strings, each representing a player.

A simple way to parse the payload is to ignore the first 11 bytes, and then split the response around the token \x00\x01player_\x00\x00. At the very end there's an extra null byte.