Server queries: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(→‎Protocol: HL1->goldsrc)
m (Added Objective C library to the implementations list)
 
(150 intermediate revisions by 58 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.


==Basic 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 5 basic types of data packed together into a data stream. All types are little endian, so no conversion is needed on x86 CPUs.
{| class=standard-table
{|
! Name || Description
! Name || Description
|-
|-
| [[byte]] || 8 bit character
| [[byte]] || 8 bit character or unsigned integer
|-
|-
| [[short]] || 16 bit signed integer
| [[short]] || 16 bit signed integer
Line 13: Line 16:
| [[long]] || 32 bit signed integer
| [[long]] || 32 bit signed integer
|-
|-
| [[float]] || 32 bit float value
| [[float]] || 32 bit floating point
|-
| [[long]] [[long]] || 64 bit unsigned integer
|-
|-
| [[string]] || variable length byte field, terminated by 0x00
| [[string]] || variable-length byte field, encoded in UTF-8, terminated by 0x00
|}
|}


==Protocol==
== 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 ===


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 in the following format:
{| class=standard-table
{|
! Data !! Type !! Comment
! Data || Type || Comment
|-
| Header || [[long]] || Always equal to -1 (0xFFFFFFFF). Means it isn't split.
|-
| colspan="3" | Payload
|}
 
=== Multi-packet Response Format ===
 
====[[Goldsource]] Server====
 
{| class=standard-table
! Data !! Type !! Comment
|-
|-
| Type || [[long]] || -2 (0xFFFFFFFE) to indicate that data is split over several packets
| Header || [[long]] || Always equal to -2 (0xFFFFFFFE). Means the packet is split.
|-
|-
| Request ID || [[long]] || The server assigns a unique number to each split packet. (Source Engine only) If the top bit of the request ID is set then this packet has been compressed with the BZip2 algorithm before being split, after you get all the pieces you need to uncompress it with BZ2_bzBuffToBuffDecompress() before reading the raw data.
| ID || [[long]] || Unique number assigned by server per answer.
|-
|-
| Packet Number || [[byte]] / [[short]] || (Goldsource Engine)The lower four bits represent the number of packets (2 to 15) and the upper four bits represent the current packet starting with 0
| 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).
(Source Engine)The lower byte is the number of packets, the upper byte this current packet starting with 0.
|-
|-
| Size of the Splits || [[short]] || (Source Engine)For the new version of the source engine we changed the SPLITPACKET header slightly to include at the end a short which is the size of the splits (it used to be hard coded).  In our games  a user can request a smaller packet size before a split occurs, the default is 0x04e0 which is 1248 bytes.  The query protocols, however, don't allow requesting a different split size, so the new default (1248) is what you should always see there.  So if you are querying a TF2 server you need to account for that.  A TF2 server op can also lower the max routable payload, so you can't guarantee that it'll always be 0x04e0.
| colspan="3" | Payload
|}
|}


====[[Source]] Server====


