source-query-ts
v1.0.0
Published
Ultra-lightweight, zero-dependency, pure TypeScript client for Valve Source Engine Server Queries (A2S) and RCON
Maintainers
Readme
About The Project
Hey! I built this because I needed to query server statuses and run console commands on Source engine servers, and found most existing node libraries (like gamedig) to be unnecessarily heavy, full of dependencies, or difficult to type-check in modern TypeScript projects.
This package is a modern, pure TypeScript implementation of Valve's A2S server query protocol and RCON protocol for Node.js and Bun. It has absolutely zero runtime dependencies.
Why this package is special
- Zero runtime dependencies - Seriously, check the package.json. No third-party network wrappers, no heavy parser utilities.
- Automatic Challenge Handling - Handles the IP-spoofing challenge response protocol seamlessly for A2S_INFO, A2S_PLAYER, and A2S_RULES.
- Split Packet Assembly - Automatically assembles multi-packet UDP responses when query payloads exceed MTU limits.
- Valve RCON Multiplexing - Implements the dummy
SERVERDATA_RESPONSE_VALUEpacket trick to detect end-of-output reliably, even for huge multi-packet responses (verified with 670KB+ payloads). - CS2-compatible RCON - Correctly handles CS2's quirky output routing (responses attributed to the dummy packet id instead of the command id) and uses the proper dummy packet type to avoid triggering empty-command side effects.
- Works everywhere - Supports ESM and CommonJS runtimes, and is fully type-safe in TypeScript.
Installation
npm install source-query-ts
pnpm add source-query-ts
bun add source-query-tsQuick example
1. Server Queries (A2S)
import { A2SClient } from "source-query-ts";
const client = new A2SClient("127.0.0.1:27015");
// 1. Get basic server details
const info = await client.getInfo();
console.log(`Server Name: ${info.name}`);
console.log(`Players: ${info.players}/${info.maxPlayers}`);
console.log(`Map: ${info.map}`);
// 2. Get active player list
const players = await client.getPlayers();
players.forEach((p) => {
console.log(`- [#${p.index}] ${p.name} | Score: ${p.score}`);
});2. Admin Command Execution (RCON)
import { RconClient } from "source-query-ts";
const rcon = new RconClient("127.0.0.1", 27015, "your-secret-password");
try {
await rcon.connect();
console.log("Authenticated!");
const status = await rcon.execute("status");
console.log(status);
} catch (error) {
console.error("RCON command failed:", error);
} finally {
rcon.close();
}API Reference
A2SClient
new A2SClient(host, port?, timeout?)- Initialize a client. Host can be an IP address or a combinedhost:portstring. Default timeout is2000ms.getInfo():Promise<A2SInfo>- Fetch basic server metadata.getPlayers():Promise<A2SPlayer[]>- Fetch players list.getRules():Promise<A2SRule[]>- Fetch server rules/cvars. Note: most CS2 servers don't respond to A2S_RULES (Valve-side regression in Source 2) — expect a timeout on CS2.
RconClient
new RconClient(host, port, password, timeout?)- Initialize an RCON client. Host can be an IP address or a combinedhost:portstring. Default timeout is5000ms.connect():Promise<void>- Connect to the TCP port and perform password authentication.execute(command):Promise<string>- Run a console command and get the fully-assembled response.close():void- Safely disconnect the underlying socket.
For developers
If you want to contribute or build the library locally, please check out the contributing guide.
License
MIT - do whatever you want with it
Credits
Built by K4ryuu
