JoinGG.cc
Features

How Server Lists Actually See Your Server

Server lists send the same query packet a player sends. Learn A2S, Minecraft ping and FiveM HTTP, then fix a listing that shows offline while players connect.

By SweetMask · · 19 min read

A server list has no private channel to your server. It sends the same query packet any player's game client sends and writes down the answer. If your listing shows offline while people are playing, the query path is broken, not the server, and there are four causes that account for nearly all of it.

Published 5 October 2026 · JoinGG · Guides

This is the single most common misunderstanding among people who own a server and are annoyed at a listing. The mental model is that a list has some kind of feed, an API key, an agreement with the game publisher, or a plugin sitting on your box reporting home. None of that exists. A list is a program that opens a socket to your address, sends a few bytes, and records what comes back. When it says nothing came back, nothing came back. Owners looking at the Counter-Strike server list and wondering why their full server reads as empty are almost always looking at a query problem one layer below the thing they are staring at.

A list is just another client, with no special access

Every multiplayer game with a server browser needs a way for a client to ask an unknown address a short question: are you a server, what are you running, how many people are on you, and how full are you. That question is standardized per engine, it is unauthenticated by design, and it predates the idea of a third-party website by about a decade. Server lists use it because it is the only mechanism there is.

Practically, this means a list operates under exactly the constraints your players do. If a player's client cannot see your server in the in-game browser, no list will see it either. If your host's DDoS filter drops unfamiliar UDP, it drops the poller the same way it drops a stranger's client. If you rate-limit queries to protect the main thread, the poller gets rate-limited. There is no allowlist to be added to and no header to send that changes the outcome.

Three consequences follow, and they explain most of the frustration people have with listings:

The whole approach is documented rather than hidden. JoinGG publishes how it collects, on what interval and what it discards in the measurement methodology, and the aggregate output of that process is what fills the site-wide statistics pages. Reading those two together tells you more about why a listing looks the way it does than any amount of guessing.

A2S: the query protocol behind every Valve game

A2S is Valve's query protocol. It runs over UDP, every request begins with the four bytes 0xFF 0xFF 0xFF 0xFF, and it covers Counter-Strike 1.6 through CS2, Team Fortress 2, Garry's Mod, Left 4 Dead 2, Day of Defeat and, by adoption, a long list of non-Valve games including Rust, ARK, 7 Days to Die and Squad. If a game has a Steam server browser, it almost certainly speaks A2S.

The three requests a list actually sends

There are three queries that matter, and most lists send one or two of them:

GoldSrc servers answer A2S_INFO with a different response header and a slightly different field order than Source servers, which is why a library written for CS2 sometimes returns garbage against CS 1.6. It is still the largest population of Source-family servers on the site: around 10,800 players across 1,588 servers, as tracked on the CS 1.6 statistics page.

The challenge that broke half the query libraries in existence

A2S_PLAYERS and A2S_RULES always required a challenge. You send the query, the server replies with header 0x41 and a four-byte challenge number, you resend the query with the challenge appended, and only then do you get data. Two round trips instead of one.

A2S_INFO did not require this, and that was the problem. A 25-byte request produced a 1,200-byte response, a roughly 48-to-1 amplification factor, and because UDP source addresses are trivially spoofed, attackers used unmodified game servers as reflectors: send a small A2S_INFO to ten thousand servers with the victim's address forged as the source, and ten thousand servers deliver a large response to the victim. Valve closed it by extending the challenge requirement to A2S_INFO, so a server now answers an unchallenged info request with a challenge rather than with data.

That change broke a very large number of query implementations at once. Any library that sent A2S_INFO and read the first packet as the answer suddenly received a five-byte challenge packet where a full info response used to be, and reported the server as unreachable or malformed. Server lists that had worked for a decade went dark on Source games overnight. The fix was mechanical, honor the challenge, but a surprising amount of code in the wild still does not, which is why the same server can appear online on one list and offline on another at the same instant. Some of the same class of breakage hit CS2's community servers during its networking transition, described in the notes on the CS2 community server networking update, and it is still worth checking against the current CS2 server list when a CS2 listing behaves strangely.

Rate limits that silently drop a poller

