Skip to content
uolist

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:

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:

JSON response shape
{ "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)

uolist-status.js
// 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.

uolist-status.php
<?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.

crontab -e
# 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.json

Opt 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.