If the packet is compressed, there are two extra fields in the first packet.
{| class=standard-table
{|
! 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 {{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.
|-
| 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.
|-
| colspan="3" | This is only present in the first packet of the response and only if the response is being compressed.
{| style="margin:10px"
! Data || Type || Comment
! Data || Type || Comment
|-
|-
| Type || [[integer]] || Number of bytes the data uses after decompression;
| Size || [[long]] || Size of the whole response once it is decompressed.
|-
| CRC32 sum || [[long]] || CRC32 checksum of uncompressed response.
|}
To uncompress this response: collect and assemble all the payloads of the received packets, then pass that into a function like [http://www.bzip.org/1.0.3/html/util-fns.html#bzbufftobuffdecompress BZ2_bzBuffToBuffDecompress()] in C, [http://fr.php.net/manual/fr/function.bzdecompress.php bzdecompress()] in PHP, or [http://docs.python.org/2/library/bz2.html bz2.decompress()] in Python. Compression appears to have been phased out in newer Source games, but is still present in ~2006-era engines.
|-
|-
| Type || [[integer]] || CRC32 checksum of the uncompressed data for validation.
| colspan="3" | Payload
|}
|}


Because UDP packets can arrive in different order or delayed, every packet should be verified by its Request ID and the Packet Number!
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.
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).
So by reading the first 4 bytes you can decide whether the data is split (-2) or in one packet (-1).


==Query Types==
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 4 queries:
The server responds to 5 queries:


;<code>A2A_PING</code>:Ping the server.
;<code>A2S_INFO</code>
;<code>A2S_SERVERQUERY_GETCHALLENGE</code>:Returns a challenge number for use in the player and rules query.
:Basic information about the server.
;<code>A2S_INFO</code>:Basic information about the server.
;<code>A2S_PLAYER</code>
;<code>A2S_PLAYER</code>:Details about each player on the server.
:Details about each player on the server.
;<code>A2S_RULES</code>:The rules the server is using.
;<code>A2S_RULES</code>
Queries should be sent in UDP packets to the listen port of the server, which is typically port 27015.
:The rules the server is using.
;<code>A2A_PING</code>
:Ping the server. (DEPRECATED)
;<code>A2S_SERVERQUERY_GETCHALLENGE</code>
:Returns a challenge number for use in the player and rules query. (DEPRECATED)


===A2A_PING===
Queries should be sent in UDP packets to the listen port of the server.
Ping the server to see if it exists, this can be used to calculate the latency to the server.
 
====Request format====
== 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.
 
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
! Data || Type || Value
! Data || Type || Value
|-
|-
| Heading || [[byte]] || 'i' (0x69)
| Header || [[byte]] || 'T' (0x54)
|}
====Reply format====
=====[[Goldsource]] servers=====
{|
! Data || Type || Value
|-
|-
| Heading || [[byte]] || 'j' (0x6A)
| Payload || [[string]] || "Source Engine Query\0"
|-
|-
| Content || [[string]] || Null
| Challenge || [[long]] || 4-byte challenge (sometimes -- see below)
|}
|}


=====[[Source]] servers=====
{|style="background:transparent;"
{|
|
! Data || Type || Value
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.
| Heading || [[byte]] || 'j' (0x6A)
|-
| Content || [[string]] || '00000000000000'
|}
|}


===A2S_SERVERQUERY_GETCHALLENGE===
Example for challenge number:
====Request format====
Challenge values are required for <code>A2S_PLAYER</code> and <code>A2S_RULES</code> requests, you can use this request to get one.
{{note|You can also send <code>A2S_PLAYER</code> and <code>A2S_RULES</code> queries with a challenge value of <code>-1 (0xFF FF FF FF)</code> and they will respond with a challenge value to use (using the reply format below).}}


FF FF FF FF 57
Server response:
{|style="background:transparent;"
|
FF FF FF FF 41 0A 08 5E EA
|}
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
|}


====Reply format====


{|
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!
! Data || Type || Comment
|-
| Type || [[byte]] || Should be equal to 'A' (0x41)
|-
| Challenge || [[long]] || The challenge number to use
|}


Example reply:
NOTE:changed 2021-6-19 13:05:43 :when l4d2 server received some packet from same ip address,it may deined replay


FF FF FF FF 41 32 42 59 45
NOTE:some older titles have been observed sending the GoldSource INFO packet AND the newer INFO packet in reply to this.


===A2S_INFO===
==== Response Format ====


====Request format====
{{Note|Both [[SiN 1 Multiplayer]] and [[Rag Doll Kung Fu]] utilise this response protocol.}}
Server info can be requested by sending the following byte values in a UDP packet to the server.
{|style="background:transparent;"
|
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
|}
i.e. -1 (int), 'T' ([[byte]]), "Source Engine Query" ([[string]])


