Powerful command-line utility and Go toolkit for working with Steam A2S game servers. Query server information, players, and rules; build A2S servers and cached UDP proxies; and handle Arma 3 and DayZ Server Browser Protocol responses.
- Source and GoldSource Server Queries:
A2S_INFO,A2S_PLAYER, andA2S_RULES. - Source and GoldSource split responses, including reordered fragments; Source bzip2-compressed payloads.
- A2S challenge exchanges and the legacy-compatible
A2S_SERVERQUERY_GETCHALLENGEandA2A_PINGrequests exposed by the Go API. - Arma 3 and DayZ Server Browser Protocol (A3SB) responses
carried by
A2S_RULES, with automatic detection, explicit layouts and native A2S fallback.
cmd/a2s: CLI for queries, diagnostics and cached proxy operation;pkg/a2s: context-aware A2S client and standard response codecs;pkg/a2s/pool: bounded concurrent queries over reusable UDP worker sockets;pkg/a2s/transport: public low-level wire types, framing codecs, and transaction contracts;pkg/a2s/server: transport-independent A2S server contracts and UDP runtime with challenges, middleware, state, and packetization;pkg/a2s/proxy: reusable response cache, polling, relay, and rate-limiting components;pkg/a3sb: typed Arma 3 and DayZ Server Browser Protocol parser and codec;pkg/keywords: typed parsers for Arma 3 and DayZA2S_INFOkeywords;pkg/appid: curated Steam AppID registry for A2S-compatible games.
go get github.com/woozymasta/a2sDownload the latest CLI release for your platform:
| Arch/OS | macOS | Linux | Windows |
|---|---|---|---|
| AMD64 | a2s-darwin-amd64 | a2s-linux-amd64 | a2s-windows-amd64 |
| ARM64 | a2s-darwin-arm64 | a2s-linux-arm64 | a2s-windows-arm64 |
Or install with go toolchain:
go install github.com/woozymasta/a2s/cmd/a2sDownload the latest release with curl in Bash:
case "$(uname -s)" in
Linux*) OS=linux;;
Darwin*) OS=darwin;;
MINGW*|MSYS*|CYGWIN*) OS=windows; EXT=.exe;;
*) exit 1;;
esac
case "$(uname -m)" in
x86_64|amd64) ARCH=amd64;;
aarch64|arm64) ARCH=arm64;;
*) exit 1;;
esac
BIN="./a2s$EXT"
curl -#SfLo "$BIN" \
"https://github.com/WoozyMasta/a2s/releases/latest/download/a2s-$OS-$ARCH$EXT"
chmod +x "$BIN"
"$BIN" -h && "$BIN" -vPrebuilt images are available from GitHub Container Registry and Docker Hub:
ghcr.io/woozymasta/a2s:latestdocker.io/woozymasta/a2s:latest
Example using a container image:
docker pull ghcr.io/woozymasta/a2s:latest
docker run --rm -ti \
-e A2S_TIMEOUT=3s \
-e A2S_BUFFER_SIZE=8192 \
ghcr.io/woozymasta/a2s:latest info host:portThe CLI queries A2S servers, formats responses, and runs a cached proxy. See the CLI reference for all commands, options, defaults, environment variables, and generated examples.
info: query server metadata;players: list current players;rules: query native A2S or A3SB rules;all: query metadata, rules, and players together;ping: measure repeated query response times;proxy: expose a cached UDP endpoint for an upstream server.
# Query server metadata.
a2s info 127.0.0.1:27015
# Export all responses as one JSON document.
a2s all 127.0.0.1:27015 --format json | jq
# Parse Arma 3 server-browser rules explicitly.
a2s rules 127.0.0.1:2303 --game arma3
# Print only ping values for five queries.
a2s ping 127.0.0.1:27015 --ping-count 5 --compact
# Cache an upstream server on a local UDP endpoint.
a2s proxy 127.0.0.1:27015 --listen :27016The Go packages cover both sides of the protocol: querying existing servers and serving or proxying A2S responses. For the complete public API, see the Go module documentation. The examples below show the main building blocks.
Use pkg/a2s for standard server queries.
ctx := context.Background()
client, err := a2s.New("127.0.0.1", 27015, a2s.WithTimeout(3*time.Second))
if err != nil {
panic(err)
}
defer client.Close()
info, err := client.GetInfo(ctx)
if err != nil {
panic(err)
}
_ = infoWrap an existing a2s.Client with pkg/a3sb
for Arma 3 and DayZ rules:
a3sClient := &a3sb.Client{Client: client}
rules, err := a3sClient.GetRules(ctx, 0) // Automatic classification.
if err != nil {
panic(err)
}
_ = rules
// Explicit layout: a3sClient.GetRules(ctx, appid.DayZ)Use pkg/a2s/pool when querying many targets.
The pool bounds concurrency and reuses worker-owned UDP sockets;
one worker runs one complete A2S transaction at a time.
queryPool, err := pool.New(
pool.WithWorkers(8),
pool.WithQueueSize(64),
pool.WithTimeout(3*time.Second),
)
if err != nil {
panic(err)
}
defer queryPool.Close()
requests := make(chan pool.Request, len(targets))
for _, target := range targets {
requests <- pool.Request{
Target: target, // resolved netip.AddrPort
Query: transport.InfoRequest,
}
}
close(requests)
for result := range queryPool.Stream(ctx, requests) {
if result.Err != nil {
continue
}
// Results arrive in completion order; result.Index is submission order.
_ = result.Packet
}Use Bind when a target starts as host:port:
DNS is resolved once and is not repeated by subsequent Endpoint.Query calls.
A bound endpoint also implements upstream contract expected by proxy package.
Use pkg/a2s/server to publish your own server data:
implement a Handler and pass it to server.New.
The server handles UDP transport, challenge validation,
and response packetization.
handler := server.HandlerFunc(func(
_ context.Context,
request *server.Request,
) (server.Response, error) {
if request.Query.Type != transport.InfoRequest {
return nil, server.ErrDrop
}
return server.InfoResponse{Info: a2s.Info{
Format: a2s.InfoFormat(transport.ResponseInfo),
Name: "Example A2S server",
}}, nil
})
srv, err := server.New(handler)
if err != nil {
panic(err)
}
conn, err := net.ListenPacket("udp", ":27015")
if err != nil {
panic(err)
}
defer conn.Close()
go srv.Serve(conn)
defer srv.Shutdown(context.Background())Use pkg/a2s/proxy with pkg/a2s/server
to serve cached responses and relay uncached queries.
Use a Poller to refresh selected cache entries from the upstream client.
cache, _ := proxy.NewCache([]transport.QueryType{
transport.InfoRequest, transport.RulesRequest,
})
handler, _ := proxy.NewHandler(cache, upstream, proxy.HandlerConfig{
ChallengeProvider: provider,
LocalPing: true,
})
srv, _ := server.New(handler, server.WithChallengeProvider(provider))Run a Poller to refresh the cache and serve srv on a UDP PacketConn.
For a deeper understanding of the protocols used, refer to the official documentation:
During development, the functionality of a2s was thoroughly tested
across a diverse range of popular games
that utilize the Steam server query protocols.
The implementation has been tested against servers from these games:
- Counter-Strike 1.6
- Counter-Strike: Source
- Team Fortress 2
- Project Zomboid
- Valheim
- Rust
- Garry's Mod
- Insurgency
- Arma 3
- DayZ
- 7 Days to Die
- ARK: Survival Evolved
- Conan Exiles
- Unturned
๐ Support Me
Your support is greatly appreciated!