Compatibility
Minecraft: Java Edition
Platforms
Tags
Creators
Details
Statfyr
A blazing-fast REST API for Minecraft player statistics
Statfyr is a lightweight Paper plugin that exposes your server's player statistics through a clean, documented REST API. Dashboards, bots, leaderboard websites, Discord integrations โ build anything, in any language, against a single HTTP endpoint.
โจ Features
- ๐ Full stat access โ playtime, kills, deaths, blocks mined, items crafted, movement, and more
- ๐ Leaderboards โ ranked endpoints for playtime, kills, deaths, mined, and crafted
- โก Async loading โ stats are fetched off the main thread, zero TPS impact
- ๐๏ธ gzip compression โ optional response compression for bandwidth efficiency
- ๐ Bearer authentication โ lock your API behind a secret key
- ๐ก๏ธ Rate limiting โ per-IP request throttling out of the box
- ๐ CORS support โ configurable allowed origins for browser-based clients
- ๐ IP whitelist โ restrict access to specific trusted addresses
- ๐ HTTPS / SSL โ optional TLS via Java keystore
- ๐ Built-in API docs โ browsable documentation at
/api/docs - ๐งฉ Pagination & sorting โ standard
limit,page, andorderparams across all list endpoints - โ๏ธ Response caching โ configurable TTL to reduce repeated stat lookups
๐ Requirements
| Requirement | Version |
|---|---|
| Java | 16+ |
| Paper/Spigot | 1.16.5+ |
๐ Installation
- Download the latest
.jarfrom the Releases tab - Drop it into your server's
/plugins/folder - Start (or restart) your server
- Edit
plugins/statfyr/config.ymlto your liking - Use
/statfyr reloadto apply changes without a full restart
The API will be live at http://your-server-ip:8080/api by default.
๐ API Overview
All responses are JSON. The base URL for all endpoints is:
http://your-server:8080/api
Endpoints at a Glance
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/health |
Server health and version info |
GET |
/api/players |
List all known players |
GET |
/api/player/{player} |
Full stats for a player (UUID or name) |
GET |
/api/player/{player}/summary |
Lightweight summarized stats |
GET |
/api/leaderboard/{type} |
Ranked leaderboard |
Leaderboard Types
playtime ยท kills ยท deaths ยท mined ยท crafted
๐ Usage Examples
Get all online players:
GET /api/players?online_only=true&limit=25
Get a player's full stats, filtered to mined and crafted categories:
GET /api/player/Steve?summary=true&categories=mined,crafted
Get the top 10 playtime leaderboard:
GET /api/leaderboard/playtime?limit=10&order=desc
Authenticated request:
GET /api/players
Authorization: Bearer your-secret-key
Example Response โ Player Summary
{
"uuid": "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"name": "Alex",
"online": false,
"playtime_ticks": 125,
"playtime_seconds": 6,
"playtime_formatted": "6s",
"combat": {
"deaths": 0,
"player_kills": 0,
"mob_kills": 0,
"damage_dealt": 0,
"damage_taken": 0
},
"movement": {
"distance_walked_cm": 0,
"distance_walked_m": 0,
"distance_sprinted_cm": 0,
"distance_sprinted_m": 0,
"distance_flown_cm": 0,
"distance_flown_m": 0,
"distance_swum_cm": 0,
"distance_swum_m": 0,
"total_distance_cm": 0,
"total_distance_m": 0,
"total_distance_km": 0,
"jumps": 0
},
"activity": {
"chests_opened": 0,
"items_crafted": 0,
"items_broken": 0,
"items_used": 0,
"items_picked_up": 0,
"items_dropped": 0,
"blocks_mined": 0
},
"metadata": {
"generated_at": "2026-05-20T11:17:16.252462500Z",
"execution_time_ms": 34,
"movement_enabled": true,
"combat_enabled": true,
"activity_enabled": true
}
}
Example Response โ Leaderboard
{
"stat": "playtime",
"total": 1,
"limit": 25,
"offset": 0,
"page": 1,
"entries": [
{
"rank": 1,
"uuid": "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"name": "Steve",
"online": false,
"value": 125,
"formatted": "6s"
}
],
"metadata": {
"generated_at": "2026-05-20T11:18:07.625703400Z",
"execution_time_ms": 3,
"ascending": false,
"online_only": false
}
}
โ๏ธ Configuration
The full config file is generated at plugins/statfyr/config.yml on first run.
http:
port: 8080
bind-address: "0.0.0.0" # Use 127.0.0.1 to restrict to localhost
security:
enable-api-key: false # Enable Bearer token auth
api-key: "" # Set your key here, or via STATFYR_API_KEY env var
enable-rate-limit: true
rate-limit-requests: 120 # Requests per window
rate-limit-window-seconds: 60
enable-cors: true
allowed-origins:
- "*" # Lock this down in production
cache:
ttl-seconds: 60
refresh-seconds: 10
Environment variable overrides:
| Variable | Config Key |
|---|---|
STATFYR_API_KEY |
security.api-key |
STATFYR_KEYSTORE_PASSWORD |
https.keystore-password |
๐ Securing Your API
For production servers, it is strongly recommended to:
- Enable API key authentication โ set
enable-api-key: trueand generate a strong random key - Restrict CORS origins โ replace
"*"with your dashboard's actual domain - Enable IP whitelisting โ if only known services need access, lock it to those IPs
- Enable HTTPS โ generate a keystore and set
https.enabled: true
Generate a keystore for HTTPS:
keytool -genkeypair -alias statfyr \
-keyalg RSA -keysize 2048 \
-storetype JKS \
-keystore plugins/statfyr/keystore.jks \
-validity 3650
๐ก API Documentation
Interactive API documentation is available at:
http://your-server:8080/api/docs
Disable it in production with docs.enabled: false.
๐๏ธ HTTP Status Codes
| Code | Meaning |
|---|---|
200 |
Success |
400 |
Bad request (invalid parameters) |
401 |
Unauthorized (missing or invalid API key) |
403 |
Forbidden (IP not whitelisted) |
404 |
Player or resource not found |
429 |
Too many requests (rate limit exceeded) |
500 |
Internal server error |
๐ ๏ธ Commands & Permissions
| Command | Permission | Description |
|---|---|---|
/statfyr reload |
statfyr.reload |
Reload the configuration |
/statfyr status |
statfyr.status |
Show API status and port |
๐ฌ Support & Community
- Comming soon!!
๐ License
Statfyr is released under the MIT License.


