About uolist
uolist.com is a community directory and ranking site for Ultima Online private shards (free shards). We list every era — T2A, UOR, AoS, SA, custom — and every emulator: RunUO, ServUO, ModernUO, POL, Sphere, and bespoke code.
How rankings work
Every Monday at 00:00 UTC the vote tally resets. One vote per shard per voter per week. We identify voters by a salted hash of IP + a persistent cookie — no login required, but obvious abuse gets squashed.
Shard probe policy
We mark each listed shard as online or offline so players can see at a glance what's up. Here's exactly what we do, so shard operators know:
- TCP connect only. A single bare TCP open and immediate close against the listed game port. We send no UO protocol bytes — nothing for your emulator to log as a malformed login attempt.
- Probe interval: ~5 minutes when a shard is responsive.
- Exponential backoff on failure. 1st failure → 5 min wait. 2nd → 10 min. 3rd → 20 min. Continues doubling to a cap of 60 minutes. We do not hammer dead shards.
- Concurrency cap of 4 probes in flight at once, with 100–600ms jitter between probes within a sweep.
- Source IP is whatever uolist.com resolves to.
Owner-provided status endpoint (recommended)
Shard owners can opt into a JSON status endpoint we'll hit instead of TCP probing. This avoids any traffic against your game port and lets you report a live player count.
Add the URL when submitting (or email us to update an existing listing). The endpoint should respond with this exact shape — anything else is rejected:
{ "online": true, "players": 142 }online is required (boolean). players is optional (non-negative integer). Response must be application/json, must be served over HTTPS, and must be ≤ 10 KB. We send User-Agent: uolist-status-probe/1.0 and follow no redirects, so identify and rate-limit us however you want.
Sample implementations
Each example assumes you already have a way to read your shard's live player count — a SQL query against your emulator's DB, a stats file the emulator writes, a TCP query to the shard's admin port, whatever. The examples just put that value behind a public URL.
Node.js (Express)
// npm i express
const express = require("express");
const app = express();
// Adapt this — read player count from your shard however you can.
async function getStatus() {
// e.g. query your DB, read a file your shard writes, etc.
return { online: true, players: 0 };
}
app.get("/uolist-status.json", async (_req, res) => {
try {
const { online, players } = await getStatus();
res.set("Cache-Control", "public, max-age=30");
res.json({ online, players });
} catch {
res.status(503).json({ online: false });
}
});
app.listen(8080);PHP
Drop on any PHP host. This example reads a plaintext players.txt that your emulator writes once a minute — adapt to your own source.
<?php
header("Content-Type: application/json");
header("Cache-Control: public, max-age=30");
$file = __DIR__ . "/players.txt";
if (!is_readable($file)) {
echo json_encode(["online" => false]);
exit;
}
$count = (int) trim(file_get_contents($file));
echo json_encode(["online" => true, "players" => $count]);Static JSON via cron (no app server needed)
Simplest path if you already serve static files from nginx/Apache: regenerate uolist-status.json on a cron. Replace your-stats-script with whatever prints your player count to stdout.
# Refresh every minute.
* * * * * printf '{"online":true,"players":%d}' "$(your-stats-script)" \
> /var/www/html/uolist-status.json.tmp \
&& mv /var/www/html/uolist-status.json.tmp /var/www/html/uolist-status.jsonOpt out
If you operate a shard listed here and don't want us probing or listing it, email us at the contact address on your shard's detail page and we'll remove it within 24 hours. We respect robots.txt on the JSON endpoint URL.
List your shard
Owners can submit their shard for inclusion. Submissions go through a short moderation queue.