Steam Master and Game Server Query
This package provides a promise-based Node.js module for programmatically interacting with Steam's Master Server Query Protocol and Game Server Queries. It enables developers to fetch lists of active game servers from a Steam master server, supporting extensive filtering by region and various server properties (e.g., game directory, map, player count, appid). Additionally, it fully supports querying individual game servers for detailed information via A2S_INFO (server name, map, players), A2S_PLAYER (player list with scores and duration), and A2S_RULES (server-specific rules and values). The current stable version is 1.1.3, with recent releases focusing on improved socket stability, enhanced retry mechanisms for queries, and options to mitigate rate limiting during master server lookups. It ships with comprehensive TypeScript type definitions, ensuring robust usage in modern JavaScript and TypeScript environments. Its primary differentiator is its complete implementation of both Master and Game Server Query protocols with a resilient, promise-based API.
Common errors
-
Error: Request timed out
cause The queried game or master server did not respond within the specified timeout duration, or the server is offline/unreachable.fixIncrease the `timeout` parameter for the query function. Verify the `gameServer` address and port are correct and that the server is online and accessible from your network. Check firewall rules. -
TypeError: queryMasterServer is not a function
cause This typically occurs in CommonJS environments (Node.js without type: 'module' in package.json) when trying to use ES module `import` syntax or an incorrect `require` pattern.fixFor CommonJS, use `const { queryMasterServer, REGIONS } = require('steam-server-query');`. Ensure your project's `package.json` is not explicitly set to `"type": "module"` if you intend to use `require`. -
Error: Address already in use
cause This error can occur when a UDP socket tries to bind to a port that is still in use, often due to improper socket closure in previous operations.fixThis issue was largely resolved in `steam-server-query@1.1.1`. Ensure you are on version `1.1.1` or higher. If the problem persists, it may indicate another application is using the port, or a very rapid succession of queries without allowing the OS to release the port.
Warnings
- gotcha Older versions of the library (prior to v1.1.1) had issues with UDP sockets not closing correctly after a request, leading to potential resource leaks or 'address already in use' errors. This was resolved in v1.1.1.
- gotcha Master server queries can be rate-limited by Valve's servers if too many requests are made in a short period. The `maxHosts` option was introduced to help mitigate this by limiting the number of hosts returned.
- gotcha A2S_PLAYER requests may sometimes require multiple attempts or 'challenge retries' due to the protocol specifics, which could lead to initial failures. This was addressed with an internal fix in v1.1.3.
- gotcha Game server query functions (`queryGameServerInfo`, `queryGameServerPlayer`, `queryGameServerRules`) expect the `gameServer` argument in `host:port` format. Providing just a hostname or an IP without a port will result in connection failures.
Install
-
npm install steam-server-query -
yarn add steam-server-query -
pnpm add steam-server-query
Imports
- queryMasterServer
const { queryMasterServer } = require('steam-server-query');import { queryMasterServer } from 'steam-server-query'; - queryGameServerInfo
import queryGameServerInfo from 'steam-server-query';
import { queryGameServerInfo } from 'steam-server-query'; - REGIONS
import * as REGIONS from 'steam-server-query';
import { REGIONS } from 'steam-server-query'; - Filter
import type { Filter } from 'steam-server-query';
Quickstart
import { queryMasterServer, queryGameServerInfo, queryGameServerPlayer, REGIONS } from 'steam-server-query';
async function runQuery() {
try {
console.log('Querying master server for all regions...');
const masterServers = [
'hl2master.steampowered.com:27011',
'hl2master.steampowered.com:27012'
];
const gameServers = await queryMasterServer(masterServers[0], REGIONS.ALL, {
appid: 440, // Team Fortress 2
gamedir: 'tf',
empty: 1
}, 2000, 5); // Timeout 2s, max 5 hosts
if (gameServers.length === 0) {
console.log('No game servers found matching criteria.');
return;
}
console.log(`Found ${gameServers.length} game servers. Querying the first one: ${gameServers[0]}`);
const serverInfo = await queryGameServerInfo(gameServers[0]);
console.log('\n--- Server Info ---');
console.log(`Name: ${serverInfo.name}`);
console.log(`Map: ${serverInfo.map}`);
console.log(`Players: ${serverInfo.players}/${serverInfo.maxPlayers}`);
console.log(`Game: ${serverInfo.game}`);
const playerInfo = await queryGameServerPlayer(gameServers[0]);
console.log('\n--- Player Info ---');
playerInfo.players.forEach(player => {
console.log(`- ${player.name} (Score: ${player.score}, Duration: ${player.duration.toFixed(2)}s)`);
});
// Example of handling potential errors or missing player data
if (playerInfo.players.length === 0) {
console.log('No players found on this server.');
}
} catch (error) {
console.error('An error occurred during the query:', error.message);
if (error.code === 'ETIMEDOUT') {
console.error('The server query timed out. The server might be offline or unreachable.');
}
}
}
runQuery();