====Reply format====
{| class=standard-table
=====[[Source]] servers=====
! Data !! Type !! Comment
{|
|-
! 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.
|-
|-
| Type || [[byte]] || Should be equal to 'I' (0x49)
| Game || [[string]] || Full name of the game.
|-
|-
| Version || [[byte]] || Network version. 0x07 is the current Steam version.
| ID || [[short]] || [[Steam Application ID]] of game.
|-
|-
| Server Name || [[string]] || The Source server's name, eg: "Recoil NZ CS Server #1"
| Players || [[byte]] || Number of players on the server.
|-
|-
| Map || [[string]] || The current map being played, eg: "de_dust"
| Max. Players || [[byte]] || Maximum number of players the server reports it can hold.
|-
|-
| Game Directory || [[string]] || The name of the folder containing the game files, eg: "cstrike"
| Bots || [[byte]] || Number of bots on the server.
|-
|-
| Game Description || [[string]] || A friendly string name for the game type, eg: "Counter Strike: Source"
| 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>
|-
|-
| AppID || [[short]] || [[Steam Application IDs|Steam Application ID]]
| 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>
|-
|-
| Number of players || [[byte]] || The number of players currently on the server
| Visibility || [[byte]] || Indicates whether the server requires a password: <ul><li>0 for public</li><li>1 for private</li></ul>
|-
|-
| Maximum players || [[byte]] || Maximum allowed players for the server
| [[VAC]] || [[byte]] || Specifies whether the server uses VAC: <ul><li>0 for unsecured</li><li>1 for secured</li></ul>
|-
|-
| Number of bots || [[byte]] || Number of bot players currently on the server
| colspan="3" | These fields only exist in a response if the server is running [[The Ship]]:
{| style="margin:10px;"
! Data || Type || Comment
|-
|-
| Dedicated || [[byte]] || 'l' for listen, 'd' for dedicated, 'p' for SourceTV
| Mode || [[byte]] || Indicates the game mode: <ul><li>0 for Hunt</li><li>1 for Elimination</li><li>2 for Duel</li><li>3 for Deathmatch</li><li>4 for VIP Team</li><li>5 for Team Elimination</li></ul>
|-
|-
| OS || [[byte]] || Host operating system. 'l' for Linux, 'w' for Windows
| Witnesses || [[byte]] || The number of witnesses necessary to have a player arrested.
|-
|-
| Password || [[byte]] || If set to 0x01, a password is required to join this server
| Duration || [[byte]] || Time (in seconds) before a player is arrested while being witnessed.
|}
|-
|-
| Secure || [[byte]] || if set to 0x01, this server is VAC secured
| Version || [[string]] || Version of the game installed on the server.
|-
|-
| Game Version || [[string]] || The version of the game, eg: "1.0.0.22"
| Extra Data Flag (EDF) || [[byte]] || If present, this specifies which additional data fields will be included.
|-
|-
| Extra Data Flag (EDF) || [[byte]] || if present this specifies which additional data fields will be included
| colspan="3" | '''Only if''' <code>if ( EDF & 0x80 )</code> proves true:
{| style="margin:10px"
! Data || Type || Comment
|-
|-
| if ( EDF & 0x80 ) || [[short]] || The server's game port # is included
| Port || [[short]] || The server's game port number.
|}
|-
|-
| if ( EDF & 0x40 ) || [[short]] [[ string ]] || The spectator port # and then the spectator server name are included
| colspan="3" | '''Only if''' <code>if ( EDF & 0x10 )</code> proves true:
{| style="margin:10px"
! Data || Type || Comment
|-
|-
| if ( EDF & 0x20 ) || [[string]] || The game tag data string for the server is included [future use]
| [[SteamID]] || [[long]] long || Server's SteamID.
|}
|}
|-
| colspan="3" | '''Only if''' <code>if ( EDF & 0x40 )</code> proves true:
{| style="margin:10px"
! Data || Type || Comment
|-
| Port || [[short]] || Spectator port number for [[SourceTV]].
|-
| Name || [[string]] || Name of the spectator server for SourceTV.
|}
|-
| colspan="3" | '''Only if''' <code>if ( EDF & 0x20 )</code> proves true:
{| style="margin:10px"
! Data || Type || Comment
|-
| Keywords || [[string]] || Tags that describe the game according to the server (for future use.)
|}
|-
| colspan="3" | '''Only if''' <code>if ( EDF & 0x01 )</code> proves true:
{| style="margin:10px"
! Data || Type || Comment
|-
| GameID || [[long]] long || The server's 64-bit GameID. If this is present, a more accurate AppID is present in the low 24 bits. The earlier AppID could have been truncated as it was forced into 16-bit storage.
|}
|}
{{Note|[[Rag Doll Kung Fu]] servers always return 0 for "Server type."}}
<br>


