npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

queryhost

v1.2.1

Published

Fast, typed game server queries for TypeScript.

Readme

QueryHost

Fast, typed game server queries for TypeScript.

QueryHost is a game-server query engine with correct protocols, explicit source provenance, bounded network behavior, and game-specific TypeScript results.

Status

The current source tree contains the package foundation and supported profiles:

  • typed public result contracts and an exhaustive game registry
  • global deadlines, a shared outbound-attempt budget, cancellation, cleanup, and stable internal errors
  • hostname and port validation, cancellable bounded DNS/SRV resolution, public-address policy, and immutable address pinning
  • bounded UDP exchanges with peer validation, packet limits, cancellation, and deterministic socket cleanup
  • A2S Info request encoding, bounded challenge handling, and strict Source and GoldSource parsing
  • bounded Source and GoldSource split-packet reconstruction with bzip2, size, and checksum validation
  • strict A2S Player and Rules parsing with bounded one-retry challenge flows
  • concurrent optional A2S enrichment with per-source success, timeout, malformed, blocked, unsupported, skipped, and transport-failure provenance
  • the public query() entry point and complete Rust, Don't Starve Together, Palworld, Project Zomboid, 7 Days to Die, DayZ, and Steam-backend Valheim profiles over bounded A2S sources
  • a generic A2S profile for Source and GoldSource servers with an explicit query port
  • bounded TCP exchanges with pinned destinations, response framing, cancellation, byte limits, and deterministic cleanup
  • Minecraft Java Server List Ping with strict VarInts, packet framing, bounded JSON, normalized MOTDs, validated favicons, player counts, protocol versions, and query latency
  • deterministic Minecraft SRV discovery and optional same-socket UDP Query enrichment for maps, software, plugins, and player names
  • Minecraft Bedrock RakNet status with strict identifiers, bounded UTF-8 fields, advertised ports, and spoofed-peer filtering
  • fixed-path HTTP over pinned addresses with preserved Host/SNI identity, redirect refusal, and bounded bodies
  • concurrent FiveM and RedM info.json, dynamic.json, and players.json queries with explicit partial and blocked-source semantics
  • Satisfactory lightweight UDP status with optional authentication-free HTTPS health enrichment
  • direct Vintage Story TCP queries with stock-server liveness detection and typed richer status responses
  • bounded property tests, generated API references, reviewed package boundaries, and clean JavaScript and TypeScript consumer smoke tests

The 1.0.0 release establishes the reviewed package-root contract. QueryHost follows semantic versioning for changes to that contract.

Installation

npm install queryhost

Public contract

The generated API reference, packaged examples, changelog, and release-readiness review document the intended package boundary.

Literal game IDs remain connected to their game-specific data types:

import { query } from "queryhost";

const result = await query({
  game: "rust",
  host: "play.example.com",
  port: 28015,
});

if (result.ok) {
  console.log(result.server.name);
  console.log(result.data.tags); // RustData
  console.log(result.sources);
}

QueryResult is a discriminated union. Check ok before reading data or error. A dynamic GameId can be narrowed with an exhaustive switch on result.game.

Implemented A2S profiles default to mode: "full": Info is required, then supported optional sources run concurrently against the same pinned address. Use mode: "summary" to request only Info; skipped optional sources remain visible as not-requested.

Use game: "a2s" for an otherwise unsupported Source or GoldSource server. Generic A2S has no default port: port is required and means the server's actual A2S query port. It returns common Info facts and Player data under data, with unchanged Rules under rawData.rules.

Palworld uses its public Steam A2S listener for unauthenticated status queries. Info supplies the normalized summary; Player and Rules are conditional because deployments do not consistently expose them. This profile does not call Pocketpair's separate authenticated REST API, so REST-only player details and server settings are not represented as A2S data.

Don't Starve Together uses the Steam A2S service exposed by each shard, not its gameplay socket or Klei's lobby HTTP service. port is the gameplay port (default 10999); the independent Steam query port defaults to 27016 and can be changed with queryPort. A query describes only the shard that owns that Steam port. QueryHost does not discover sibling shards or combine a cluster, and a Klei lobby listing's gameplay port does not reveal a custom Steam query port.

