Understanding player activity patterns is key to running a successful Minecraft server. When do players log on? Which servers are growing? How does your server compare to others? In this tutorial, we'll build a player analytics dashboard using Chart.js and the Minecraft ServerHub API.
What We're Building
A single-page dashboard that shows:
- Real-time player count for any server
- Historical player trend chart
- Comparison view for multiple servers
- Peak hours analysis
All data comes from the free Minecraft ServerHub REST API, which tracks 5000+ servers and provides historical snapshots.
Project Setup
We'll keep this simple with vanilla HTML and JavaScript. No build tools needed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MC Server Analytics</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: #0f0f0f; color: #e5e5e5; padding: 2rem; }
.card { background: #1a1a1a; border-radius: 12px; padding: 1.5rem; margin-bottom: 1.5rem; }
h1 { font-size: 1.75rem; margin-bottom: 0.5rem; }
.subtitle { color: #888; margin-bottom: 2rem; }
.subtitle a { color: #60a5fa; text-decoration: none; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 1.5rem; }
.stat { text-align: center; }
.stat-value { font-size: 2rem; font-weight: bold; color: #22c55e; }
.stat-label { color: #888; font-size: 0.875rem; }
input { background: #262626; border: 1px solid #333; color: white; padding: 0.5rem 1rem; border-radius: 8px; font-size: 1rem; }
button { background: #22c55e; color: black; border: none; padding: 0.5rem 1.5rem; border-radius: 8px; font-size: 1rem; cursor: pointer; font-weight: 600; }
button:hover { background: #16a34a; }
canvas { max-height: 400px; }
</style>
</head>
<body>
<h1>Minecraft Server Analytics</h1>
<p class="subtitle">
Powered by <a href="https://minecraft-serverhub.com">Minecraft ServerHub</a> |
<a href="https://minecraft-serverhub.com/developers">API Docs</a>
</p>
<div class="card">
<input id="serverInput" type="text" placeholder="Enter server address (e.g. play.hypixel.net)" />
<button onclick="loadServer()">Track</button>
</div>
<div class="grid" id="statsGrid"></div>
<div class="card">
<canvas id="playerChart"></canvas>
</div>
<div class="card">
<canvas id="compareChart"></canvas>
</div>
<script src="app.js"></script>
</body>
</html>
Step 1: Fetching Server Data
The Minecraft ServerHub API provides server status at a simple endpoint. Here's our data layer:
// app.js
const API_BASE = "https://minecraft-serverhub.com/api";
async function fetchServerStatus(address) {
const response = await fetch(API_BASE + "/server/" + address);
if (!response.ok) throw new Error("Server not found");
return response.json();
}
async function fetchServerHistory(address) {
// Fetch historical snapshots for trend analysis
const response = await fetch(API_BASE + "/server/" + address + "/history");
if (!response.ok) return [];
const data = await response.json();
return data.snapshots || [];
}
Step 2: Displaying Real-Time Stats
Create stat cards that show current server metrics:
function renderStats(server, address) {
const grid = document.getElementById("statsGrid");
const stats = [
{ label: "Status", value: server.online ? "ONLINE" : "OFFLINE", color: server.online ? "#22c55e" : "#ef4444" },
{ label: "Players", value: server.online ? server.players.online + "/" + server.players.max : "N/A", color: "#60a5fa" },
{ label: "Version", value: server.version || "Unknown", color: "#a78bfa" },
{ label: "Latency", value: server.online ? server.latency + "ms" : "N/A", color: "#f59e0b" },
];
grid.innerHTML = stats.map(function(s) {
return '<div class="card stat">' +
'<div class="stat-value" style="color:' + s.color + '">' + s.value + '</div>' +
'<div class="stat-label">' + s.label + '</div>' +
'</div>';
}).join("");
}
Step 3: Building the Player Count Chart
This is the core visualization. We use Chart.js to render player count over time:
let playerChart = null;
function renderPlayerChart(history, address) {
const ctx = document.getElementById("playerChart").getContext("2d");
if (playerChart) playerChart.destroy();
const labels = history.map(function(h) {
return new Date(h.timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
});
const playerData = history.map(function(h) {
return h.players ? h.players.online : 0;
});
playerChart = new Chart(ctx, {
type: "line",
data: {
labels: labels,
datasets: [{
label: address + " - Players Online",
data: playerData,
borderColor: "#22c55e",
backgroundColor: "rgba(34, 197, 94, 0.1)",
fill: true,
tension: 0.3,
pointRadius: 2,
}]
},
options: {
responsive: true,
plugins: {
legend: { labels: { color: "#e5e5e5" } },
title: {
display: true,
text: "Player Count Over Time",
color: "#e5e5e5",
font: { size: 16 }
}
},
scales: {
x: { ticks: { color: "#888" }, grid: { color: "#262626" } },
y: { ticks: { color: "#888" }, grid: { color: "#262626" }, beginAtZero: true }
}
}
});
}
Step 4: Server Comparison View
Let server owners compare their player counts against popular servers. We'll track multiple servers on one chart:
let compareChart = null;
const trackedServers = [];
const chartColors = ["#22c55e", "#60a5fa", "#f59e0b", "#ef4444", "#a78bfa"];
async function addToComparison(address) {
if (trackedServers.length >= 5) return;
const status = await fetchServerStatus(address);
trackedServers.push({
address: address,
players: status.online ? status.players.online : 0,
max: status.online ? status.players.max : 0,
});
renderCompareChart();
}
function renderCompareChart() {
const ctx = document.getElementById("compareChart").getContext("2d");
if (compareChart) compareChart.destroy();
compareChart = new Chart(ctx, {
type: "bar",
data: {
labels: trackedServers.map(function(s) { return s.address; }),
datasets: [{
label: "Current Players",
data: trackedServers.map(function(s) { return s.players; }),
backgroundColor: trackedServers.map(function(s, i) { return chartColors[i]; }),
borderRadius: 6,
}, {
label: "Max Capacity",
data: trackedServers.map(function(s) { return s.max; }),
backgroundColor: trackedServers.map(function(s, i) { return chartColors[i] + "33"; }),
borderRadius: 6,
}]
},
options: {
responsive: true,
plugins: {
legend: { labels: { color: "#e5e5e5" } },
title: {
display: true,
text: "Server Comparison",
color: "#e5e5e5",
font: { size: 16 }
}
},
scales: {
x: { ticks: { color: "#888" }, grid: { color: "#262626" } },
y: { ticks: { color: "#888" }, grid: { color: "#262626" }, beginAtZero: true }
}
}
});
}
Step 5: Tying It All Together
The main load function that orchestrates everything:
async function loadServer() {
const input = document.getElementById("serverInput");
const address = input.value.trim();
if (!address) return;
try {
const status = await fetchServerStatus(address);
renderStats(status, address);
const history = await fetchServerHistory(address);
if (history.length > 0) {
renderPlayerChart(history, address);
}
await addToComparison(address);
input.value = "";
} catch (err) {
alert("Could not load server: " + err.message);
}
}
// Load a popular server by default
window.addEventListener("DOMContentLoaded", function() {
document.getElementById("serverInput").value = "play.hypixel.net";
loadServer();
});
Adding Auto-Refresh
Keep the dashboard live with periodic updates:
let currentAddress = null;
setInterval(async function() {
if (!currentAddress) return;
try {
const status = await fetchServerStatus(currentAddress);
renderStats(status, currentAddress);
} catch (e) {
console.error("Refresh failed:", e);
}
}, 60000); // Every 60 seconds
Peak Hours Analysis
One of the most useful analytics features is knowing when player activity peaks. The Minecraft ServerHub statistics page shows ecosystem-wide trends, but you can also calculate this per-server:
function analyzePeakHours(history) {
const hourBuckets = {};
for (let i = 0; i < 24; i++) hourBuckets[i] = [];
history.forEach(function(snapshot) {
const hour = new Date(snapshot.timestamp).getHours();
if (snapshot.players) {
hourBuckets[hour].push(snapshot.players.online);
}
});
const averages = {};
Object.keys(hourBuckets).forEach(function(hour) {
const values = hourBuckets[hour];
if (values.length > 0) {
averages[hour] = Math.round(values.reduce(function(a, b) { return a + b; }, 0) / values.length);
} else {
averages[hour] = 0;
}
});
return averages;
}
This gives server owners actionable data: schedule events during peak hours, plan maintenance during low-activity periods, and understand their player base's timezone distribution.
Discovering Servers to Analyze
Need servers to test with? The Minecraft ServerHub explorer lists 5000+ active servers organized by gamemode, version, and player count. You can find servers across categories:
- Survival servers — The classic gameplay experience
- Creative servers — Building and design communities
- PvP servers — Competitive gameplay
- Minigame servers — Game networks and hubs
Each server page on Minecraft ServerHub already shows player history charts, making it easy to verify your dashboard's data against the platform's own analytics.
Deploying Your Dashboard
Since it's just HTML + JS, deploy anywhere:
# GitHub Pages
git init && git add . && git commit -m "analytics dashboard"
gh repo create mc-analytics --public --source=. --push
# Or use any static host: Vercel, Netlify, Cloudflare Pages
What's Next?
Some ideas for extending the dashboard:
- SQLite storage — Save snapshots locally for long-term trend analysis
- Email alerts — Notify when player count drops below a threshold
- Webhook integrations — Post analytics summaries to Discord
- Export to CSV — Let server owners export their data
- Embeddable widgets — Create iframe-ready components using the badge API
Conclusion
Building analytics tools for Minecraft servers is a great way to learn data visualization while solving a real problem for server communities. The Minecraft ServerHub API makes it easy to get started — no API key needed, just fetch and display.
For production-ready analytics with historical data and trend analysis, visit the Minecraft ServerHub statistics dashboard which already tracks the entire Minecraft server ecosystem.
Built with Minecraft ServerHub — free server monitoring, analytics, and developer tools for Minecraft.
Top comments (0)