Steam Query Protocol (A2S)
If you've ever wondered how Steam knows your game server exists, how the server browser populates, or why your server sometimes doesn't show up — the answer is the Steam Server Query Protocol, commonly called A2S.
This guide explains what A2S is, how it works, which games use it, and how to troubleshoot common issues.
What is the Steam Query Protocol?
The Steam Query Protocol is a UDP-based protocol that allows clients (like the Steam server browser, or tools like python-a2s) to request information from a game server. Valve originally designed it for Source Engine games (Counter-Strike, Team Fortress 2, Half-Life), but it's now used by most games with Steam multiplayer.
When you open the Steam server browser and see a list of servers with player counts, map names, and ping times — that data comes from A2S queries.
The Three Main Query Types
| Query | Request | Response | Purpose |
|---|---|---|---|
| A2S_INFO | \xFF\xFF\xFF\xFF\x54 | Server name, map, players, max players, game, OS | Basic server information |
| A2S_PLAYER | \xFF\xFF\xFF\xFF\x55 | Player names, scores, play time | Who's currently playing |
| A2S_RULES | \xFF\xFF\xFF\xFF\x56 | Server configuration key-value pairs | Server settings (cvars) |
All three use UDP and follow a challenge-response pattern to prevent spoofing.
How A2S Works
┌──────────┐ ┌──────────────┐
│ Client │ │ Game Server │
│ (Steam) │ │ (Query Port) │
└─────┬─────┘ └──────┬───────┘
│ │
│ A2S_INFO request (UDP) │
│────────────────────────────────>│
│ │
│ Challenge response │
│<────────────────────────────────│
│ │
│ A2S_INFO + challenge token │
│────────────────────────────────>│
│ │
│ Server info response │
│<────────────────────────────────│
│ │
- Client sends a query to the server's query port (usually the game port or game port + 1)
- Server responds with a challenge — a random 4-byte token
- Client re-sends the query with the challenge token included
- Server responds with the actual data
The challenge step was added by Valve to prevent reflection/amplification DDoS attacks, where attackers would spoof the source IP to flood a victim with server responses.
Query Port vs Game Port
This is one of the most common sources of confusion. Most games use two different ports:
| Port | Protocol | Purpose |
|---|---|---|
| Game Port | UDP (usually) | Actual game traffic — player connections, world state |
| Query Port | UDP | Steam browser queries, monitoring tools, A2S |
The query port is typically:
- Game port + 1 (Source Engine convention: game on 27015, query on 27016)
- A fixed offset (ARK uses game port 7777, query port 27015)
- The same port (some games handle both on one port)
Port Mapping for Popular Games
| Game | Default Game Port | Query Port | Protocol |
|---|---|---|---|
| Rust | 28015 | 28016 | UDP |
| ARK: Survival Evolved | 7777 | 27015 | UDP |
| ARK: Survival Ascended | 7777 | 27015 | UDP |
| Valheim | 2456 | 2457 | UDP |
| DayZ | 2302 | 27016 | UDP |
| 7 Days to Die | 26900 | 26900 | UDP (same port) |
| Enshrouded | 15636 | 15637 | UDP |
| Palworld | 8211 | 27015 | UDP |
| SCUM | 7042 | 27015 | UDP |
| V Rising | 9876 | 9877 | UDP |
| Unturned | 27015 | 27016 | UDP |
| Project Zomboid | 16261 | 16261 | UDP (same port) |
| Satisfactory | 7777 | 15777 | UDP |
| Factorio | 34197 | N/A | No A2S — uses own protocol |
| Minecraft | 25565 | 25565 | TCP (own protocol, not A2S) |
Minecraft uses its own Server List Ping protocol over TCP. Factorio uses a custom matchmaking protocol. These games bypass Steam's query system entirely.
Querying a Server with Python
You can query any A2S-compatible server using the python-a2s library:
pip install python-a2s
import a2s
# Query server info
address = ("your-server-ip", 27015) # Use the QUERY port, not game port
info = a2s.info(address, timeout=3.0)
print(f"Server: {info.server_name}")
print(f"Map: {info.map_name}")
print(f"Players: {info.player_count}/{info.max_players}")
print(f"Game: {info.game}")
print(f"Platform: {info.platform}")
print(f"VAC: {info.vac_enabled}")
# Query players
players = a2s.players(address)
for player in players:
print(f" {player.name}: {player.score} points, {player.duration:.0f}s")
# Query server rules/cvars
rules = a2s.rules(address)
for key, value in rules.items():
print(f" {key} = {value}")
From Inside a Kubernetes Cluster
If your server runs inside K8s (like Reactor's infrastructure), you can query from within the cluster using the pod's internal IP:
kubectl exec <pod-name> -c game-server -- \
python3 -c "import a2s; print(a2s.info(('127.0.0.1', 27015)).server_name)"
Why Your Server Isn't Showing Up
If your game server is running but doesn't appear in the Steam server browser, check these common causes:
1. Query Port Not Open
The query port must be reachable from the internet over UDP. Many hosting providers and firewalls block UDP by default.
Fix: Ensure your firewall allows inbound UDP on the query port. On Reactor, all required ports are automatically opened via NodePort services.
2. Wrong Query Port Configuration
Some games default to a query port that differs from what Steam expects.
Fix: Check the game's configuration file for a QueryPort or QUERY_PORT setting. Make sure it matches what's actually exposed.
3. Server Not Registered with Steam Master Server
Most games automatically register with the Steam master server on startup. If this fails (due to network issues or misconfiguration), the server won't appear in the browser.
Fix: Check the game server logs for messages like "Master server connection" or "Steam authentication". A GSLT (Game Server Login Token) is required for some games.
4. NAT / Port Forwarding Issues
If the game server binds to an internal IP but the external IP differs, Steam queries may fail because the server reports the wrong IP.
Fix: Set MULTIHOME=0.0.0.0 or the correct external IP in your server configuration.
5. Rate Limiting
Steam limits how many queries a single IP can make. If you're running monitoring tools that query too frequently, the server may stop responding.
Fix: Reduce query frequency to once every 5-10 seconds per server.
GSLT — Game Server Login Tokens
Some games (Rust, CS2, Garry's Mod) require a Game Server Login Token (GSLT) to appear in the Steam server browser. Without a GSLT, the server runs but is invisible to Steam matchmaking.
How to Get a GSLT
- Go to Steam Game Server Account Management
- Enter the game's App ID (e.g., 252490 for Rust)
- Add a memo (e.g., "My Rust Server")
- Copy the generated token
- Set it in your server config (
+sv_setsteamaccount <token>for Source games)
When you provision a game server on Reactor that requires a GSLT, we automatically generate and configure it for you using the Steam Web API. No manual setup needed.
Monitoring & Uptime Checking
You can use A2S queries to build monitoring systems that check if your game server is healthy:
import a2s
import time
def check_server(host, port, timeout=5):
try:
info = a2s.info((host, port), timeout=timeout)
return {
"online": True,
"players": info.player_count,
"max_players": info.max_players,
"map": info.map_name,
"latency_ms": round(info.ping * 1000),
}
except Exception:
return {"online": False}
# Poll every 30 seconds
while True:
status = check_server("your-server-ip", 27015)
if not status["online"]:
print("⚠️ Server is DOWN!")
# Send alert via Discord webhook, email, etc.
else:
print(f"✅ {status['players']}/{status['max_players']} players on {status['map']}")
time.sleep(30)
Games That Use A2S on Reactor
The following games hosted on Reactor use the Steam Query Protocol for server browser visibility:
- ARK: Survival Evolved
- ARK: Survival Ascended
- Rust
- Valheim
- Palworld
- Enshrouded
- DayZ
- 7 Days to Die
- V Rising
- SCUM
- Unturned
- Project Zomboid
- Icarus
- Don't Starve Together
- Sons of the Forest
- Arma Reforger
Further Reading
- Valve Developer Wiki — Server Queries
- python-a2s Documentation
- Steam Game Server Account Management
- Reactor Wiki — Server Management
Need help with your game server? Contact us or check our game-specific guides.