Example reply:
Example response for [[Counter-Strike: Source]]:
{|style="background:transparent;"
{|style="background:transparent;"
|
|
Line 174: Line 260:
|}
|}


=====[[The Ship]] servers=====
Example response for [[The Ship]]:
{|
{|style="background:transparent;"
! Data || Type || Comment
|
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]]:
{|style="background:transparent;"
|
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]]:
{|style="background:transparent;"
|
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.
 
{| 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.
|-
|-
| Type || [[byte]] || Should be equal to 'I' (0x49)
| Game || [[string]] || Full name of the game.
|-
|-
| Version || [[byte]] || Network version. 0x07 is the current Steam version.
| Players || [[byte]] || Number of players on the server.
|-
|-
| Server Name || [[string]] || The Source server's name, eg: "Xtra The Ship #1 [Hunt]"
| Max. Players || [[byte]] || Maximum number of players the server reports it can hold.
|-
|-
| Map || [[string]] || The current map being played, eg: "batavier"
| Protocol || [[byte]] || Protocol version used by the server.
|-
|-
| Game Directory || [[string]] || The name of the folder containing the game files, eg: "ship"
| 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>
|-
|-
| Game Description || [[string]] || A friendly string name for the game type, eg: "The Ship"
| Environment || [[byte]] || Indicates the operating system of the server: <ul><li>'L' for Linux</li><li>'W' for Windows</li></ul>
|-
|-
| AppID || [[short]] || [[Steam Application IDs|Steam Application ID]]
| Visibility || [[byte]] || Indicates whether the server requires a password: <ul><li>0 for public</li><li>1 for private</li></ul>
|-
|-
| Number of players || [[byte]] || The number of players currently on the server
| Mod || [[byte]] || Indicates whether the game is a mod: <ul><li>0 for [[Half-Life]]</li><li>1 for Half-Life mod</li></ul>
|-
|-
| Maximum players || [[byte]] || Maximum allowed players for the server
| colspan="3" | These fields are only present in the response if "Mod" is 1:
{| style="margin:10px"
! Data || Type || Comment
|-
|-
| Number of bots || [[byte]] || Number of bot players currently on the server
| Link || [[string]] || URL to mod website.
|-
|-
| Dedicated || [[byte]] || 'l' for listen, 'd' for dedicated, 'p' for SourceTV
| Download Link || [[string]] || URL to download the mod.
|-
|-
| OS || [[byte]] || Host operating system. 'l' for Linux, 'w' for Windows
| NULL || [[byte]] || NULL byte (0x00)
|-
|-
| Password || [[byte]] || If set to 0x01, a password is required to join this server
| Version || [[long]] || Version of mod installed on server.
|-
|-
| Secure || [[byte]] || if set to 0x01, this server is VAC secured
| Size || [[long]] || Space (in bytes) the mod takes up.
|-
|-
| Game Mode || [[byte]] || 0x00 for Hunt, 0x01 for Elimination, 0x02 for Duel, 0x03 for Deathmatch, 0x04 for Team VIP, 0x05 for Team Elimination
| Type || [[byte]] || Indicates the type of mod: <ul><li>0 for single '''and''' multiplayer mod</li><li>1 for multiplayer '''only''' mod</li></ul>
|-
|-
| Witness Count || [[byte]] || The minimum number of witnesses for a player to be arrested.
| 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>
|}
|-
|-
| Witness Time || [[byte]] || Time in seconds before player is arrested while being witnessed.
| [[VAC]] || [[byte]] || Specifies whether the server uses VAC: <ul><li>0 for unsecured</li><li>1 for secured</li></ul>
|-
|-
| Game Version || [[string]] || The version of the game, eg: "1.0.0.14"
| Bots || [[byte]] || Number of bots on the server.
|}
|}


