# Minecraft Prometheus Exporter turns a Bukkit server into a metrics endpoint

> Minecraft Prometheus Exporter is a Bukkit plugin that serves server statistics on port 9940, lets you switch each metric on or off, adds a custom health check endpoint, and ships a Grafana dashboard, with several metrics that do not work on Folia.

**sladkoff/minecraft-prometheus-exporter** — A Bukkit plugin which exports minecraft server stats to Prometheus

- Repository: https://github.com/sladkoff/minecraft-prometheus-exporter
- Stars: 541 · Forks: 76
- Language: Java
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/sladkoff-minecraft-prometheus-exporter

## Drop the jar in and scrape port 9940

Minecraft Prometheus Exporter is a Bukkit plugin that exports Minecraft server metrics to Prometheus, built for Paper, Spigot, Bukkit, Folia for experimental support, and other forks. The install is the shortest step in the whole project: copy the prometheus-exporter.jar into the Bukkit plugins directory and start the server. After startup the metrics endpoint is available at localhost:9940/metrics, and the port can be changed in the plugin's config.yml, which is created with defaults after the first use.

The endpoint layout is the conventional Prometheus one, so a scrape job is a couple of lines and the plugin needs no proxy or agent in front of it. There is a second endpoint too, at localhost:9940/health, which carries the result of the custom health checks the plugin can run.

The scope is a single server process. The plugin attaches to the server it is installed in, so every server you want to monitor needs the plugin and its own port. If you run several servers behind a BungeeCord proxy, the README points at a separate BungeeCord Prometheus Exporter for the additional metrics that live on the proxy side.

## Configuration comes from three places, in a fixed order

The host and port of the HTTP endpoint can be set in three ways, and the order of priority is fixed. Environment variables win first, with MINECRAFT_PROMETHEUS_EXPORTER_HOST and MINECRAFT_PROMETHEUS_EXPORTER_PORT, and when they are set they override everything else. System properties come second, minecraft.prometheus.exporter.host and minecraft.prometheus.exporter.port, which are passed when the JVM starts. The configuration file is the fallback, used only when neither of the other two is defined.

That ordering is designed for container and cluster deployments, where the same jar is baked into an image and the address has to come from outside it. The default config file shows the whole scheme in comments, including the system property form to use at JVM startup:

```yaml
host: localhost
# The port can be changed in case it conflicts with any other application.
port: 9940
```

The comment at the top of the file is the part to read before anything else. The HTTP server binds to localhost by default, and the file says to set the host to any reachable address or to 0.0.0.0 if your Prometheus runs on another host or inside a Kubernetes cluster. A default of localhost is a sensible security posture, and it is also the reason a first scrape from another machine fails with nothing in the logs.

## Metrics are toggled one by one, and the off switches are deliberate

The enable_metrics block in config.yml lists every metric the plugin can export, and each one is individually switchable. The comment says it plainly: metrics which are disabled by default may have a performance impact on your server.

The default set is on for the JVM metrics, jvm_threads, jvm_gc and jvm_memory, for the player counts, players_total, whitelisted_players and players_online_total, for entities_total, living_entities_total and loaded_chunks_total, and for tps together with the tick duration average, median and max. The two that ship disabled are tick_duration_min and, along with player_online, the per-player and per-player-statistic series, which are the granular ones that grow with the number of players online.

The shape of the block is a small design lesson in its own right. A metrics plugin that exports everything by default will eventually be the reason a server feels slow, so the expensive series are opt-in and the cheap ones are on. It also means the panel you build from these metrics will silently have gaps until you enable what you need, which is worth checking when a query returns nothing.

## The metric list, and where Folia breaks down

The metrics table is where the plugin's real coverage is visible, and it carries a Folia support column next to each entry. The counts for unique players online and offline, players online per world, world size in bytes and the JVM memory figure work on Folia. The whitelist count, chunks loaded per world, entities loaded per world and the villager count do not.

That pattern is the practical lesson. Folia changes how the server is partitioned across threads, and the API calls that count chunks or entities for a world are not available in the same form there. The plugin still runs and still serves the metrics that are supported, so a Folia deployment gets a useful but partial picture, and a chunk-loading alarm will not fire on that platform.

The rest of the table continues into per-player and tick timing series beyond the part reproduced in the README, and the README points to the metrics list itself as the reference for building your own dashboards. The naming is prefixed with mc_, which keeps the series grouped in a Prometheus query and avoids colliding with the JVM metrics that the plugin also exports.

## Scrape configs for one server or for a fleet

The Prometheus side is a job entry in the scrape_configs section. A single server looks like this, with a label that names it:

```yaml
- job_name: 'minecraft'
  static_configs:
    - targets: ['localhost:9940']
      labels:
        server_name: 'my-awesome-server'
```

For several servers the same job carries several target groups, each with its own server_name label, which is what lets one dashboard show a fleet rather than a single box:

```yaml
- job_name: 'minecraft'
  static_configs:
    - targets: ['localhost:9940']
      labels:
        server_name: 'server1'
    - targets: ['localhost:9939']
      labels:
        server_name: 'server2'
```

Note the second port, 9939, which is there because each plugin instance needs its own port on the host. The label is the part that matters for a shared dashboard, since the metric names are identical across servers and the label is the only thing that tells the panels apart.

