Compatibility
Minecraft: Java Edition
Platforms
Tags
Creators
Details
Mineflayer
Mineflayer keeps a player on a Minecraft server that is not a person — and it does it two ways. Locally, it registers a fake player through the exact code path a real login uses, so the server itself cannot tell the difference. Remotely, it sends a bot to another server over a real client connection, and that server needs no plugin installed.
Both join under a freshly generated name and a random UUID, every single time.
The local fake player
/mineflayer m start
-
Same entry point as real players. Registered through
PlayerList.placeNewPlayer, the same path a genuine login uses. It shows up inBukkit.getOnlinePlayers(), raises the player count by one, appears in the tab list, and keeps the server out of its idle state. -
Unkickable by design. Three independent layers, because the server has more than one way to remove a player and no single layer covers them all:
- Prevention. Every server-side watchdog that ends in a disconnect is reset
twice a second — the keepalive timeout, the client-load timeout, the idle
timeout (
player-idle-timeout) and the flight checks. A timer that never reaches its limit never kicks. - Blocking.
PlayerKickEventis cancelled atMONITORpriority, which is the single funnel for/kick, bans, plugin calls and every anti-cheat built on the Bukkit API. The priority is deliberate: nothing gets the last word after this. - Recovery. If something removes the player anyway — an NMS-level disconnect that fires no cancellable event — it is re-registered on the very next tick, and it never gives up. A failing rejoin slows down instead of stopping, because the reasons a join fails are almost always temporary.
Bans and whitelists do not stop the recovery layer:
placeNewPlayernever consultscanPlayerLogin. Verified by inspecting the server jar, not assumed. - Prevention. Every server-side watchdog that ends in a disconnect is reset
twice a second — the keepalive timeout, the client-load timeout, the idle
timeout (
-
No body, and untouchable by commands. Spectator mode, plus
invulnerableandcollidable = falseset explicitly and re-applied twice a second. Damage, teleports and game-mode changes out of spectator are all refused, and any command naming the player — from a player, the console or a command block — is cancelled, except this plugin's own, which is the one intended way out.One deliberate exception: a selector command like
/kill @ais not cancelled. Breaking the server for its real players to shield one fake one is the wrong trade, and it isn't needed — the individual effects are already refused above. -
Nothing that gives it away cheaply. A plausible steady latency is reported instead of zero, since a ping of exactly zero is the clearest tell that no real connection stands behind a player.
The remote bot
/mineflayer m connectto <ip> <port> start
Sends a bot to a different server, which needs no plugin and gets no special treatment. It is not a local registration — it is a real client connection: the plugin opens a socket and speaks the Minecraft protocol the way any client does, through Handshake → Login → Configuration → Play. The target just sees an ordinary player join, which is exactly why nothing has to be installed on it.
Scope is connect and stay: it answers keepalive and ping, confirms transitions, reconnects on its own, and relays the target's chat into your console. It does not move, build or fight.
Every automatic kick path is closed:
| Path | What the bot does |
|---|---|
player-idle-timeout |
player_input every 15 ticks |
| Client-load timeout | player_loaded on entering play |
| Keepalive timeout | answers keep_alive and ping |
| Flight checks | move_player_status_only every second, on-ground |
| Repeated death | auto-respawn on set_health ≤ 0 or a combat kill |
| Resource-pack refusal | accepts and reports it loaded, in both phases |
| Non-vanilla client detection | minecraft:brand = vanilla, default client settings |
The idle timeout is the detail that matters most, and answering keepalive is not
enough for it: per the server jar, nothing resets lastActionTime except a real
position change or a player_input packet. player_input is used specifically
because it resets the timer without claiming any position, so it cannot fail a
movement or flight check.
Reconnect. If the bot settles on the target and is then removed — kicked, restarted, dropped — it comes straight back with no wait at all. Anything that never settled backs off from one second to thirty and never stops trying. The two are told apart by session length, which is necessary: a target that kicks on sight also reaches the play phase for a moment, and without that distinction the plugin would reconnect forever at network speed.
Handoff. The local fake player steps aside when the remote bot successfully
joins, and comes back on stop. The order is deliberate — the local player is
never taken down before the remote join is confirmed, so a refused target cannot
leave you with no player at all. If the target keeps refusing until the backoff
hits its ceiling, the local player returns on its own in the meantime.
A new identity every join
Both the fake player and the remote bot generate a fresh 12-character name and a random UUID for every join — the first one from the command and every automatic rejoin after it. There is no setting for this; it is how the plugin works.
The one exception is a premium remote account, and it is a constraint rather than a choice: an access token authenticates the single name it owns, so a generated name would be refused by Mojang on every attempt.
Commands
| Command | Description |
|---|---|
/mineflayer m start |
Brings the local fake player online |
/mineflayer m stop |
Takes the local fake player offline |
/mineflayer m connectto <ip> <port> start |
Sends a bot to another server |
/mineflayer m connectto <ip> <port> stop |
Disconnects that bot |
/mf |
Alias for /mineflayer |
Permission: mineflayer.command (default: op).
Installation
- Place the jar in your server's
pluginsfolder. - Restart the server.
- Run
/mineflayer m start.
Nothing needs configuring for the local player, or for a remote target running
online-mode=false. A remote target with online-mode=true requires a real
Microsoft account that owns the name — its access token and profile UUID go in
config.yml. There is no way around that check: it happens on Mojang's side, not
the target server's, so nothing in this plugin can stand in for it, and an account
you do not own cannot be used. Treat config.yml as a secret once a token is in it.
Version independence
Server internals are reached through reflection, with methods resolved by shape (parameter count and types) rather than literal signature, and packet IDs read out of the running server at startup rather than hardcoded. That is what keeps one jar valid across both series: the IDs genuinely differ between them, and a stale hardcoded table would have sent well-formed packets under wrong numbers — a silent, confusing failure, worse than an obvious one.
The tradeoff is real: a mismatch surfaces at runtime rather than at build time, so failures are reported to the command sender and logged instead of swallowed.
Compatibility
- Bukkit, Spigot, Paper, Purpur and forks
- Minecraft 26.1.x and 26.2.x
- Java 25
Limits, stated plainly
- On a remote target, a human decision cannot be blocked. Automatic kicks are
closed off, but if that server's admin runs
/ban, enables a whitelist you are not on, or blocks your server's address, the bot is out. The event-cancelling protection above exists only on a server you control. - The bot is an ordinary player on the target. That server's commands affect it like any other player — it can be teleported, killed, and have its game mode changed. The command shield is local-only.
- A rotating identity defeats a name ban, not an address ban — and an address ban is what a target reaches for once it notices names that never repeat.
- Nothing carries over between joins. No inventory, position, permission or
whitelist entry survives a new identity, and locally every join writes a new file
under
world/playerdatathat is never reused. - On proxy-fronted networks (Velocity, BungeeCord) the count shown by the proxy is computed from proxy-level connections and will not include the local fake player.
What is guaranteed: neither bot will ever leave because of something it did or failed to do. And if either one is removed anyway, it comes back.
Mineflayer by DevGBX9


