Skip to content
RustPluginGenerator

OnPlayerUnbanned

OnPlayerUnbanned is called by Oxide when a Steam ID is removed from the server's ban list, after the removal has already been processed by RustCore.

Signature
void OnPlayerUnbanned(string playerName, ulong steamId, string address)

Parameters

Hook parameters
ParameterTypeDescription
playerNamestringDisplay name of the unbanned player, or the literal string "Unnamed" if Oxide cannot find a player object with that Steam ID (for example after a restart).
steamIdulongSteam ID of the account that was removed from the banned list, as a ulong. Use this as the stable identifier; the name and address can change.
addressstringLast known IP address of the player, or "0" when no player object is available for that Steam ID.

Return value

The return value is ignored at this call site. Returning null, true, or anything else has no effect on Oxide or on the ban list.

How it works

Oxide fires this hook inside RustCore.OnServerUserRemove after it confirms that the removed user was actually in the Banned group. The check runs only when the server is initialized, the user exists in ServerUsers.users, and that user's group is Banned. Removing an admin, a normal user, or a Steam ID that is not on the list does not trigger it.

Because the hook is raised by Oxide's own extension and not by a patched game method, it fires regardless of whether the unban came from server.writecfg, RCON (banid/unban style commands), an admin tool such as the Oxide unban console command, or a plugin calling the ban API. The ban entry is already gone by the time your code runs, so you cannot cancel the unban here.

The parameters come from Covalence's player lookup: playerName and address are only meaningful when Oxide can still resolve the Steam ID to a player object. For offline players and after a restart you will often get "Unnamed" and "0". Treat steamId as the authoritative value and look up anything else you need from your own stored data. OnUserUnbanned carries the same event with a string ID, so pick one and ignore the other to avoid double handling.

Example plugin: Notify staff and log every unban

UnbanNotifier.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Unban Notifier", "RustPluginGenerator", "1.0.0")]
    [Description("Sends staff a chat and console message whenever a player is unbanned")]
    public class UnbanNotifier : RustPlugin
    {
        private const string PermStaff = "unbannotifier.staff";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Notify staff in chat")]
            public bool NotifyChat = true;

            [JsonProperty("Write to server console")]
            public bool LogToConsole = true;
        }

        protected override void LoadDefaultConfig() => config = new PluginConfig();

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<PluginConfig>();
                if (config == null) throw new Exception();
            }
            catch
            {
                PrintWarning("Configuration file is invalid, using defaults");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void SaveConfig() => Config.WriteObject(config);

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Staff"] = "UNBAN: {0} ({1}) from {2}",
                ["Console"] = "Player unbanned: {0} ({1}) address {2}"
            }, this);
        }

        private void Init()
        {
            permission.RegisterPermission(PermStaff, this);
        }

        private void OnPlayerUnbanned(string playerName, ulong steamId, string address)
        {
            string name = string.IsNullOrEmpty(playerName) || playerName == "Unnamed" ? "unknown" : playerName;
            string ip = string.IsNullOrEmpty(address) || address == "0" ? "unknown" : address;

            if (config.LogToConsole)
                Puts(Msg("Console", null, name, steamId, ip));

            if (!config.NotifyChat) return;

            string message = Msg("Staff", null, name, steamId, ip);
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected) continue;
                if (permission.UserHasPermission(player.UserIDString, PermStaff))
                    player.ChatMessage(message);
            }
        }

        private string Msg(string key, string userId = null, params object[] args) =>
            string.Format(lang.GetMessage(key, this, userId), args);
    }
}

The plugin listens for OnPlayerUnbanned and builds a readable line containing the Steam ID, name, and address. It sends that line to every connected player who holds the unbannotifier.staff permission, and prints the same text to the server console through Puts so it ends up in Oxide logs. Optional config toggles the staff chat message and the console line independently. A NextTick wrapper is not needed because unbans are rare events, so calling Puts here is safe. Names and addresses are shown as received, with the fallback values from Oxide handled by a short helper that substitutes unknown when the name is Unnamed or the address is 0.

Common use cases

  • Keep a ban history for appeals

    Write the Steam ID, name, and address to a data file so staff can review who was unbanned and when, even after oxide/data has been reloaded.

  • Alert staff on Discord-style webhooks via other plugins

    Call into a notification plugin you reference with [PluginReference] to post to an admin channel, guarding against that plugin being absent.

  • Reset per-player penalties

    Clear stored strike counts or temporary restrictions tied to the Steam ID, so a player who won an appeal starts clean on the next connect.

Pitfalls

  • Fires for console and RCON unbans too

    The hook does not know who issued the unban. If you need the operator, compare the timing against OnRconCommand or run your own unban flow through a command that saves the caller.

  • Name and address can be placeholders

    Oxide passes Unnamed and 0 when Covalence cannot resolve the player. Never key records on the name, and treat 0 as unknown rather than a real IP.

  • Not the same as a failed ban removal

    The hook only fires when the entry existed in the Banned group. An unban command for an unknown ID or an admin silently does nothing, so absence of this hook is expected, not an error.

Build a plugin with OnPlayerUnbanned

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Keep a ban history for appeals using the OnPlayerUnbanned hook, with a config file and a permission
Generate this plugin

Edit the prompt on the next screen. 2 free plugins a month, no card.

Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.

Build a plugin with OnPlayerUnbanned

Generate