Example reply:
{{Note|HLTV servers may respond with a late request that is either incomplete or incorrect if the number of slots is 255.}}
{|style="background:transparent;"
 
<br>
 
Example response:
{| style="background:transparent;"
|
|
  FF FF FF FF 49 07 53 68 69 70 20 53 65 72 76 65    ÿÿÿÿI.Ship Serve
  FF FF FF FF 6D 37 37 2E 31 31 31 2E 31 39 34 2E    ÿÿÿÿm77.111.194.
  72 00 62 61 74 61 76 69 65 72 00 73 68 69 70 00    r.batavier.ship.
31 31 30 3A 32 37 30 31 35 00 46 52 20 2D 20 56    110:27015.FR - V
  54 68 65 20 53 68 69 70 00 60 09 01 05 00 6C 77   The Ship.`....lw
65 72 79 47 61 6D 65 73 2E 6E 65 74 20 2D 20 44   eryGames.net - D
  00 00 01 03 03 31 2E 30 2E 30 2E 34 00             .....1.0.0.4.
  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                   ....ž÷.....
|}
|}


=====[[Goldsource]] servers=====
=== A2S_PLAYER ===


WARNING: This is obsolete.  GoldSource servers (except for HLTV ones?) now report using the same protocol as Source servers. To differentiate between (for example) Counter-Strike and Counter-Strike: Source, or other games with the same gamedir, use the Steam AppId.
This query retrieves information about the players currently on the server. It needs an initial step to acquire a challenge number.


{|
{{Note|[[SourceTV]] does not respond to this request.}}
! Data || Type || Comment
 
==== Request Format ====
 
{| class=standard-table
! Data || Type || Value
|-
|-
| Type || [[byte]] || Should be equal to 'm' (0x6D)
| Header || [[byte]] || 'U' (0x55)
|-
|-
| Game IP || [[string]] || Game Server IP address and port
| Challenge || [[int]] || Challenge number, or -1 (0xFFFFFFFF) to receive a challenge number.
|}
 
Challenge response format:
{| class=standard-table
! Data || Type || Value
|-
|-
| Server Name || [[string]] || The server's name, eg: "Recoil NZ CS Server #1"
| Header || [[byte]] || 'A' (0x41)
|-
|-
| Map || [[string]] || The current map being played, eg: "de_dust"
| Challenge || [[int]] || Challenge number.
|}
 
Example challenge request:
{| style="background:transparent;"
|
FF FF FF FF 55 FF FF FF FF                        ÿÿÿÿUÿÿÿÿ"     
|}
 
Example challenge response:
{| style="background:transparent;"
|
FF FF FF FF 41 4B A1 D5 22                        ÿÿÿÿAÿÿÿÿ"     
|}
 
Example A2S_PLAYER request with the received challenge number:
{| style="background:transparent;"
|
FF FF FF FF 55 4B A1 D5 22                        ÿÿÿÿUÿÿÿÿ"     
|}
 
==== Response Format ====
 
{| class=standard-table
! Data !! Type !! Comment
|-
|-
| Game Directory || [[string]] || The name of the folder containing the game files, eg: "cstrike"
| Header || [[byte]] || Always equal to 'D' (0x44)
|-
|-
| Game Description || [[string]] || A friendly string name for the game type, eg: "Counter-Strike"
| Players || [[byte]] || Number of players whose information was gathered.
|-
|-
| Number of players || [[byte]] || The number of players currently on the server
| colspan="3" | For every player in "Players" there is this chunk in the response:
{| style="margin:10px"
! Data || Type || Comment
|-
|-
| Maximum players || [[byte]] || Maximum allowed players for the server
| Index || [[byte]] || Index of player chunk starting from 0.
|-
|-
| Version || [[byte]] || Network version. 0x07 is the current Steam version.
| Name || [[string]] || Name of the player.
|-
|-
| Dedicated || [[byte]] || 'l' for listen, 'd' for dedicated, 'p' for HLTV
| Score || [[long]] || Player's score (usually "frags" or "kills".)
|-
|-
| OS || [[byte]] || Host operating system. 'l' for Linux, 'w' for Windows
| Duration || [[float]] || Time (in seconds) player has been connected to the server.
|-
|}
| Password || [[byte]] || If set to 0x01, a password is required to join this server
|-
| IsMod || [[byte]] || If set to 0x01, this byte is followed by [[#ModInfo|ModInfo]]
|-
| Secure || [[byte]] || if set to 0x01, this server is VAC secured
|-
| Number of bots || [[byte]] || Number of bot players currently on the server
|}
|}


======ModInfo======
[[The Ship]] additional player info (comes after the basic information in the packet):
{|
 
{| class=standard-table
! Data || Type || Comment
! Data || Type || Comment
|-
|-
| URLInfo || [[string]] || URL containing information about this mod
| Deaths || [[long]] || Player's deaths
|-
|-
| URLDL || [[string]] || URL to download this mod
| 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.}}
 
{{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>
 
Example response:
{| style="background:transparent;"
|
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:
{| 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.
 
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
! Data || Type || Value
|-
|-
| Nul || [[byte]] || 0x00
| Header || [[byte]] || 'V' (0x56)
|-
|-
| ModVersion || [[long]] || Version of the installed mod
| Challenge || [[long]] || Challenge number, or -1 (0xFFFFFFFF) to receive a challenge number.
|-
|}
| ModSize || [[long]] || The download size of this mod
 
Challenge response format:
{| class=standard-table
! Data || Type || Value
|-
|-
| SvOnly || [[byte]] || If 1 this is a server side only mod
| Header || [[byte]] || 'A' (0x41)
|-
|-
| ClDLL || [[byte]] || If 1 this mod has a custom client dll
| Challenge || [[long]] || Challenge number.
|}
|}


=====[[SiN 1 Multiplayer]] servers=====
Example challenge request:
SiN 1 Multiplayer servers respond to the "Source Engine Query" request. Their reply is in the same format as Source's.
{| style="background:transparent;"
|
FF FF FF FF 56 FF FF FF FF                        ÿÿÿÿVÿÿÿÿ"      
|}


Example reply:
Example challenge response:
{|style="background:transparent;"
{| style="background:transparent;"
|
|
  FF FF FF FF 49 2F 53 65 6E 73 65 6D 61 6E 6E 20    ÿÿÿÿI/Sensemann
  FF FF FF FF 41 4B A1 D5 22                        ÿÿÿÿVK¡Õ"     
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.
|}
|}


=====[[Rag Doll Kung Fu]] servers=====
{{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)}}


Rag Doll Kung Fu servers respond to the "Source Engine Query" request. Their reply is in the same format as Source's.
Final request that includes the received challenge number:
Example reply:
{| style="background:transparent;"
{|style="background:transparent;"
|
|
  FF FF FF FF 49 FC 54 68 65 20 44 75 64 65 27 73    ÿÿÿÿIüThe Dude's
  FF FF FF FF 56 4B A1 D5 22                        ÿÿÿÿVK¡Õ"     
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.
|}
|}


===A2S_PLAYER===
==== Response Format ====
====Request format====
 
FF FF FF FF 55 <4 byte challenge number>
{{Note|Responses to this query are usually multi-packeted.}}
The challenge number can either be set to <code>-1 (0xFF FF FF FF)</code> to have the server reply with <code>S2C_CHALLENGE</code>, or use the value from a previous <code>A2S_SERVERQUERY_GETCHALLENGE</code> request.
 
====Reply format====
{| class=standard-table
The players response has two sections, the initial header:
! Data !! Type !! Comment
{|
|-
! Data || Type || Comment
| Header || [[byte]] || Always equal to 'E' (0x45)
|-
|-
| Type || [[byte]] || Should be equal to 'D' (0x44)
| Rules || [[short]] || Number of rules in the response.
|-
|-
| Num Players || [[byte]] || The number of players reported in this response
| colspan="3" | For every rule in "Rules" there is this chunk in the response:
|}
{| style="margin:10px;"
Then for each player the following fields are sent:
{|
! Data || Type || Comment
! Data || Type || Comment
|-
|-
| Index || [[byte]] || The index into [0.. Num Players] for this entry
| Name || [[string]] || Name of the rule.
|-
|-
| Player Name || [[string]] || Player's name
| Value || [[string]] || Value of the rule.
|}
|}
 
=== A2A_PING ===
 
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.}}
 
==== Request Format ====
 
{| class=standard-table
! Data || Type || Value
|-
|-
| Kills|| [[long]] || Number of kills this player has
| Header || [[byte]] || 'i' (0x69)
|}
 
{| style="background:transparent;"
|
FF FF FF FF 69                                    ÿÿÿÿi         
|}
 
==== Response Format ====
 
===== [[Goldsource]] Server =====
 
{| class=standard-table
! Data || Type || Value
|-
|-
| Time connected || [[float]] || The time in seconds this player has been connected
| Header || [[byte]] || 'j' (0x6A)
|-
|-
| Payload || [[string]] || Null
|}
|}


{| style="background:transparent;"
|
FF FF FF FF 6A 00                                  ÿÿÿÿj.         
|}


{{note| Java users can read the player score as an [[int]] and reverse the bytes with Integer.reverseBytes(int i).}}
===== [[Source]] Server =====


===A2S_RULES===
{| class=standard-table
====Request format====
! Data || Type || Value
FF FF FF FF 56 <4 byte challenge number>
The challenge number can either be set to <code>-1 (0xFF FF FF FF)</code> to have the server reply with <code>S2C_CHALLENGE</code>, or use the value from a previous <code>A2S_SERVERQUERY_GETCHALLENGE</code> request.
====Reply format====
The rules response has two sections, the initial header:
{|
! Data || Type || Comment
|-
|-
| Type || [[byte]] || Should be equal to 'E' (0x45)
| Heading || [[byte]] || 'j' (0x6A)
|-
|-
| Num Rules || [[short]] || The number of rules reported in this response
| Payload || [[string]] || '00000000000000.'
|}
 
{| style="background:transparent;"
|
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 <code>-1 (0xFFFFFFFF)</code> 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 ====
 
{| class=standard-table
! Data || Type || Value
|-
|-
| Header || [[byte]] || 'W' (0x57)
|}
|}
Then for each rule the following fields are sent:
 
{|
{| style="background:transparent;"
|
FF FF FF FF 57                                    ÿÿÿÿW         
|}
 
==== Response Format ====
 
{| class=standard-table
! Data || Type || Comment
! Data || Type || Comment
|-
|-
| Rule Name || [[string]] || The name of the rule
| Header || [[byte]] || Should be equal to 'A' (0x41.)
|-
|-
| Rule Value || [[string]] || The rule's value
| Challenge || [[long]] || The challenge number to use.
|}
 
Example response:
 
{| style="background:transparent;"
|
FF FF FF FF 41 4B A1 D5 22                        ÿÿÿÿAK¡Õ"     
|}
|}
===See Also===
 
== 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
* [https://github.com/BinaryAlien/libssq libssq] C library
* [http://www.barkerjr.net/gameserver.html GameServer] Java library
* [http://queried.sourceforge.net QueryEd] Java library
* [[Steam Condenser]] Java, PHP, and Ruby library
* [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/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/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 also ==
 
* [[Master Server Query Protocol]]
* [[Master Server Query Protocol]]
* [[Source Server Query Library]]
* [[Source RCON Protocol]]
* [[Steam Condenser]]
{{otherlang:en}}
{{otherlang:en:fr|Server_Queries:fr}}
 
[[Category:Networking]]
[[Category:Networking]]
[[Category:Technical]]
[[Category:Technical]]
[[Category:Dedicated Server]]

Latest revision as of 00:16, 13 August 2025

English (en)Français (fr)Русский (ru)Translate (Translate)

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 Wikipedia icon 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.
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.
Data Type Comment
Size long Size of the whole response once it is decompressed.
CRC32 sum long CRC32 checksum of uncompressed response.

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

Note.pngNote:Both SiN 1 Multiplayer and Rag Doll Kung Fu utilise this response protocol.
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:
  • 'd' for a dedicated server
  • 'l' for a non-dedicated server
  • 'p' for a SourceTV relay (proxy)
Environment byte Indicates the operating system of the server:
  • 'l' for Linux
  • 'w' for Windows
  • 'm' or 'o' for Mac (the code changed after L4D1)
Visibility byte Indicates whether the server requires a password:
  • 0 for public
  • 1 for private
VAC byte Specifies whether the server uses VAC:
  • 0 for unsecured
  • 1 for secured
These fields only exist in a response if the server is running The Ship:
Data Type Comment
Mode byte Indicates the game mode:
  • 0 for Hunt
  • 1 for Elimination
  • 2 for Duel
  • 3 for Deathmatch
  • 4 for VIP Team
  • 5 for Team Elimination
Witnesses byte The number of witnesses necessary to have a player arrested.
Duration byte Time (in seconds) before a player is arrested while being witnessed.
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:
Data Type Comment
Port short The server's game port number.
Only if if ( EDF & 0x10 ) proves true:
Data Type Comment
SteamID long long Server's SteamID.
Only if if ( EDF & 0x40 ) proves true:
Data Type Comment
Port short Spectator port number for SourceTV.
Name string Name of the spectator server for SourceTV.
Only if if ( EDF & 0x20 ) proves true:
Data Type Comment
Keywords string Tags that describe the game according to the server (for future use.)
Only if if ( EDF & 0x01 ) proves true:
Data Type Comment
GameID long long The server's 64-bit GameID. If this is present, a more accurate AppID is present in the low 24 bits. The earlier AppID could have been truncated as it was forced into 16-bit storage.
Note.pngNote:Rag Doll Kung Fu servers always return 0 for "Server type."


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:
  • 'D' for dedicated server
  • 'L' for non-dedicated server
  • 'P' for a HLTV server
Environment byte Indicates the operating system of the server:
  • 'L' for Linux
  • 'W' for Windows
Visibility byte Indicates whether the server requires a password:
  • 0 for public
  • 1 for private
Mod byte Indicates whether the game is a mod:
These fields are only present in the response if "Mod" is 1:
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:
  • 0 for single and multiplayer mod
  • 1 for multiplayer only mod
DLL byte Indicates whether mod uses its own DLL:
  • 0 if it uses the Half-Life DLL
  • 1 if it uses its own DLL
VAC byte Specifies whether the server uses VAC:
  • 0 for unsecured
  • 1 for secured
Bots byte Number of bots on the server.
Note.pngNote:HLTV servers may respond with a late request that is either incomplete or incorrect if the number of slots is 255.


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.

Note.pngNote:SourceTV does not respond to this request.

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:
Data Type Comment
Index byte Index of player chunk starting from 0.
Name string Name of the player.
Score long Player's score (usually "frags" or "kills".)
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):

Data Type Comment
Deaths long Player's deaths
Money long Player's money
Note.pngNote: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.pngWarning: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.



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¡Õ"       
Warning.pngWarning: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:

FF FF FF FF 56 4B A1 D5 22                         ÿÿÿÿVK¡Õ"       

Response Format

Note.pngNote:Responses to this query are usually multi-packeted.
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:
Data Type Comment
Name string Name of the rule.
Value string Value of the rule.

A2A_PING

Ping the server to see if it exists, this can be used to calculate the latency to the server.

Warning.pngWarning:According to Valve (see 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

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

See also