Valheim queries its direct Steam-backend A2S endpoint. The default game port is UDP 2456 and the query destination is UDP 2457; custom game ports preserve that +1 convention. Info provides the world, build, password state, and counts. Full mode also requests Player records, whose names Valheim commonly leaves empty, while Rules is reported as unsupported without network work. Successful data carries backend: "steam". Servers launched with -crossplay use PlayFab relay discovery and cannot be queried through this direct A2S profile.

Minecraft Java performs optional SRV discovery followed by one required Server List Ping over TCP. In full mode it also attempts optional UDP Query enrichment for the map, software, plugins, and player names. Query failure preserves the successful SLP result as partial; summary mode skips Query explicitly.

Minecraft Bedrock sends one required RakNet unconnected ping to UDP 19132 by default. Its pong supplies the normalized name, version, player counts, and Bedrock-specific edition, protocol, game mode, server ID, and advertised IPv4/IPv6 ports. Advertised ports are reported as server data; QueryHost does not follow them or connect to a new destination.

FiveM and RedM use the shared Cfx FXServer HTTP endpoint family on port 30120 by default. In full mode, their fixed info.json, dynamic.json, and players.json endpoints run concurrently against one pinned address. Any usable endpoint can identify a live server; unavailable endpoints remain omitted and produce game-specific partial provenance. summary mode requests only dynamic.json. Redirects are never followed, and blocked Nope responses are reported as blocked rather than empty data.

Vintage Story uses its normal TCP game port, 42420 by default. Current stock servers acknowledge the direct status request without disclosing metadata, producing data.response: "liveness"; compatible servers may return the protocol's richer status answer with name, MOTD, player counts, mode, password state, and version. QueryHost connects only to the caller's validated, pinned target and does not consult the public server list or another central service.

Satisfactory uses the dedicated server's shared UDP/TCP game port, 7777 by default. Its lightweight UDP API is the required status source and returns the server name, lifecycle state, network changelist, modded flag, and substate revisions without authentication. Full mode additionally calls the authentication-free HTTPS HealthCheck; summary mode and the documented loading state skip HTTPS. Vanilla servers generate self-signed certificates by default, so this narrowly scoped request disables certificate identity validation while retaining TLS encryption and the validated pinned destination. QueryHost never attempts password login, requests an API token, or calls authenticated management functions.

port is the game's normal connection port. Rust follows its conventional two-port offset, so game port 28015 queries A2S on 28017. Palworld uses game port 8211 and a fixed conventional Steam query port of 27015; changing the game port does not shift that query default. DayZ uses game port 2302 and Steam query port 2305 by convention; a custom game port preserves the +3 offset. Don't Starve Together keeps its independently configured query port at 27016 even when port changes. Project Zomboid uses UDP 16261 and 7 Days to Die uses UDP 26900 for both the registry default and A2S destination. An explicit queryPort always takes precedence for custom layouts.

Minecraft Java looks up _minecraft._tcp.<host> only when host is a DNS name and port is omitted. Valid SRV targets are tried by ascending priority and RFC-weighted order; no record falls back to the original host on port 25565. Supplying port or an IP literal bypasses SRV. queryPort changes only the optional UDP Query destination and does not replace the SLP game port.

Game inputs accept documented aliases while results always use the canonical ID. minecraft and mc resolve to Java Edition; Bedrock remains explicit.

| Canonical ID | Accepted aliases | | ---------------------- | ------------------------------------------------------------ | | a2s | — | | rust | — | | palworld | — | | project-zomboid | projectzomboid, zomboid, pz | | 7-days-to-die | seven-days-to-die, 7days-to-die, 7d2d, 7dtd | | dayz | — | | valheim | — | | minecraft-java | minecraft, mc, java, minecraft-java-edition | | minecraft-bedrock | bedrock, mcbe, mc-bedrock, minecraft-bedrock-edition | | fivem | five-m | | redm | red-m, rdr3 | | satisfactory | — | | vintage-story | vintagestory, vs | | dont-starve-together | dst, dontstarvetogether |

Project Zomboid interprets its description, PvP state, game version, and semicolon-delimited mod IDs from Rules. Its game-specific Rules version takes precedence over the generic A2S Info version. 7 Days to Die interprets its description, game name, world, mode, server clock, and website.

