Server queries: Difference between revisions
m (update A2S_PLAYERS to not use SERVERQUERY_CHALLENGE) |
m (Added Objective C library to the implementations list) |
||
(90 intermediate revisions by 43 users not shown) | |||
Line 1: | Line 1: | ||
{{ | {{LanguageBar}} | ||
}} | |||
You can query information from a running game server using UDP/IP packets. This document describes the packet formats and protocol to access this data. | You can query information from a running game server using UDP/IP packets. This document describes the packet formats and protocol to access this data. | ||
= Data Types = | == Data Types == | ||
All server queries consist of five basic types of data packed together into a data stream. All types are little endian, which is the default on most languages on x86 CPUs. Java users should use ByteBuffer to convert. | All server queries consist of five basic types of data packed together into a data stream. All types are little endian, which is the default on most languages on x86 CPUs. Java users should use ByteBuffer to convert. | ||
Line 25: | Line 23: | ||
|} | |} | ||
= Protocol = | == Protocol == | ||
Steam uses a packet size of 1400 bytes + IP/UDP headers. If a request or response needs more packets for the data it starts the packets with an additional header. | Steam uses a packet size of up to 1400 bytes + IP/UDP headers. If a request or response needs more packets for the data it starts the packets with an additional header. | ||
== Simple Response Format == | 2023-07-10: Rust has been observed breaking this, sending packets up to the maximum IP size (64KB). | ||
=== Simple Response Format === | |||
{| class=standard-table | {| class=standard-table | ||
Line 39: | Line 39: | ||
|} | |} | ||
== Multi-packet Response Format == | === Multi-packet Response Format === | ||
===[[Goldsource]] Server=== | ====[[Goldsource]] Server==== | ||
{| class=standard-table | {| class=standard-table | ||
Line 55: | Line 55: | ||
|} | |} | ||
===[[Source]] Server=== | ====[[Source]] Server==== | ||
{| class=standard-table | {| class=standard-table | ||
Line 62: | Line 62: | ||
| Header || [[long]] || Always equal to -2 (0xFFFFFFFE). Means the packet is split. | | Header || [[long]] || Always equal to -2 (0xFFFFFFFE). Means the packet is split. | ||
|- | |- | ||
| ID || [[long]] || Same as the [[Goldsource]] server meaning. However, if the {{wiki|most significant bit}} is 1, then the response was compressed with bzip2 before being cut and sent. Refer to compression procedure below. | | ID || [[long]] || Same as the [[Goldsource]] server meaning. However, if the {{wiki|most significant bit}} is 1, then the response was compressed with [[bzip2]] before being cut and sent. Refer to compression procedure below. | ||
|- | |- | ||
| Total || [[byte]] || The total number of packets in the response. | | Total || [[byte]] || The total number of packets in the response. | ||
Line 68: | Line 68: | ||
| Number || [[byte]] || The number of the packet. Starts at 0. | | Number || [[byte]] || The number of the packet. Starts at 0. | ||
|- | |- | ||
| Size || [[short]] || ([[Orange Box]] Engine and above only.) Maximum size of packet before packet switching occurs. The default value is 1248 bytes (0x04E0), but the server administrator can decrease this. For older engine versions: the maximum and minimum size of the packet was unchangeable. AppIDs which are known not to contain this field: 215, 17550, 17700. | | Size || [[short]] || ([[Orange Box]] Engine and above only.) Maximum size of packet before packet switching occurs. The default value is 1248 bytes (0x04E0), but the server administrator can decrease this. For older engine versions: the maximum and minimum size of the packet was unchangeable. AppIDs which are known not to contain this field: 215, 17550, 17700, and 240 when protocol = 7. | ||
|- | |- | ||
| colspan="3" | This is only present in the first packet of the response and only if the response is being compressed. | | colspan="3" | This is only present in the first packet of the response and only if the response is being compressed. | ||
Line 86: | Line 86: | ||
So by reading the first 4 bytes you can decide whether the data is split (-2) or in one packet (-1). | So by reading the first 4 bytes you can decide whether the data is split (-2) or in one packet (-1). | ||
= Requests = | Note: Some titles when using the split packet method have been observed erroneously nesting the single message header inside the split payload. | ||
== Requests == | |||
The server responds to 5 queries: | The server responds to 5 queries: | ||
Line 103: | Line 105: | ||
Queries should be sent in UDP packets to the listen port of the server. | Queries should be sent in UDP packets to the listen port of the server. | ||
== A2S_INFO == | == Challenge Mechanism == | ||
Servers may respond with the data immediately. However, since this reply is larger than the request, it makes the server vulnerable to a reflection amplification attack. | |||
Instead, the server may reply with a challenge to the client using S2C_CHALLENGE ('A' or 0x41). In that case, the client should repeat the request by appending the challenge number. | |||
This change was introduced in December 2020 to address the reflection attack vulnerability, and all clients are encouraged to support the new protocol. See [https://steamcommunity.com/discussions/forum/14/2974028351344359625/ this post] for more info. | |||
Previously the structure of this document made it seem that only A2S_INFO messages would be responded with in this manner, however ANY of the queries made MAY result in a `S2C_CHALLENGE` response if either the challenge was omitted, is wrong, or has expired. | |||
=== A2S_INFO === | |||
Retrieves information about the server including, but not limited to: its name, the map currently being played, and the number of players. | Retrieves information about the server including, but not limited to: its name, the map currently being played, and the number of players. | ||
=== Request Format === | l4d2 server 2.2.1.3 update:some server will send challenge number ,it caused hlsw cant get server info; | ||
==== Request Format ==== | |||
{| class=standard-table | {| class=standard-table | ||
Line 114: | Line 125: | ||
| Header || [[byte]] || 'T' (0x54) | | Header || [[byte]] || 'T' (0x54) | ||
|- | |- | ||
| Payload || [[string]] || "Source Engine Query" | | Payload || [[string]] || "Source Engine Query\0" | ||
|- | |||
| Challenge || [[long]] || 4-byte challenge (sometimes -- see below) | |||
|} | |} | ||
Line 120: | Line 133: | ||
| | | | ||
FF FF FF FF 54 53 6F 75 72 63 65 20 45 6E 67 69 ÿÿÿÿTSource Engi | FF FF FF FF 54 53 6F 75 72 63 65 20 45 6E 67 69 ÿÿÿÿTSource Engi | ||
6E 65 20 51 75 65 72 79 00 ne Query | 6E 65 20 51 75 65 72 79 00 ne Query. | ||
|} | |} | ||
Example for challenge number: | |||
Server response: | |||
{|style="background:transparent;" | |||
| | |||
FF FF FF FF 41 0A 08 5E EA | |||
{| style=" | |||
|} | |} | ||
You need send : | |||
| | {|style="background:transparent;" | ||
| | | | ||
FF FF FF FF 54 53 6F 75 72 63 65 20 45 6E 67 69 6E 65 20 51 75 65 72 79 00 0A 08 5E EA | |||
|} | |} | ||
NOTE: In the future, additional data may be appended to the request! Do not assume that if a request has extra data, that it is a bogus packet! | |||
NOTE:changed 2021-6-19 13:05:43 :when l4d2 server received some packet from same ip address,it may deined replay | |||
NOTE:some older titles have been observed sending the GoldSource INFO packet AND the newer INFO packet in reply to this. | |||
==== | ==== Response Format ==== | ||
{{Note|Both [[SiN 1 Multiplayer]] and [[Rag Doll Kung Fu]] utilise this response protocol.}} | {{Note|Both [[SiN 1 Multiplayer]] and [[Rag Doll Kung Fu]] utilise this response protocol.}} | ||
Line 208: | Line 163: | ||
! Data !! Type !! Comment | ! Data !! Type !! Comment | ||
|- | |- | ||
| Header || [[byte]] || Always equal to 'I' (0x49 | | Header || [[byte]] || Always equal to 'I' (0x49) | ||
|- | |- | ||
| Protocol || [[byte]] || Protocol version used by the server. | | Protocol || [[byte]] || Protocol version used by the server. | ||
Line 228: | Line 183: | ||
| Bots || [[byte]] || Number of bots on the server. | | Bots || [[byte]] || Number of bots on the server. | ||
|- | |- | ||
| Server type || [[byte]] || Indicates the type of server: <ul><li>'d' for a dedicated server</li><li>'l' for a non-dedicated server</li><li>'p' for a [[SourceTV]] | | Server type || [[byte]] || Indicates the type of server: <ul><li>'d' for a dedicated server</li><li>'l' for a non-dedicated server</li><li>'p' for a [[SourceTV]] relay (proxy)</li></ul> | ||
|- | |- | ||
| Environment || [[byte]] || Indicates the operating system of the server: <ul><li>'l' for Linux</li><li>'w' for Windows</li><li>'m' or 'o' for Mac (the code changed after L4D1)</li></ul> | | Environment || [[byte]] || Indicates the operating system of the server: <ul><li>'l' for Linux</li><li>'w' for Windows</li><li>'m' or 'o' for Mac (the code changed after L4D1)</li></ul> | ||
Line 293: | Line 248: | ||
<br> | <br> | ||
Example response for [[Counter Strike: Source]]: | Example response for [[Counter-Strike: Source]]: | ||
{|style="background:transparent;" | {|style="background:transparent;" | ||
| | | | ||
Line 333: | Line 288: | ||
|} | |} | ||
== A2S_PLAYER == | |||
===== Obsolete [[GoldSource]] Response ===== | |||
GoldSource servers reply using the same response as Source servers. Older and pre-Steam servers still reply with the response format below. GoldSource can be distinguished from Source via AppIDs. | |||
{| class=standard-table | |||
! Data !! Type !! Comment | |||
|- | |||
| Header || [[byte]] || Always equal to 'm' (0x6D) | |||
|- | |||
| Address || [[string]] || IP address and port of the server. | |||
|- | |||
| Name || [[string]] || Name of the server. | |||
|- | |||
| Map || [[string]] || Map the server has currently loaded. | |||
|- | |||
| Folder || [[string]] || Name of the folder containing the game files. | |||
|- | |||
| Game || [[string]] || Full name of the game. | |||
|- | |||
| Players || [[byte]] || Number of players on the server. | |||
|- | |||
| Max. Players || [[byte]] || Maximum number of players the server reports it can hold. | |||
|- | |||
| Protocol || [[byte]] || Protocol version used by the server. | |||
|- | |||
| Server type || [[byte]] || Indicates the type of server: <ul><li>'D' for dedicated server</li><li>'L' for non-dedicated server</li><li>'P' for a HLTV server</li></ul> | |||
|- | |||
| Environment || [[byte]] || Indicates the operating system of the server: <ul><li>'L' for Linux</li><li>'W' for Windows</li></ul> | |||
|- | |||
| Visibility || [[byte]] || Indicates whether the server requires a password: <ul><li>0 for public</li><li>1 for private</li></ul> | |||
|- | |||
| Mod || [[byte]] || Indicates whether the game is a mod: <ul><li>0 for [[Half-Life]]</li><li>1 for Half-Life mod</li></ul> | |||
|- | |||
| colspan="3" | These fields are only present in the response if "Mod" is 1: | |||
{| style="margin:10px" | |||
! Data || Type || Comment | |||
|- | |||
| Link || [[string]] || URL to mod website. | |||
|- | |||
| Download Link || [[string]] || URL to download the mod. | |||
|- | |||
| NULL || [[byte]] || NULL byte (0x00) | |||
|- | |||
| Version || [[long]] || Version of mod installed on server. | |||
|- | |||
| Size || [[long]] || Space (in bytes) the mod takes up. | |||
|- | |||
| Type || [[byte]] || Indicates the type of mod: <ul><li>0 for single '''and''' multiplayer mod</li><li>1 for multiplayer '''only''' mod</li></ul> | |||
|- | |||
| DLL || [[byte]] || Indicates whether mod uses its own DLL: <ul><li>0 if it uses the [[Half-Life]] DLL</li><li>1 if it uses its own DLL</li></ul> | |||
|} | |||
|- | |||
| [[VAC]] || [[byte]] || Specifies whether the server uses VAC: <ul><li>0 for unsecured</li><li>1 for secured</li></ul> | |||
|- | |||
| Bots || [[byte]] || Number of bots on the server. | |||
|} | |||
{{Note|HLTV servers may respond with a late request that is either incomplete or incorrect if the number of slots is 255.}} | |||
<br> | |||
Example response: | |||
{| style="background:transparent;" | |||
| | |||
FF FF FF FF 6D 37 37 2E 31 31 31 2E 31 39 34 2E ÿÿÿÿm77.111.194. | |||
31 31 30 3A 32 37 30 31 35 00 46 52 20 2D 20 56 110:27015.FR - V | |||
65 72 79 47 61 6D 65 73 2E 6E 65 74 20 2D 20 44 eryGames.net - D | |||
65 61 74 6D 61 74 63 68 20 2D 20 6F 6E 6C 79 20 eatmatch - only | |||
73 75 72 66 5F 73 6B 69 20 2D 20 6E 67 52 00 73 surf_ski - ngR.s | |||
75 72 66 5F 73 6B 69 00 63 73 74 72 69 6B 65 00 urf_ski.cstrike. | |||
43 6F 75 6E 74 65 72 2D 53 74 72 69 6B 65 00 0C Counter-Strike.. | |||
12 2F 64 6C 00 01 77 77 77 2E 63 6F 75 6E 74 65 ./dl..www.counte | |||
72 2D 73 74 72 69 6B 65 2E 6E 65 74 00 00 00 01 r-strike.net.... | |||
00 00 00 00 9E F7 0A 00 01 01 00 ....ž÷..... | |||
|} | |||
=== A2S_PLAYER === | |||
This query retrieves information about the players currently on the server. It needs an initial step to acquire a challenge number. | This query retrieves information about the players currently on the server. It needs an initial step to acquire a challenge number. | ||
Line 339: | Line 371: | ||
{{Note|[[SourceTV]] does not respond to this request.}} | {{Note|[[SourceTV]] does not respond to this request.}} | ||
=== Request Format === | ==== Request Format ==== | ||
{| class=standard-table | {| class=standard-table | ||
Line 346: | Line 378: | ||
| Header || [[byte]] || 'U' (0x55) | | Header || [[byte]] || 'U' (0x55) | ||
|- | |- | ||
| Challenge || [[ | | Challenge || [[int]] || Challenge number, or -1 (0xFFFFFFFF) to receive a challenge number. | ||
|} | |||
Challenge response format: | |||
{| class=standard-table | |||
! Data || Type || Value | |||
|- | |||
| Header || [[byte]] || 'A' (0x41) | |||
|- | |||
| Challenge || [[int]] || Challenge number. | |||
|} | |} | ||
Line 358: | Line 399: | ||
{| style="background:transparent;" | {| style="background:transparent;" | ||
| | | | ||
FF FF FF FF 41 4B A1 D5 22 | FF FF FF FF 41 4B A1 D5 22 ÿÿÿÿAÿÿÿÿ" | ||
|} | |} | ||
Line 367: | Line 408: | ||
|} | |} | ||
=== Response Format === | ==== Response Format ==== | ||
{| class=standard-table | {| class=standard-table | ||
! Data !! Type !! Comment | ! Data !! Type !! Comment | ||
|- | |- | ||
| Header || [[byte]] || Always equal to 'D' (0x44 | | Header || [[byte]] || Always equal to 'D' (0x44) | ||
|- | |- | ||
| Players || [[byte]] || Number of players whose information was gathered. | | Players || [[byte]] || Number of players whose information was gathered. | ||
Line 388: | Line 429: | ||
| Duration || [[float]] || Time (in seconds) player has been connected to the server. | | Duration || [[float]] || Time (in seconds) player has been connected to the server. | ||
|} | |} | ||
|} | |||
[[The Ship]] additional player info (comes after the basic information in the packet): | |||
{| class=standard-table | |||
! Data || Type || Comment | |||
|- | |||
| Deaths || [[long]] || Player's deaths | |||
|- | |||
| Money || [[long]] || Player's money | |||
|} | |} | ||
{{Note|When a player is trying to connect to a server, they are recorded in the number of players. However, they will not be in the list of player information chunks.}} | {{Note|When a player is trying to connect to a server, they are recorded in the number of players. However, they will not be in the list of player information chunks.}} | ||
{{Warning|CS:GO Server by default returns only max players and server uptime. You have to change server cvar "host_players_show" in server.cfg to value "2" if you want to revert to old format with players list.}} | |||
<br> | <br> | ||
Line 403: | Line 457: | ||
|} | |} | ||
== A2S_RULES == | [[The Ship]] response: | ||
{| style="background:transparent;" | |||
| | |||
FF FF FF FF 44 13 00 53 68 69 70 6D 61 74 65 31 ▒▒▒▒D..Shipmate1 | |||
00 00 00 00 00 00 00 80 BF 01 53 68 69 70 6D 61 .......▒▒.Shipma | |||
74 65 32 00 00 00 00 00 00 00 80 BF 02 53 68 69 te2.......▒▒.Shi | |||
70 6D 61 74 65 33 00 00 00 00 00 00 00 80 BF 03 pmate3.......▒▒. | |||
53 68 69 70 6D 61 74 65 34 00 00 00 00 00 00 00 Shipmate4....... | |||
80 BF 04 53 68 69 70 6D 61 74 65 35 00 00 00 00 ▒▒.Shipmate5.... | |||
00 00 00 80 BF 07 28 31 29 4C 61 6E 64 4C 75 62 ...▒▒.(1)LandLub | |||
62 65 72 00 00 00 00 00 D3 8E 68 45 00 00 00 00 ber.....ӎhE.... | |||
C4 09 00 00 00 00 00 00 C4 09 00 00 00 00 00 00 ▒.......▒....... | |||
C4 09 00 00 00 00 00 00 C4 09 00 00 00 00 00 00 ▒.......▒....... | |||
C4 09 00 00 00 00 00 00 C4 09 00 00 ▒.......▒... | |||
|} | |||
=== A2S_RULES === | |||
Returns the server rules, or configuration variables in name/value pairs. This query requires an initial challenge step. | Returns the server rules, or configuration variables in name/value pairs. This query requires an initial challenge step. | ||
=== Request Format === | The [[Console variable]]s included are the ones marked with [[FCVAR_NOTIFY]] as well as any additional ones listed in the server configuration. | ||
==== Request Format ==== | |||
{| class=standard-table | {| class=standard-table | ||
Line 414: | Line 486: | ||
| Header || [[byte]] || 'V' (0x56) | | Header || [[byte]] || 'V' (0x56) | ||
|- | |- | ||
| Challenge || [[long]] || Challenge number | | Challenge || [[long]] || Challenge number, or -1 (0xFFFFFFFF) to receive a challenge number. | ||
|} | |||
Challenge response format: | |||
{| class=standard-table | |||
! Data || Type || Value | |||
|- | |||
| Header || [[byte]] || 'A' (0x41) | |||
|- | |||
| Challenge || [[long]] || Challenge number. | |||
|} | |||
Example challenge request: | |||
{| style="background:transparent;" | |||
| | |||
FF FF FF FF 56 FF FF FF FF ÿÿÿÿVÿÿÿÿ" | |||
|} | |} | ||
Line 423: | Line 510: | ||
|} | |} | ||
{{Warning| | {{Warning|CS:GO Rules reply is broken since update CSGO 1.32.3.0 (Feb 21, 2014). Before the update rules got truncated when exceeding MTU, after the update rules reply is not sent at all. You can also see a console message: [NET] Cannot send connectionless packet to xxx.xxx.xxx.xxx:xxxxx '0x45' exceeding MTU (2644)}} | ||
Final request that includes the received challenge number: | Final request that includes the received challenge number: | ||
Line 431: | Line 518: | ||
|} | |} | ||
=== Response Format === | ==== Response Format ==== | ||
{{Note|Responses to this query are usually multi-packeted.}} | {{Note|Responses to this query are usually multi-packeted.}} | ||
Line 438: | Line 525: | ||
! Data !! Type !! Comment | ! Data !! Type !! Comment | ||
|- | |- | ||
| Header || [[byte]] || Always equal to 'E' (0x45 | | Header || [[byte]] || Always equal to 'E' (0x45) | ||
|- | |- | ||
| Rules || [[short]] || Number of rules in the response. | | Rules || [[short]] || Number of rules in the response. | ||
Line 452: | Line 539: | ||
|} | |} | ||
=== A2A_PING === | |||
= | |||
Ping the server to see if it exists, this can be used to calculate the latency to the server. | Ping the server to see if it exists, this can be used to calculate the latency to the server. | ||
{{Warning|According to Valve (see [[Talk:Server_queries#A2A_PING_no_longer_supported.3F|Talk Page]]), A2A_PING is no longer supported on Counter Strike: Source and Team Fortress 2 servers, and is considered a deprecated feature.}} | {{Warning|According to Valve (see [[Talk:Server_queries#A2A_PING_no_longer_supported.3F|Talk Page]]), A2A_PING is no longer supported on Counter-Strike: Source and Team Fortress 2 servers, and is considered a deprecated feature.}} | ||
=== Request Format === | ==== Request Format ==== | ||
{| class=standard-table | {| class=standard-table | ||
Line 586: | Line 558: | ||
|} | |} | ||
=== Response Format === | ==== Response Format ==== | ||
==== [[Goldsource]] Server ==== | ===== [[Goldsource]] Server ===== | ||
{| class=standard-table | {| class=standard-table | ||
Line 603: | Line 575: | ||
|} | |} | ||
==== [[Source]] Server ==== | ===== [[Source]] Server ===== | ||
{| class=standard-table | {| class=standard-table | ||
Line 610: | Line 582: | ||
| Heading || [[byte]] || 'j' (0x6A) | | Heading || [[byte]] || 'j' (0x6A) | ||
|- | |- | ||
| Payload || [[string]] || '00000000000000' | | Payload || [[string]] || '00000000000000.' | ||
|} | |} | ||
Line 619: | Line 591: | ||
|} | |} | ||
== A2S_SERVERQUERY_GETCHALLENGE == | === A2S_SERVERQUERY_GETCHALLENGE === | ||
A2S_PLAYER and A2S_RULES queries both require a challenge number. Formerly, this number could be obtained via an A2S_SERVERQUERY_GETCHALLENGE request. In newer games it no longer works. Instead, issue A2S_PLAYER or A2S_RULES queries with an initial challenge of <code>-1 (0xFFFFFFFF)</code> to receive a usable challenge number. | A2S_PLAYER and A2S_RULES queries both require a challenge number. Formerly, this number could be obtained via an A2S_SERVERQUERY_GETCHALLENGE request. In newer games it no longer works. Instead, issue A2S_PLAYER or A2S_RULES queries with an initial challenge of <code>-1 (0xFFFFFFFF)</code> to receive a usable challenge number. | ||
Line 625: | Line 597: | ||
On some engines (confirmed AppIDs: 17510, 17530, 17740, 17550, 17700) it can be used. The format is: | On some engines (confirmed AppIDs: 17510, 17530, 17740, 17550, 17700) it can be used. The format is: | ||
=== Request Format === | ==== Request Format ==== | ||
{| class=standard-table | {| class=standard-table | ||
Line 638: | Line 610: | ||
|} | |} | ||
=== Response Format === | ==== Response Format ==== | ||
{| class=standard-table | {| class=standard-table | ||
Line 655: | Line 627: | ||
|} | |} | ||
= Implementations = | == Implementations == | ||
* [https://www.npmjs.com/package/@fabricio-191/valve-server-query @fabricio-191/valve-server-query] Server, Master Server and RCON protocols implementation for Node.js | |||
* [https://www.npmjs.com/package/steam-server-query Steam Server Query] Javascript (Node.js) module which implements the Master Server Query Protocol and Game Server Queries | |||
* [https://github.com/ribasco/async-gamequery-lib Asynchronous Game Query Library] A Java 8 based Asynchronous Game Query Library powered by Netty | |||
* [[Source Server Query Library]] C library | * [[Source Server Query Library]] C library | ||
* [https://github.com/BinaryAlien/libssq libssq] C library | |||
* [http://www.barkerjr.net/gameserver.html GameServer] Java library | * [http://www.barkerjr.net/gameserver.html GameServer] Java library | ||
* [http://queried.sourceforge.net QueryEd] Java library | * [http://queried.sourceforge.net QueryEd] Java library | ||
* [[Steam Condenser]] Java, PHP, and Ruby library | * [[Steam Condenser]] Java, PHP, and Ruby library | ||
* [http://search.cpan.org/~masanorih/Net-SRCDS-Queries | * [https://github.com/sonicsnes/node-gamedig GameDig] Javascript (Node.JS) module | ||
* [ | * [http://search.cpan.org/~masanorih/ Net-SRCDS-Queries] Perl module | ||
* [https://github.com/linKhehe/a2squery a2squery] Python library | |||
* [https://github.com/TronPaul/srcdspy SRCDSpy] Python library | |||
* [http://github.com/frostschutz/SourceLib SourceLib] Python library | * [http://github.com/frostschutz/SourceLib SourceLib] Python library | ||
* [http:// | * [http://github.com/Holiverh/python-valve python-valve] Python library | ||
* [https://github.com/big-oh404/src_l4d2_query Left4Query] Python library | |||
* [https://pypi.python.org/pypi/valve-range-query/1.0.4 valve-range-query] Python Library for IP range query | |||
* [https://github.com/Yepoleb/python-a2s python-a2s] Python library (supports async) | |||
* [https://github.com/Yepoleb/dayzquery dayzquery] Add-on for [https://github.com/Yepoleb/python-a2s python-a2s] library which parses DayZ-specific binary data in A2S_RULES response | |||
* [https://github.com/atomy/sourcestats/ SourceStats] Source Server Statistics | * [https://github.com/atomy/sourcestats/ SourceStats] Source Server Statistics | ||
* [https://github.com/xPaw/PHP-Source-Query-Class PHP Source Query] PHP library | * [https://github.com/xPaw/PHP-Source-Query-Class PHP Source Query] PHP library | ||
* [https://github.com/cemahseri/SteamQuery.NET SteamQuery.NET] .NET/C# Wrapper (Built in .NET 9/.NET Standard 2.0, by cemahseri. Supports Source, GoldSource, and obsolete GoldSource protocols.) | |||
* [http://querymaster.codeplex.com/ QueryMaster] C# library | |||
* [https://github.com/armageddonapps/QueryMaster QueryMaster] C# library (remaster for .NET Standart 2.0) | |||
* [https://github.com/Florian2406/Okolni-Source-Query Okolni-Source-Query] C# library (.NET Standard 2.0, Now Support l4d2 2213) | |||
* [https://github.com/Crytilis/A2S A2S] C# library utilizing NET5. (Currently supports A2S_Info and A2S_Player) | |||
* [http://www.codeproject.com/KB/game/Game_Server_Query_DLL.aspx aQuery] VB.NET library | |||
* [https://github.com/rumblefrog/go-a2s/ go-a2s] Golang library | |||
* [https://github.com/rumblefrog/a2s-rs/ a2s-rs] Rust library | |||
* [https://github.com/hundunzhidian/RconA2sAPi Rcon and A2s WebApi]中文的WebApi协议库,基于Spring boot,仅支持A2S_INFO、A2S_PLAYER,Now Support l4d2 2213 | |||
* [https://github.com/hjorslev/SteamPS SteamPS] Module that utilizes PowerShell as a wrapper for SteamCMD. Uses server queries in the command [https://github.com/hjorslev/SteamPS/blob/master/SteamPS/Public/Get-SteamServerInfo.ps1 Get-SteamServerInfo] | |||
* [https://github.com/hundunzhidian/valvemiraibot Mirai Tencent QQ robot]基于mriaiBot适配了a2s rcon的腾讯qq机器人,仅支持A2S_INFO、A2S_PLAYER,Rcon,Now Support l4d2 2213 | |||
* [https://github.com/gamedig/rust-gamedig/ Rust-GameDig] Rust library that supports the entirety of the protocol (also has the obsolete GoldSrc response). | |||
* [https://github.com/gnif/SteamQueryProxy SteamQueryProxy] Extremely high performance protocol proxy written in pure C for Linux (Can be used to mitigate VSE DoS attacks, supports Source & GoldSource). | |||
* [https://github.com/Svarrogh1337/Steam2Go Steam2Go] Golang library. Includes support for A2S, rcon and various WebAPI services. | |||
* [https://github.com/hugmouse/objc-sourcequery ObjC Source Query] ObjC implementation of the Source Engine Query Protocol + Valve Master Server queries. | |||
= See | == See also == | ||
* [[Master Server Query Protocol]] | * [[Master Server Query Protocol]] | ||
* [[Source RCON Protocol]] | * [[Source RCON Protocol]] | ||
[[Category:Networking]] | [[Category:Networking]] | ||
[[Category:Technical]] | [[Category:Technical]] | ||
[[Category:Dedicated Server]] |
Latest revision as of 00:16, 13 August 2025
You can query information from a running game server using UDP/IP packets. This document describes the packet formats and protocol to access this data.
Data Types
All server queries consist of five basic types of data packed together into a data stream. All types are little endian, which is the default on most languages on x86 CPUs. Java users should use ByteBuffer to convert.
Name | Description |
---|---|
byte | 8 bit character or unsigned integer |
short | 16 bit signed integer |
long | 32 bit signed integer |
float | 32 bit floating point |
long long | 64 bit unsigned integer |
string | variable-length byte field, encoded in UTF-8, terminated by 0x00 |
Protocol
Steam uses a packet size of up to 1400 bytes + IP/UDP headers. If a request or response needs more packets for the data it starts the packets with an additional header.
2023-07-10: Rust has been observed breaking this, sending packets up to the maximum IP size (64KB).
Simple Response Format
Data | Type | Comment |
---|---|---|
Header | long | Always equal to -1 (0xFFFFFFFF). Means it isn't split. |
Payload |
Multi-packet Response Format
Goldsource Server
Data | Type | Comment |
---|---|---|
Header | long | Always equal to -2 (0xFFFFFFFE). Means the packet is split. |
ID | long | Unique number assigned by server per answer. |
Packet number | byte | Upper 4 bits represent the number of the current packet (starting at 0) and bottom 4 bits represent the total number of packets (2 to 15). |
Payload |
Source Server
Data | Type | Comment | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Header | long | Always equal to -2 (0xFFFFFFFE). Means the packet is split. | |||||||||
ID | long | Same as the Goldsource server meaning. However, if the ![]() | |||||||||
Total | byte | The total number of packets in the response. | |||||||||
Number | byte | The number of the packet. Starts at 0. | |||||||||
Size | short | (Orange Box Engine and above only.) Maximum size of packet before packet switching occurs. The default value is 1248 bytes (0x04E0), but the server administrator can decrease this. For older engine versions: the maximum and minimum size of the packet was unchangeable. AppIDs which are known not to contain this field: 215, 17550, 17700, and 240 when protocol = 7. | |||||||||
This is only present in the first packet of the response and only if the response is being compressed.
To uncompress this response: collect and assemble all the payloads of the received packets, then pass that into a function like BZ2_bzBuffToBuffDecompress() in C, bzdecompress() in PHP, or bz2.decompress() in Python. Compression appears to have been phased out in newer Source games, but is still present in ~2006-era engines. | |||||||||||
Payload |
Because UDP packets can arrive in different order or delayed, every packet should be verified by its "ID" and "Number"! Every request or response with or without this header is continued with an integer -1 (0xFFFFFFFF) and the user data. So by reading the first 4 bytes you can decide whether the data is split (-2) or in one packet (-1).
Note: Some titles when using the split packet method have been observed erroneously nesting the single message header inside the split payload.
Requests
The server responds to 5 queries:
A2S_INFO
- Basic information about the server.
A2S_PLAYER
- Details about each player on the server.
A2S_RULES
- The rules the server is using.
A2A_PING
- Ping the server. (DEPRECATED)
A2S_SERVERQUERY_GETCHALLENGE
- Returns a challenge number for use in the player and rules query. (DEPRECATED)
Queries should be sent in UDP packets to the listen port of the server.
Challenge Mechanism
Servers may respond with the data immediately. However, since this reply is larger than the request, it makes the server vulnerable to a reflection amplification attack. Instead, the server may reply with a challenge to the client using S2C_CHALLENGE ('A' or 0x41). In that case, the client should repeat the request by appending the challenge number. This change was introduced in December 2020 to address the reflection attack vulnerability, and all clients are encouraged to support the new protocol. See this post for more info.
Previously the structure of this document made it seem that only A2S_INFO messages would be responded with in this manner, however ANY of the queries made MAY result in a `S2C_CHALLENGE` response if either the challenge was omitted, is wrong, or has expired.
A2S_INFO
Retrieves information about the server including, but not limited to: its name, the map currently being played, and the number of players.
l4d2 server 2.2.1.3 update:some server will send challenge number ,it caused hlsw cant get server info;
Request Format
Data | Type | Value |
---|---|---|
Header | byte | 'T' (0x54) |
Payload | string | "Source Engine Query\0" |
Challenge | long | 4-byte challenge (sometimes -- see below) |
FF FF FF FF 54 53 6F 75 72 63 65 20 45 6E 67 69 ÿÿÿÿTSource Engi 6E 65 20 51 75 65 72 79 00 ne Query. |
Example for challenge number:
Server response:
FF FF FF FF 41 0A 08 5E EA |
You need send :
FF FF FF FF 54 53 6F 75 72 63 65 20 45 6E 67 69 6E 65 20 51 75 65 72 79 00 0A 08 5E EA |
NOTE: In the future, additional data may be appended to the request! Do not assume that if a request has extra data, that it is a bogus packet!
NOTE:changed 2021-6-19 13:05:43 :when l4d2 server received some packet from same ip address,it may deined replay
NOTE:some older titles have been observed sending the GoldSource INFO packet AND the newer INFO packet in reply to this.
Response Format

Data | Type | Comment | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Header | byte | Always equal to 'I' (0x49) | ||||||||||||
Protocol | byte | Protocol version used by the server. | ||||||||||||
Name | string | Name of the server. | ||||||||||||
Map | string | Map the server has currently loaded. | ||||||||||||
Folder | string | Name of the folder containing the game files. | ||||||||||||
Game | string | Full name of the game. | ||||||||||||
ID | short | Steam Application ID of game. | ||||||||||||
Players | byte | Number of players on the server. | ||||||||||||
Max. Players | byte | Maximum number of players the server reports it can hold. | ||||||||||||
Bots | byte | Number of bots on the server. | ||||||||||||
Server type | byte | Indicates the type of server:
| ||||||||||||
Environment | byte | Indicates the operating system of the server:
| ||||||||||||
Visibility | byte | Indicates whether the server requires a password:
| ||||||||||||
VAC | byte | Specifies whether the server uses VAC:
| ||||||||||||
These fields only exist in a response if the server is running The Ship:
| ||||||||||||||
Version | string | Version of the game installed on the server. | ||||||||||||
Extra Data Flag (EDF) | byte | If present, this specifies which additional data fields will be included. | ||||||||||||
Only if if ( EDF & 0x80 ) proves true:
| ||||||||||||||
Only if if ( EDF & 0x10 ) proves true:
| ||||||||||||||
Only if if ( EDF & 0x40 ) proves true:
| ||||||||||||||
Only if if ( EDF & 0x20 ) proves true:
| ||||||||||||||
Only if if ( EDF & 0x01 ) proves true:
|

Example response for Counter-Strike: Source:
FF FF FF FF 49 02 67 61 6D 65 32 78 73 2E 63 6F ÿÿÿÿI.game2xs.co 6D 20 43 6F 75 6E 74 65 72 2D 53 74 72 69 6B 65 m Counter-Strike 20 53 6F 75 72 63 65 20 23 31 00 64 65 5F 64 75 Source #1.de_du 73 74 00 63 73 74 72 69 6B 65 00 43 6F 75 6E 74 st.cstrike.Count 65 72 2D 53 74 72 69 6B 65 3A 20 53 6F 75 72 63 er-Strike: Sourc 65 00 F0 00 05 10 04 64 6C 00 00 31 2E 30 2E 30 e......dl..1.0.0 2E 32 32 00 .22. |
Example response for The Ship:
FF FF FF FF 49 07 53 68 69 70 20 53 65 72 76 65 ÿÿÿÿI.Ship Serve 72 00 62 61 74 61 76 69 65 72 00 73 68 69 70 00 r.batavier.ship. 54 68 65 20 53 68 69 70 00 60 09 01 05 00 6C 77 The Ship.`....lw 00 00 01 03 03 31 2E 30 2E 30 2E 34 00 .....1.0.0.4. |
Example response for SiN 1 Multiplayer:
FF FF FF FF 49 2F 53 65 6E 73 65 6D 61 6E 6E 20 ÿÿÿÿI/Sensemann 53 69 4E 20 44 4D 00 70 61 72 61 64 6F 78 00 53 SiN DM.paradox.S 69 4E 20 31 00 53 69 4E 20 31 00 1D 05 00 10 00 iN 1.SiN 1...... 6C 77 00 00 31 2E 30 2E 30 2E 30 00 lw..1.0.0.0. |
Example response for Rag Doll Kung Fu:
FF FF FF FF 49 FC 54 68 65 20 44 75 64 65 27 73 ÿÿÿÿIüThe Dude's 20 64 6F 6A 6F 00 53 6F 63 63 65 72 00 52 44 4B dojo.Soccer.RDK 46 53 6F 63 63 65 72 00 52 61 67 44 6F 6C 6C 4B FSoccer.RagDollK 75 6E 67 46 75 3A 20 53 6F 63 63 65 72 00 EA 03 ungFu: Soccer.ê. 01 04 00 00 77 00 00 32 2E 33 2E 30 2E 30 00 ....w..2.3.0.0. |
Obsolete GoldSource Response
GoldSource servers reply using the same response as Source servers. Older and pre-Steam servers still reply with the response format below. GoldSource can be distinguished from Source via AppIDs.
Data | Type | Comment | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Header | byte | Always equal to 'm' (0x6D) | ||||||||||||||||||||||||
Address | string | IP address and port of the server. | ||||||||||||||||||||||||
Name | string | Name of the server. | ||||||||||||||||||||||||
Map | string | Map the server has currently loaded. | ||||||||||||||||||||||||
Folder | string | Name of the folder containing the game files. | ||||||||||||||||||||||||
Game | string | Full name of the game. | ||||||||||||||||||||||||
Players | byte | Number of players on the server. | ||||||||||||||||||||||||
Max. Players | byte | Maximum number of players the server reports it can hold. | ||||||||||||||||||||||||
Protocol | byte | Protocol version used by the server. | ||||||||||||||||||||||||
Server type | byte | Indicates the type of server:
| ||||||||||||||||||||||||
Environment | byte | Indicates the operating system of the server:
| ||||||||||||||||||||||||
Visibility | byte | Indicates whether the server requires a password:
| ||||||||||||||||||||||||
Mod | byte | Indicates whether the game is a mod:
| ||||||||||||||||||||||||
These fields are only present in the response if "Mod" is 1:
| ||||||||||||||||||||||||||
VAC | byte | Specifies whether the server uses VAC:
| ||||||||||||||||||||||||
Bots | byte | Number of bots on the server. |

Example response:
FF FF FF FF 6D 37 37 2E 31 31 31 2E 31 39 34 2E ÿÿÿÿm77.111.194. 31 31 30 3A 32 37 30 31 35 00 46 52 20 2D 20 56 110:27015.FR - V 65 72 79 47 61 6D 65 73 2E 6E 65 74 20 2D 20 44 eryGames.net - D 65 61 74 6D 61 74 63 68 20 2D 20 6F 6E 6C 79 20 eatmatch - only 73 75 72 66 5F 73 6B 69 20 2D 20 6E 67 52 00 73 surf_ski - ngR.s 75 72 66 5F 73 6B 69 00 63 73 74 72 69 6B 65 00 urf_ski.cstrike. 43 6F 75 6E 74 65 72 2D 53 74 72 69 6B 65 00 0C Counter-Strike.. 12 2F 64 6C 00 01 77 77 77 2E 63 6F 75 6E 74 65 ./dl..www.counte 72 2D 73 74 72 69 6B 65 2E 6E 65 74 00 00 00 01 r-strike.net.... 00 00 00 00 9E F7 0A 00 01 01 00 ....ž÷..... |
A2S_PLAYER
This query retrieves information about the players currently on the server. It needs an initial step to acquire a challenge number.

Request Format
Data | Type | Value |
---|---|---|
Header | byte | 'U' (0x55) |
Challenge | int | Challenge number, or -1 (0xFFFFFFFF) to receive a challenge number. |
Challenge response format:
Data | Type | Value |
---|---|---|
Header | byte | 'A' (0x41) |
Challenge | int | Challenge number. |
Example challenge request:
FF FF FF FF 55 FF FF FF FF ÿÿÿÿUÿÿÿÿ" |
Example challenge response:
FF FF FF FF 41 4B A1 D5 22 ÿÿÿÿAÿÿÿÿ" |
Example A2S_PLAYER request with the received challenge number:
FF FF FF FF 55 4B A1 D5 22 ÿÿÿÿUÿÿÿÿ" |
Response Format
Data | Type | Comment | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Header | byte | Always equal to 'D' (0x44) | |||||||||||||||
Players | byte | Number of players whose information was gathered. | |||||||||||||||
For every player in "Players" there is this chunk in the response:
|
The Ship additional player info (comes after the basic information in the packet):
Data | Type | Comment |
---|---|---|
Deaths | long | Player's deaths |
Money | long | Player's money |


Example response:
FF FF FF FF 44 02 01 5B 44 5D 2D 2D 2D 2D 3E 54 ÿÿÿÿD..[D]---->T 2E 4E 2E 57 3C 2D 2D 2D 2D 00 0E 00 00 00 B4 97 .N.W<----.....´— 00 44 02 4B 69 6C 6C 65 72 20 21 21 21 00 05 00 .D.Killer !!!... 00 00 69 24 D9 43 ..i$ÙC |
The Ship response:
FF FF FF FF 44 13 00 53 68 69 70 6D 61 74 65 31 ▒▒▒▒D..Shipmate1 00 00 00 00 00 00 00 80 BF 01 53 68 69 70 6D 61 .......▒▒.Shipma 74 65 32 00 00 00 00 00 00 00 80 BF 02 53 68 69 te2.......▒▒.Shi 70 6D 61 74 65 33 00 00 00 00 00 00 00 80 BF 03 pmate3.......▒▒. 53 68 69 70 6D 61 74 65 34 00 00 00 00 00 00 00 Shipmate4....... 80 BF 04 53 68 69 70 6D 61 74 65 35 00 00 00 00 ▒▒.Shipmate5.... 00 00 00 80 BF 07 28 31 29 4C 61 6E 64 4C 75 62 ...▒▒.(1)LandLub 62 65 72 00 00 00 00 00 D3 8E 68 45 00 00 00 00 ber.....ӎhE.... C4 09 00 00 00 00 00 00 C4 09 00 00 00 00 00 00 ▒.......▒....... C4 09 00 00 00 00 00 00 C4 09 00 00 00 00 00 00 ▒.......▒....... C4 09 00 00 00 00 00 00 C4 09 00 00 ▒.......▒... |
A2S_RULES
Returns the server rules, or configuration variables in name/value pairs. This query requires an initial challenge step.
The Console variables included are the ones marked with FCVAR_NOTIFY as well as any additional ones listed in the server configuration.
Request Format
Data | Type | Value |
---|---|---|
Header | byte | 'V' (0x56) |
Challenge | long | Challenge number, or -1 (0xFFFFFFFF) to receive a challenge number. |
Challenge response format:
Data | Type | Value |
---|---|---|
Header | byte | 'A' (0x41) |
Challenge | long | Challenge number. |
Example challenge request:
FF FF FF FF 56 FF FF FF FF ÿÿÿÿVÿÿÿÿ" |
Example challenge response:
FF FF FF FF 41 4B A1 D5 22 ÿÿÿÿVK¡Õ" |

Final request that includes the received challenge number:
FF FF FF FF 56 4B A1 D5 22 ÿÿÿÿVK¡Õ" |
Response Format

Data | Type | Comment | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Header | byte | Always equal to 'E' (0x45) | |||||||||
Rules | short | Number of rules in the response. | |||||||||
For every rule in "Rules" there is this chunk in the response:
|
A2A_PING
Ping the server to see if it exists, this can be used to calculate the latency to the server.

Request Format
Data | Type | Value |
---|---|---|
Header | byte | 'i' (0x69) |
FF FF FF FF 69 ÿÿÿÿi |
Response Format
Goldsource Server
Data | Type | Value |
---|---|---|
Header | byte | 'j' (0x6A) |
Payload | string | Null |
FF FF FF FF 6A 00 ÿÿÿÿj. |
Source Server
Data | Type | Value |
---|---|---|
Heading | byte | 'j' (0x6A) |
Payload | string | '00000000000000.' |
FF FF FF FF 6A 30 30 30 30 30 30 30 30 30 30 30 ÿÿÿÿj00000000000 30 30 30 00 000. |
A2S_SERVERQUERY_GETCHALLENGE
A2S_PLAYER and A2S_RULES queries both require a challenge number. Formerly, this number could be obtained via an A2S_SERVERQUERY_GETCHALLENGE request. In newer games it no longer works. Instead, issue A2S_PLAYER or A2S_RULES queries with an initial challenge of -1 (0xFFFFFFFF)
to receive a usable challenge number.
On some engines (confirmed AppIDs: 17510, 17530, 17740, 17550, 17700) it can be used. The format is:
Request Format
Data | Type | Value |
---|---|---|
Header | byte | 'W' (0x57) |
FF FF FF FF 57 ÿÿÿÿW |
Response Format
Data | Type | Comment |
---|---|---|
Header | byte | Should be equal to 'A' (0x41.) |
Challenge | long | The challenge number to use. |
Example response:
FF FF FF FF 41 4B A1 D5 22 ÿÿÿÿAK¡Õ" |
Implementations
- @fabricio-191/valve-server-query Server, Master Server and RCON protocols implementation for Node.js
- Steam Server Query Javascript (Node.js) module which implements the Master Server Query Protocol and Game Server Queries
- Asynchronous Game Query Library A Java 8 based Asynchronous Game Query Library powered by Netty
- Source Server Query Library C library
- libssq C library
- GameServer Java library
- QueryEd Java library
- Steam Condenser Java, PHP, and Ruby library
- GameDig Javascript (Node.JS) module
- Net-SRCDS-Queries Perl module
- a2squery Python library
- SRCDSpy Python library
- SourceLib Python library
- python-valve Python library
- Left4Query Python library
- valve-range-query Python Library for IP range query
- python-a2s Python library (supports async)
- dayzquery Add-on for python-a2s library which parses DayZ-specific binary data in A2S_RULES response
- SourceStats Source Server Statistics
- PHP Source Query PHP library
- SteamQuery.NET .NET/C# Wrapper (Built in .NET 9/.NET Standard 2.0, by cemahseri. Supports Source, GoldSource, and obsolete GoldSource protocols.)
- QueryMaster C# library
- QueryMaster C# library (remaster for .NET Standart 2.0)
- Okolni-Source-Query C# library (.NET Standard 2.0, Now Support l4d2 2213)
- A2S C# library utilizing NET5. (Currently supports A2S_Info and A2S_Player)
- aQuery VB.NET library
- go-a2s Golang library
- a2s-rs Rust library
- Rcon and A2s WebApi中文的WebApi协议库,基于Spring boot,仅支持A2S_INFO、A2S_PLAYER,Now Support l4d2 2213
- SteamPS Module that utilizes PowerShell as a wrapper for SteamCMD. Uses server queries in the command Get-SteamServerInfo
- Mirai Tencent QQ robot基于mriaiBot适配了a2s rcon的腾讯qq机器人,仅支持A2S_INFO、A2S_PLAYER,Rcon,Now Support l4d2 2213
- Rust-GameDig Rust library that supports the entirety of the protocol (also has the obsolete GoldSrc response).
- SteamQueryProxy Extremely high performance protocol proxy written in pure C for Linux (Can be used to mitigate VSE DoS attacks, supports Source & GoldSource).
- Steam2Go Golang library. Includes support for A2S, rcon and various WebAPI services.
- ObjC Source Query ObjC implementation of the Source Engine Query Protocol + Valve Master Server queries.