Source servers throttle queries by default. sv_max_queries_sec defaults to 3.0, sv_max_queries_window to 30 seconds, and sv_max_queries_sec_global to 60. Read together, one address may average three queries per second over a rolling thirty-second window, and the server answers at most sixty queries per second in total. Exceed either and your packets are dropped without a reply, which is indistinguishable from the server being down.

This is a sensible defense and you should not turn it off. It does mean that a poller sharing an outbound address with anything else that touches your server, or a list that retries aggressively after a timeout, can throttle itself into looking at a wall. Well-behaved pollers query once, wait, and retry sparingly for exactly this reason.

Minecraft and FiveM answer completely differently

Two of the three largest populations on the site do not speak A2S at all, and their failure modes are entirely different.

Minecraft: Server List Ping over TCP, on the game port

Minecraft Java has no query port in the Valve sense. A list opens a normal TCP connection to the game port, 25565 by default, and performs the same handshake a client performs before showing you the server in its multiplayer menu. It sends a Handshake packet carrying the protocol version, the address and port it dialed, and a next-state field set to 1 for status. The server replies with a JSON document containing the version name and protocol number, a players object with online and max and an optional sample list of names, the MOTD, and a favicon. An optional ping and pong exchange follows to measure latency.

Three things about this trip people up. First, the connection is TCP on the game port, so if your server is joinable your server is queryable, and a Minecraft listing that reads offline usually means a resolution problem rather than a firewall problem. Second, an SRV record matters: if you publish _minecraft._tcp.example.com pointing at a non-default port and a list resolves only the A record, it dials 25565 and finds nothing. Third, if you run BungeeCord or Velocity, the proxy answers the ping itself with its own configured MOTD and its own view of the player count, not the backend's. That is usually what you want, but it means a list is describing the proxy. With 4,230 servers and roughly 56,400 concurrent players tracked on the Minecraft statistics page, proxy setups are common enough that this explains a good share of mismatched listings across the Minecraft server list.

Minecraft also has a separate, older GameSpy-derived query protocol on UDP, enabled with enable-query=true. It returns a fuller player list, but it is off by default, so most lists do not depend on it. Bedrock is a different protocol again: an unconnected RakNet ping on UDP 19132.

FiveM: three HTTP endpoints on the game port

FiveM does not use a binary query protocol. A cfx server runs a small HTTP service on its game port, 30120 by default, and exposes /info.json, /players.json and /dynamic.json. The last is the cheap one and the one lists lean on: it returns the hostname, gametype, mapname, current client count and sv_maxclients in a few hundred bytes. /info.json carries the server version, resource list and the sv_projectName and sv_projectDesc variables. /players.json returns per-player entries with name, ping and identifiers.

The FiveM-specific failure has a name: sv_requestParanoia. Raise it and the server restricts what unauthenticated HTTP requests can see, which is a reasonable privacy choice and an immediate cause of a listing going blank. The related sv_endpointprivacy controls whether player IP addresses appear in /players.json, and you should have that on regardless of what it does to listings. A second common cause is a server.cfg with endpoint_add_udp but no matching endpoint_add_tcp, which leaves gameplay working and the HTTP endpoints unreachable. Artifact updates change the behavior of all of this more often than people expect, which is the subject of the notes on how FiveM artifact updates affect server queries. FiveM remains the largest population tracked here, around 72,600 players across 1,854 servers on the FiveM statistics page, and the servers themselves are browsable on the FiveM server list.

Why the query port is so often not the game port

The phrase "query port" causes more listing failures than any other single concept, because its meaning changes per game and the defaults are inconsistent.

The pattern behind the mess is historical. Valve originally answered queries on the same UDP port as gameplay, which is efficient but couples them: a flood aimed at the query port is a flood aimed at your players. Games that came later split the two so the query listener could be firewalled, rate-limited or moved independently, and every one of them picked a different default offset. Hosts then add their own layer, allocating a block of ports per instance and setting the query port to whatever is free.

The practical rule: never assume. Open your actual start script and read the arguments. If you see -port, +server.port, -queryport, +server.queryport or query.port, those values are the truth and whatever the listing has is a guess. When you submit a server through the server submission form, the port you enter needs to be the one that answers queries, which for Source and Minecraft is usually the game port and for a moved Rust or 7 Days to Die instance usually is not.

Your listing says offline while players are joining