DayZ uses required A2S Info and optional A2S Rules. It exposes ordered Info keywords plus validated direct Rules fields such as terrain, platform, dedicated state, connection port, and build/version values. Its bounded DayZ decoder also reassembles escaped server-browser metadata pages into a description, Steam Workshop mods, and signing-key names. Direct string-valued Rules remain available under rawData.rules; binary page records are represented by their typed decoded values instead of lossy strings. Malformed or undocumented values remain raw instead of being guessed. DayZ's A2S Player response is intentionally unsupported: Info still supplies confirmed aggregate player counts, but the profile does not present anonymous or malformed Player records as identities. DayZ's official server configuration documents its separately configured game and Steam query ports, while the official server-browser source keeps both destinations distinct.

Every named A2S profile exposes confirmed string Rules unchanged under rawData.rules, separate from normalized data; all rule-derived values and rawData remain omitted when Rules is unavailable.

Command-line queries

For quick real-server testing from this repository:

npm run query -- rust play.example.com 28015

The installed package also provides the same command as queryhost. It writes the complete parsed QueryResult as formatted JSON and exits with 0 for success, 1 for a query failure, or 2 for invalid command arguments.

queryhost a2s play.example.com 27015
queryhost dayz play.example.com 2302 --mode full
queryhost dst play.example.com 10999 --query-port 27016
queryhost rust play.example.com 28015 --mode full --timeout 3000
queryhost palworld play.example.com 8211 --mode full
queryhost rust play.example.com --query-port 28017 --mode summary
queryhost project-zomboid play.example.com 16261
queryhost 7-days-to-die play.example.com 26900
queryhost 7dtd play.example.com 26900
queryhost valheim play.example.com 2456
queryhost mc play.example.com 25565
queryhost mcbe play.example.com 19132
queryhost fivem play.example.com 30120
queryhost redm play.example.com 30120
queryhost satisfactory play.example.com 7777
queryhost vs play.example.com 42420

Run npm run query -- --help or queryhost --help for the complete option list. The command uses the library's normal target policy, so private, loopback, link-local, reserved, and other non-public destinations remain blocked.

Data semantics

Optional values are omitted when the server or source cannot confirm them. QueryHost does not convert unavailable data into false, zero, or an empty collection.

A required-source failure produces ok: false. When a required source succeeds and optional enrichment fails, the result remains successful with partial: true, source provenance, and stable warnings.

server.queryRttMs measures the primary query exchange. durationMs measures the complete operation, including discovery and optional sources. See Internal architecture for the full result invariants.

Registry

Registry metadata is available from the same package so applications, the hosted API, and documentation can share one source of truth:

import { GAME_REGISTRY, isGameId } from "queryhost";

GAME_REGISTRY["minecraft-java"].defaultPort; // 25565
isGameId("rust"); // true

The registry is exhaustive over GameId. Adding a game requires a typed data model and registry definition; consumers should not maintain a second game list.

Infrastructure boundary

This package is a standalone Node.js library with no Cloudflare or Railway dependencies. Every query() call performs live network work unless the caller adds caching. The separate hosted API runs the package as a portable Node.js service on Railway behind Cloudflare.

Safety model

Queries use one global deadline, propagated cancellation, a shared 16-attempt outbound-work budget, and deterministic cleanup. Production DNS uses one resolver per query, cancels its native work with the query, and settles immediately when the caller aborts or the deadline expires. Untrusted targets pass through hostname and port validation, DNS/SRV answer caps, public-address policy, and immutable address pinning before a transport can connect. The same policy applies to SRV-derived targets.

Requirements

  • Node.js 24 or newer
  • npm 12

Development

npm install
npm run verify

npm run verify checks formatting, linting, runtime and property tests, generated API docs, type tests, the production build, dependency licenses, package size and contents, public exports, and packed JavaScript and TypeScript consumers.

The codebase uses the native TypeScript 7 compiler across library code, runtime tests, and type tests. Oxlint provides type-aware linting through its Go backend, while TypeDoc uses the TypeScript 6 compatibility package until the native compiler exposes a stable tooling API. Explicit any and unknown types are forbidden; boundary data must be validated into a concrete type before it enters the library.

Package layout

src/       Public contracts and internal library implementation
test/      Runtime tests
test-d/    Published TypeScript contract tests
docs/      Maintainer-facing technical documentation

Detailed module ownership, invariants, and extension rules live in Internal architecture.

License

Apache-2.0