## A ready made Grafana dashboard, with one manual step

The project ships a Grafana dashboard as a JSON file, minecraft-server-dashboard.json in the dashboards directory of the repository, and the import is the standard one. In Grafana you go to Dashboards, then Import, then paste in or upload the file.

There is one manual step afterwards, and the README spells it out. The JVM Memory Used widget has to be updated to reflect your server's maximum memory, which defaults to 8G in the dashboard, and you change it in the widget options, in the gauge maximum.

That is the whole integration. The dashboard is a starting point rather than a finished product, and the README notes that you can also build your own dashboards from the exported metrics, with the metric list as the reference. Since the plugin exposes ordinary Prometheus series, anything that talks to Prometheus can consume them, and the dashboard is only a convenience.

## Running it in Docker, and the Folia experiment

The repository includes a docker-compose file that wires the plugin into a containerised server, which is the fastest way to try the whole thing. The service uses the itzg/minecraft-server image pinned to a 2025.2.1 tag, with the EULA accepted, the Minecraft version set to 1.20.4 and the server type set to FOLIA, with a commented line showing the PAPER alternative and another commented block showing how a plugin jar can be fetched from a release URL.

Two ports are published, 25565 for the game and 9940 for the metrics endpoint, and the data directory is mounted as a volume, with the container set to restart unless stopped.

The Folia default in the compose file is a hint about where the project is experimenting, and it lines up with the experimental support the README mentions for that platform. If you intend to run the same compose file for your own testing, remember that the plugin jar has to be added, which the commented PLUGINS block shows how to do by pointing at a release asset.

## Where this plugin is the wrong tool

The obvious boundary is that it monitors one Minecraft server. There is no multi-server awareness in the plugin itself, no federation and no cluster view, so a fleet is a fleet of scrape targets and your own labelling. Anything that needs proxy level metrics, the connection counts and player distribution across a BungeeCord network, is out of scope, and the README points to a separate project for that.

The second boundary is the plugin model. The exporter only exists inside a running server, so it measures what that process can see. A server that is down produces no metrics at all rather than a zero, which means your alerting has to treat a missing series differently from a zero value, and a server that is still starting has no plugin endpoint either.

The third is Folia, where several of the more interesting metrics are unavailable, as the support column shows.

The last is scope. This is a Minecraft exporter and nothing else, and the JVM and tick timing series it exposes overlap with what a JVM exporter would give you for the same process. If you only need CPU, memory and garbage collection, the JVM metrics in the plugin are a convenience rather than a reason to install it.

## Conclusion

Minecraft Prometheus Exporter fits a server operator who runs Paper, Spigot, Bukkit or a similar fork, wants per-world player counts, chunk counts and tick timing in Prometheus, and can live with the plugin being deployed on every server instance separately. It does not fit a multi-server setup behind a proxy if you expect proxy level metrics, since the README points to a separate BungeeCord exporter for that, and you should check the Folia support column before relying on chunk, entity or whitelist counts. Before you install it, check three things: that the host and port are reachable from your Prometheus, since the plugin binds to localhost by default, that the metrics you need are enabled in config.yml, since several are off by default because they cost performance, and that the Folia column for that metric is a yes if you run Folia. The plugin is MIT licensed, the latest release is v3.1.2 from 2025-02-13, and the last push was on 2026-10-08.

## FAQ

### How do I install the Minecraft Prometheus Exporter?

Copy the prometheus-exporter.jar into the Bukkit plugins directory and start your Minecraft server. The metrics endpoint is then available at localhost:9940/metrics, and the port can be changed in the config.yml that the plugin creates after first use.

### How do I change the host and port of the metrics endpoint?

The plugin reads environment variables first, with MINECRAFT_PROMETHEUS_EXPORTER_HOST and MINECRAFT_PROMETHEUS_EXPORTER_PORT, then system properties such as minecraft.prometheus.exporter.host, and only then the config file. The server binds to localhost by default, so you need to set 0.0.0.0 or a reachable address for a Prometheus running elsewhere.

### Which Minecraft metrics does the exporter support on Folia?

Unique players, players online per world, world size and JVM memory work on Folia, while the whitelist count, chunks loaded per world, entities per world and the villager count do not. The README carries a Folia support column next to every metric in its table.

### Can I monitor several Minecraft servers with one Prometheus job?

Yes, by listing several target groups in the same job and giving each a server_name label, since the metric names are identical across servers. Each plugin instance still needs its own port on the host, for example 9940 and 9939.

### Does the exporter have a health check endpoint?

Yes. The plugin can run custom health checks on your server and exposes the aggregated result at localhost:9940/health, and the checks can be written in your own plugins.

## Sources

- [Issues](https://github.com/sladkoff/minecraft-prometheus-exporter/issues)
- [License: MIT](https://github.com/sladkoff/minecraft-prometheus-exporter/blob/master/LICENSE)
- [README](https://github.com/sladkoff/minecraft-prometheus-exporter/blob/master/README.md)
- [Releases](https://github.com/sladkoff/minecraft-prometheus-exporter/releases)
- [sladkoff/minecraft-prometheus-exporter on GitHub](https://github.com/sladkoff/minecraft-prometheus-exporter)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sladkoff-minecraft-prometheus-exporter