This is the specific complaint that brings most people to this page, and it has a small number of causes. Work through them in this order, because they are sorted by how often they turn out to be the answer.

  1. The query port is firewalled or not forwarded. Players reach the game port and the poller reaches the query port. If those differ and only one is open, you get exactly this symptom. Test from outside your own network, never from the box itself. nmap -sU -p 27015 your.address for a UDP query port, or nc -vz your.address 25565 for Minecraft. If a UDP scan is inconclusive, use a public A2S query tool from a different network.
  1. A rate limit is dropping the poller. Check whether sv_max_queries_sec has been lowered below the default 3.0, and whether your host or DDoS provider applies its own UDP rate limit in front of you. Scrubbing services routinely drop unfamiliar low-volume UDP because it looks like probing, and a single query per hour from an unfamiliar address is the definition of unfamiliar low-volume UDP.
  1. The list's query library does not honor the A2S challenge. If your server answers a manual query fine but two lists disagree about it, this is the likely split. There is nothing to fix on your side; you can confirm it by sending A2S_INFO twice, once without a challenge and once with the challenge the server returns, and noting that only the second attempt yields data.
  1. The address in the listing does not match reality. A changed IP after a host migration, an A record still pointing at the old box, a listing entered with the RCON or SourceTV port, or a hostname with an SRV record the list does not resolve. This is the one to check first if the listing has ever worked and recently stopped.

Two things that are almost never the cause, despite being the first suspects: your server being full, and your server being password protected. A full server still answers A2S_INFO. A password-protected server answers too, and reports its visibility flag honestly. If a listing has gone dark, the packet did not come back at all.

One more that is worth ruling out early: the server actually was down. Restarts, crash loops and out-of-memory kills produce a genuinely unreachable server for a few minutes at a time, and if a poller happens to land in that window it records what it found. A single missed sweep looks identical to a firewall problem from the outside. Continuous availability checks are the way to tell those apart, and the practical setups are covered in the guide to game server monitoring and uptime.

Why the player count on a list lags or disagrees

Assume for this section that queries are working and the listing is live. The number still will not match your console, for reasons that are structural rather than accidental.

Polling interval. A list shows the number your server reported at the last poll. JoinGG polls each listed server once an hour, so a displayed count can be up to an hour old. That is a deliberate trade: a server list covering eleven and a half thousand servers cannot poll every one of them every thirty seconds without becoming a traffic problem for the very servers it is describing, and hourly sampling is enough to characterize a server's population without being enough to track a single join.

Caching between the poll and the page. Pages are usually generated from stored results, not from a live query issued when you load them. Two visitors loading the same listing seconds apart see the same number because they are reading the same stored row.

What the server chooses to count. This is the big one. A2S_INFO carries a player count and a separate bot count, but engines and mods disagree about which humans and which non-humans belong in which field. Some servers include bots in the player count, which makes an empty server look busy. Some report reserved or configured slots rather than occupied ones. Some anti-idle or queue systems hold connecting players in a state that is counted by one field and not the other. Sites that show slot capacity as if it were population are describing a different quantity entirely, and the difference between a server listing you can trust and one you cannot is largely about which of these it discloses, a point developed in the piece on what makes a server listing trustworthy.

Population genuinely moves that fast. Across the whole site the swing between the busiest and quietest measured hours is 242,719 players at Saturday 18:00 UTC against 73,158 at Wednesday 06:00 UTC, a factor of 3.3. An individual server can swing harder than that. A count taken at the top of the hour and a count taken at half past are measuring two different things, and neither is wrong.

What fake player counts look like from the poller's side

Because the server writes the answer, a server can write whatever it likes. Inflating a count is trivial: return a larger number in A2S_INFO, or generate rows in A2S_PLAYERS with plausible names. Plenty of servers do it, and it is more visible from outside than the people doing it seem to believe.

The signatures are mostly statistical rather than clever:

The reason to care is not moral. Inflated counts convert badly. A player who joins expecting 48 people and finds four leaves within a minute, and a server accumulating a reputation for that gets avoided even when it is genuinely busy later. If a server is empty, the productive fix is scheduling a reliable peak window, telling people about it, and being findable, which is the argument made at length in the piece on why nobody joins your server. Faking the number moves your listing up for one afternoon and costs you the returning players who would have made it real.

How JoinGG polls, and what it will not do

Concretely, so you can predict what your listing will do.

Every listed server is queried once an hour over its native protocol. A2S for Source and GoldSrc games and for the non-Valve titles that adopted it, Server List Ping for Minecraft Java, HTTP for FiveM. There is no universal poller and no shortcut: a game gets supported when its actual protocol gets implemented. That is why the catalogue holds 147 games while only 31 currently have servers listed against them.

The current sweep covers 11,561 listed servers, of which roughly 10,700 answer in any given hour. The gap, a little over 800 servers or about 7 percent, is the normal background of restarts, wipes, expired hosting, seasonal servers and boxes that have quietly gone away. It is not an error rate to be engineered down to zero; a healthy list always has some fraction of entries mid-restart, and a list reporting 100 percent response is a list that is repeating old numbers.

What happens when a server does not answer is the part worth knowing. It contributes nothing to that hour. It does not carry its previous count forward, it is not counted as zero players in a way that drags an average down, and it is not deleted. It simply has no data point for that hour, and it reappears with a real number the moment it answers again. This matters for anyone reading the aggregate trends: a dip in a game's total is a dip in players who were actually observed, never an artifact of servers being marked down.

Results are kept for seven days. That window is long enough to show a weekly cycle, which is the cycle that actually governs game server population, and short enough that nothing on the site is describing a server as it was a month ago. Peak and trough figures such as the Saturday evening high and the Wednesday morning low come out of that seven-day window rather than from a longer archive.

And the negative space: no credentials are ever requested, no software is installed on your machine, no plugin is required, and no data is collected beyond what your server publishes to any client that asks. If you want to see the whole thing rather than one game's slice, the full server list is the same data set the statistics pages summarize, drawn from the same hourly sweep.

Frequently asked questions

Why does my server show offline on a list when players can join?

Because joining and being queried use different ports and sometimes different protocols. Players reach the game port; the list reaches the query port. A firewall rule covering only the game port, a query rate limit dropping the poller, or a query library that does not answer the A2S challenge will all produce a full server that reads as offline.

What is the query port and how do I find mine?

It is the port your server answers status requests on, which is often but not always the game port. Source games default to the game port over UDP. Minecraft Java answers on the game port over TCP. FiveM answers over HTTP on 30120. Rust and several survival games move it. Check your start script for a queryport argument before assuming.

Why is the player count on the list different from the count in my server console?

Polling interval and caching. A list shows the number your server reported at the last poll, not the number right now. JoinGG polls each listed server once an hour, so a count can be up to an hour old. Servers that report configured slots or count bots rather than humans widen the gap further.

Does a server list need my RCON password or FTP details?

No. Every figure on a list comes from the same public query packet a player's client sends before showing you a server in the in-game browser. No credentials are involved, nothing is installed on your machine, and no plugin is required. Anything asking for RCON or FTP access to list your server is asking for something it does not need.

Can I make my server report a higher player count?

You can, and it is visible from the poller's side. Inflated counts produce patterns real servers do not have: a count that never moves, a number that exceeds the slot limit, or a player list whose entries all report identical connection times. The traffic that arrives from an inflated listing also leaves immediately, which costs you more than the placement gains.

How often should a list re-check a server before dropping it?

Long enough to survive a restart, short enough that dead servers do not linger. JoinGG polls hourly and keeps seven days of history. A server that misses a sweep contributes nothing to that hour rather than repeating its last known number, and it reappears on its own as soon as it answers again.

The useful shift in perspective is this: stop treating your listing as something a website decides about you, and start treating it as a readout of one specific packet exchange. When it is wrong, the exchange is what to test. Send the query yourself from an address that is not your own, read the raw response, and compare it to what the listing shows. In almost every case the listing turns out to be reporting accurately what your server told it, and the work is upstream, on the port, the firewall or the config value that is answering for you.

Once the query path is clean the rest takes care of itself: a server that answers gets polled, and a server that gets polled gets found. If yours is not listed yet, submit it with the correct query port and it will be swept on the next hourly pass.

JoinGG lists 11,561 game servers across 31 games with servers currently online, with roughly 10,700 answering any given hourly sweep and seven days of results retained. Figures in this article reflect measurements taken on 9 September 2026.

a2s queryserver listquery portminecraft server list pingfivem info.jsonplayer count accuracy

More