RustBanned.net
Single LookupMass LookupAPIFAQ
RustBanned.net
Single Lookup
Check a single player
Mass Lookup
Check up to 100 players
API
Integrate with your server
FAQ
Common questions

© 2026 RustBanned.net

Not affiliated with or endorsed by Valve Corporation or Facepunch Studios.

© 2026 RustBanned.net. All rights reserved.

    API referencev1.4.0
    Introduction
    • Overview
    • Your first request
    • The essentials
    • Making requests
    • Errors
    Endpoints
    • All endpoints
    • Look up an account
    • Batch lookup
    • Scan a friend list
    • Rust statistics
    • Rust inventory
    • Image proxy
    Guides
    • Discord bot
    • Rust server plugin
    • AI assistant prompt
    • Before you ship

    API reference#

    A read-only HTTPS API for Steam ban data. No key, no signup. Responses are JSON.

    Your first request#

    Pick your shell and paste this in. You should get JSON back.

    curl "https://rustbanned.net/api/lookup?steamId=76561198012345678" \
      -H "User-Agent: YourAppName/1.0 (contact@example.com)"

    curl ships with macOS, most Linux distributions, and Windows 10 build 1803 and later, so there is nothing to install. The three commands differ only in how each shell continues a line: \ in bash and zsh, a backtick in PowerShell, and no continuation in cmd. In Windows PowerShell 5.1 curl is an alias for Invoke-WebRequest, which does not accept -H, so call curl.exe by name.

    steamId takes a SteamID64, a vanity name like Karaxo, or a profile URL. User-Agent should name your app and give a contact address; /api/lookup returns 403 if it is missing or shorter than 5 characters. Call this from a server, bot, or plugin. Browser JavaScript cannot set its own User-Agent.

    The essentials#

    Base URL
    https://rustbanned.net
    Authentication
    None.
    Required header
    User-Agent, at least 5 characters. Enforced on /api/lookup; send it everywhere anyway.
    Response format
    JSON. /api/friends streams Server-Sent Events.

    All endpoints#

    • GETPOST/api/lookupLook up an account
    • POST/api/lookup/batchBatch lookup
    • POST/api/friendsScan a friend list
    • GET/api/rust-statsRust statistics
    • GET/api/inventoryRust inventory
    • GET/api/imageImage proxy

    Making requests#

    Requests are checked against a schema at the edge. A request that fails validation never reaches the API.

    GET

    Input in the query string

    For single lookups. Use your language's URL helper so vanity names and profile URLs get encoded.

    HTTP
    GET /api/lookup?steamId=Karaxo
    User-Agent: YourAppName/1.0 (contact@example.com)
    POST

    Input in a JSON body

    Required for batch and friends, and accepted for single lookups. Send Content-Type: application/json.

    HTTP
    POST /api/lookup
    Content-Type: application/json
    User-Agent: YourAppName/1.0 (contact@example.com)
    
    {
      "input": "Karaxo"
    }

    Parameter names are case-sensitive#

    Names must match the spelling on this page exactly, capitals included. Get the casing wrong and validation reports the parameter as missing, not as invalid. A request carrying a valid SteamID64 still comes back 400.

    JSON field names work the same way. Most reports of this come from hand-typed cURL.

    /api/lookup?steamId=76561198012345678Accepted
    /api/lookup?steamid=76561198012345678400
    { "steamId": "76561198012345678" }Accepted
    { "steamid": "76561198012345678" }400

    Request requirements

    • Use https://rustbanned.net. HSTS is on, so an HTTP fallback will not work.
    • Set a User-Agent of at least 5 characters, naming your app and a contact address.
    • Send only the fields listed for the endpoint.
    • Set a timeout. The examples here use 10 seconds.

    If a request is refused

    Check the method, path, parameter casing, JSON body, and Content-Type. The response may come from the API or from Cloudflare, so check the response Content-Type before parsing it as JSON. Cloudflare pages carry a Ray ID. Quote it if you email.

    Errors#

    Standard HTTP meanings. Every endpoint can return 429 or a 5xx. A 5xx may come from the API or from Cloudflare in front of it; the second kind never reaches the API and arrives as an HTML error page rather than JSON.

    CodeStatusMeaning
    200OKThe request succeeded.
    400Bad requestA parameter or field is missing, misspelled, or fails validation.
    403ForbiddenRefused by security rules, the User-Agent requirement, or a privacy setting.
    404Not foundThe account or the requested data does not exist.
    429Too many requestsRate limited. Back off before retrying.
    500Internal server errorThe endpoint failed unexpectedly.
    502Bad gatewayAn upstream fetch failed, or the edge could not reach the origin. Any endpoint can return this, not just the image proxy.
    503Service unavailableSteam or another required service is down.

    Retrying after 429

    Back off exponentially. Use Retry-After when the response carries it. Tight retry loops keep the limit active and can get the IP blocked. The same backoff is worth applying to 502 and 503, which are usually transient; the snippet below only retries 429, so widen the condition if you want that.

    backoff.ts
    async function fetchWithBackoff(
      url: string,
      options: RequestInit,
      retries = 4
    ): Promise<Response> {
      for (let attempt = 0; attempt <= retries; attempt++) {
        const response = await fetch(url, options);
        if (response.status !== 429) return response;
    
        const retryAfter = Number(response.headers.get("Retry-After"));
        const waitMs = Number.isFinite(retryAfter) && retryAfter > 0
          ? retryAfter * 1000
          : 2 ** attempt * 500; // 500ms, 1s, 2s, 4s...
    
        if (attempt === retries) return response; // give up, let the caller handle it
        await new Promise((resolve) => setTimeout(resolve, waitMs));
      }
      throw new Error("unreachable");
    }
    GETPOST/api/lookup

    Look up an account#

    Returns the ban record for one Steam account.

    Takes a SteamID64, a vanity name, or a profile URL. Vanity names and URLs cost an extra call to resolve first, so pass a SteamID64 when you already have one. This is the only endpoint that checks the User-Agent header, and every response carries a Server-Timing header with the Steam lookup duration.

    Parameters

    steamIdstringin queryrequired
    GET requests only. Maximum 256 characters.
    inputstringin bodyrequired
    POST only. Same accepted formats.

    Responses

    • 200Lookup completed.
    • 400Missing or malformed parameter or body.
    • 403The User-Agent header is absent or shorter than 5 characters.
    • 404No Steam account matched.
    • 500Unexpected failure.
    • 503Steam is unavailable.

    Returns one account object.

    Request
    curl "https://rustbanned.net/api/lookup?steamId=76561198012345678" \
      -H "User-Agent: YourAppName/1.0 (contact@example.com)"
    200 · Response
    {
      "steamId": "76561198012345678",
      "profile": {
        "personaname": "PlayerName",
        "profileurl": "https://steamcommunity.com/profiles/76561198012345678",
        "avatarfull": "https://avatars.steamstatic.com/...",
        "timecreated": 1234567890
      },
      "bans": {
        "CommunityBanned": false,
        "VACBanned": true,
        "NumberOfVACBans": 1,
        "DaysSinceLastBan": 365,
        "NumberOfGameBans": 0,
        "EconomyBan": "none"
      },
      "rustHours": 1234.5,
      "friendsPrivate": false
    }

    The account object#

    Fields may be added over time. Do not assume the shape is fixed.

    FieldTypeDescription
    steamIdstringResolved SteamID64.
    profile.personanamestringCurrent Steam display name.
    profile.profileurlstringCanonical Steam profile URL.
    profile.avatarfullstringFull-size avatar URL on the Steam CDN.
    profile.timecreatednumberAccount creation time, in Unix seconds.
    bans.VACBannedbooleanWhether the account carries one or more VAC bans.
    bans.NumberOfVACBansnumberTotal VAC ban count across all games.
    bans.NumberOfGameBansnumberTotal developer-issued game ban count.
    bans.DaysSinceLastBannumberDays since the most recent reported ban.
    bans.CommunityBannedbooleanWhether Steam reports a Community ban.
    bans.EconomyBanstringTrade and market standing, such as "none".
    rustHoursnumber | nullHours played in Rust. Null when private or unavailable.
    friendsPrivatebooleanWhether the friend list was hidden from the lookup.
    POST/api/lookup/batch

    Batch lookup#

    Looks up as many as 50 accounts in one request.

    Entries resolve independently and accept the same formats as a single lookup. One batch is faster than 50 sequential calls and far less likely to hit the rate limit. Entries that fail to resolve are left out of results and counted in failed, so check resolved and failed rather than assuming the array lines up with what you sent.

    Parameters

    steamIdsstring[]in bodyrequired
    256 characters each. Anything past the 50th entry is dropped rather than rejected.

    Responses

    • 200Batch completed. Individual entries may still have failed to resolve.
    • 400steamIds is missing, not an array, or empty.
    • 404No entry resolved to a Steam account.
    • 500Unexpected failure.
    • 503Steam is unavailable.

    Returns results for the entries that resolved, plus resolved and failed counts.

    Request
    curl -X POST "https://rustbanned.net/api/lookup/batch" \
      -H "User-Agent: YourAppName/1.0 (contact@example.com)" \
      -H "Content-Type: application/json" \
      -H "Accept: application/json" \
      -d '{
        "steamIds": [
          "76561198012345678",
          "Karaxo",
          "https://steamcommunity.com/id/example"
        ]
      }'
    200 · Response
    {
      "results": [
        { "steamId": "76561198012345678", "profile": { ... }, "bans": { ... } },
        { "steamId": "76561198087654321", "profile": { ... }, "bans": { ... } }
      ],
      "resolved": 2,
      "failed": 1
    }
    POST/api/friends

    Scan a friend list#

    Checks every account on a player's friend list.

    Friend lists run to hundreds of accounts, so results arrive as Server-Sent Events. At most 100 friends are checked; totalFriends still reports the real size of the list. Progress events arrive during the scan and the results arrive as one final event, so read each data: line rather than waiting for the connection to close. Friends whose profile or ban record is unavailable are left out. A private or unavailable friend list is reported as an error event, not as an empty result.

    Parameters

    steamIdstringin bodyrequired
    A resolved SteamID64, 17 digits. Vanity names and profile URLs are rejected.

    Responses

    • 200Always. Failures are delivered as an error event inside the stream, so check each event rather than the status code.

    Returns progress events, then one event carrying the whole friends array.

    Request
    curl -N -X POST "https://rustbanned.net/api/friends" \
      -H "User-Agent: YourAppName/1.0 (contact@example.com)" \
      -H "Content-Type: application/json" \
      -d '{ "steamId": "76561198012345678" }'
    
    # This endpoint streams Server-Sent Events (SSE).
    # Read each "data:" event as it arrives instead of waiting for one JSON object.
    200 · Event stream
    data: {"progress":{"current":0,"total":100,"totalFriends":214}}
    
    data: {"progress":{"current":90,"total":100,"totalFriends":214}}
    
    data: {"friends":[
      {
        "steamId": "76561198012345678",
        "personaname": "PlayerName",
        "avatar": "https://avatars.steamstatic.com/abc123.jpg",
        "profileurl": "https://steamcommunity.com/id/example",
        "banned": true,
        "rustHours": 1234.5,
        "banDetails": {
          "VACBanned": true,
          "NumberOfVACBans": 1,
          "NumberOfGameBans": 0,
          "CommunityBanned": false,
          "EconomyBan": "none",
          "DaysSinceLastBan": 365
        }
      }
    ],"totalFriends":214}
    GET/api/rust-stats

    Rust statistics#

    Returns in-game Rust statistics for one account.

    Steam only exposes these when the player's game details are public. Expect 403 often, and don't retry it. Statistics come back in seven groups: combat, survival, building, resources, npc, items, and misc. Responses are cached for five minutes.

    Parameters

    steamIdstringin queryrequired
    A resolved SteamID64, 17 digits.

    Responses

    • 200Statistics returned.
    • 400Missing or malformed SteamID64.
    • 403Statistics are private.
    • 404No statistics for this account.
    • 4xx / 5xxSteam's own status code, passed through when the upstream fetch fails.
    • 500Statistics fetch failed, or the server has no Steam API key configured.

    Returns the account's Rust statistics, grouped by category.

    cURL
    curl "https://rustbanned.net/api/rust-stats?steamId=76561198012345678" \
      -H "User-Agent: YourAppName/1.0 (contact@example.com)"
    200 · Response
    {
      "steamId": "76561198012345678",
      "stats": {
        "combat":    { "kills": 4821, "deaths": 3190, "kd": 1.51, "headshots": 1204,
                       "headshotRate": 22.4, "bulletsFired": 90210, "bulletsHit": 5372,
                       "accuracy": 5.9, "wounded": 88, "woundedAssisted": 31,
                       "beenPickedUp": 12 },
        "survival":  { "deaths": 3190, "suicides": 74, "fallingDeaths": 33, ... },
        "building":  { "structuresBuilt": 9042, "upgradesBuilt": 2210, "repairsDone": 118 },
        "resources": { "woodHarvested": 1204553, "stoneHarvested": 880210, ... },
        "npc":       { "scientistsKilled": 512, "boarsKilled": 233, ... },
        "items":     { "itemsDropped": 902, "itemsPickedUp": 15522, "itemsCrafted": 88 },
        "misc":      { "barrelsBroken": 4410, "heliHits": 219, "arrowsFired": 1200, ... }
      }
    }
    GET/api/inventory

    Rust inventory#

    Returns the Rust inventory for one account.

    A private inventory is not an error: it comes back as 200 with private set to true and an empty items array. Results are capped at the first 50 items, and each icon is a relative /api/image URL you can use directly in an img tag. Responses are cached for five minutes.

    Parameters

    steamIdstringin queryrequired
    A resolved SteamID64, 17 digits.

    Responses

    • 200Inventory returned, or the inventory is private.
    • 400steamId is missing.
    • 4xx / 5xxSteam's own status code, passed through when the upstream fetch fails.
    • 500Inventory fetch failed.

    Returns a private flag, up to 50 items, and the total item count.

    cURL
    curl "https://rustbanned.net/api/inventory?steamId=76561198012345678" \
      -H "User-Agent: YourAppName/1.0 (contact@example.com)"
    200 · Response
    {
      "private": false,
      "items": [
        {
          "name": "Metal Facemask",
          "icon": "/api/image?url=https%3A%2F%2Fcommunity.cloudflare...",
          "tradable": true,
          "marketable": true,
          "type": ""
        }
      ],
      "total": 128
    }
    GET/api/image

    Image proxy#

    Serves a Steam CDN image through rustbanned.net.

    For embedding Steam avatars where third-party image hosts are blocked. Only the four steamstatic.com hostnames listed below are accepted.

    Parameters

    urlstringin queryrequired
    An https URL on community.cloudflare.steamstatic.com, community.akamai.steamstatic.com, cdn.akamai.steamstatic.com, or avatars.steamstatic.com. 2048 characters max.

    Responses

    • 200Image returned.
    • 400Missing or malformed url.
    • 403Hostname is not an approved Steam CDN.
    • 502Upstream fetch failed.

    Returns the image bytes, with the upstream content type.

    cURL
    curl "https://rustbanned.net/api/image?url=https%3A%2F%2Favatars.steamstatic.com%2Fabc123_full.jpg" \
      -H "User-Agent: YourAppName/1.0 (contact@example.com)" \
      --output avatar.jpg

    Discord bot#

    A /check slash command that returns a player's ban record as an embed.

    Defer the interaction first. Discord kills an unacknowledged slash command after about three seconds, and a slow Steam response takes longer than that. The examples below all defer.

    Command handler
    // discord.js v14 command handler
    // npm install discord.js
    
    import { EmbedBuilder } from "discord.js";
    
    export async function checkCommand(interaction) {
      if (!interaction.isChatInputCommand() || interaction.commandName !== "check") return;
    
      const steam = interaction.options.getString("steam", true);
    
      // Discord needs an acknowledgement quickly. Defer before the API call.
      await interaction.deferReply();
    
      try {
        const url = new URL("https://rustbanned.net/api/lookup");
        url.searchParams.set("steamId", steam);
    
        const response = await fetch(url, {
          headers: {
            "User-Agent": "MyRustDiscordBot/1.0 (you@example.com)",
            "Accept": "application/json"
          },
          signal: AbortSignal.timeout(10_000)
        });
    
        const contentType = response.headers.get("content-type") ?? "";
        if (!contentType.includes("application/json")) {
          throw new Error(`Non-JSON response (HTTP ${response.status})`);
        }
    
        const data = await response.json();
        if (!response.ok) {
          throw new Error(data.error ?? `HTTP ${response.status}`);
        }
    
        const embed = new EmbedBuilder()
          .setTitle(data.profile?.personaname ?? data.steamId)
          .setURL(data.profile?.profileurl ?? "https://rustbanned.net")
          .addFields(
            { name: "SteamID64", value: data.steamId, inline: false },
            { name: "VAC bans", value: String(data.bans.NumberOfVACBans), inline: true },
            { name: "Game bans", value: String(data.bans.NumberOfGameBans), inline: true },
            { name: "Rust hours", value: data.rustHours == null ? "Private" : String(data.rustHours), inline: true },
            { name: "Last ban", value: `${data.bans.DaysSinceLastBan} days ago`, inline: true }
          );
    
        if (data.profile?.avatarfull) {
          embed.setThumbnail(data.profile.avatarfull);
        }
    
        await interaction.editReply({ embeds: [embed] });
      } catch (error) {
        console.error(error);
        await interaction.editReply(
          "I couldn't check that account right now. Verify the Steam ID and try again."
        );
      }
    }
    
    // Register a slash command named /check with one required STRING option:
    // name: "steam"
    // description: "SteamID64, vanity name, or Steam profile URL"

    The discord.js and Discord.Net examples are command handlers for an existing bot. The discord.py one is closer to a full minimal bot. Keep your token in an environment variable.

    Rust server plugin#

    Call the API from a uMod / Oxide plugin to get an in-game admin command. uMod's webrequest timeout is in milliseconds, not seconds.

    In-game output/check 76561198012345678 → PlayerName | VAC: 1 | Game bans: 0 | Rust hours: 1234.5
    RustBannedCheck.cs
    using Newtonsoft.Json.Linq;
    using Oxide.Core.Libraries;
    using System;
    using System.Collections.Generic;
    
    namespace Oxide.Plugins
    {
        [Info("RustBannedLookup", "YourName", "1.0.0")]
        [Description("Adds /check <steam> using the RustBanned public API")]
        public class RustBannedLookup : RustPlugin
        {
            [ChatCommand("check")]
            private void CheckPlayer(BasePlayer player, string command, string[] args)
            {
                if (args.Length == 0)
                {
                    SendReply(player, "Usage: /check <SteamID64, vanity name, or profile URL>");
                    return;
                }
    
                var input = Uri.EscapeDataString(string.Join(" ", args));
                var url = $"https://rustbanned.net/api/lookup?steamId={input}";
                var headers = new Dictionary<string, string>
                {
                    ["User-Agent"] = "MyRustServerPlugin/1.0 (you@example.com)",
                    ["Accept"] = "application/json"
                };
    
                // uMod timeout is in milliseconds.
                webrequest.Enqueue(url, null, (code, response) =>
                {
                    if (code != 200 || string.IsNullOrWhiteSpace(response))
                    {
                        SendReply(player, $"RustBanned lookup failed (HTTP {code}).");
                        return;
                    }
    
                    try
                    {
                        var data = JObject.Parse(response);
                        var name = data["profile"]?["personaname"]?.ToString() ?? "Unknown";
                        var vac = data["bans"]?["NumberOfVACBans"]?.Value<int>() ?? 0;
                        var game = data["bans"]?["NumberOfGameBans"]?.Value<int>() ?? 0;
                        var hours = data["rustHours"]?.Type == JTokenType.Null
                            ? "Private"
                            : data["rustHours"]?.ToString() ?? "Unknown";
    
                        SendReply(
                            player,
                            $"{name} | VAC: {vac} | Game bans: {game} | Rust hours: {hours}"
                        );
                    }
                    catch
                    {
                        SendReply(player, "RustBanned returned an unexpected response.");
                    }
                }, this, RequestMethod.GET, headers, 10000f);
            }
        }
    }

    AI assistant prompt#

    Paste this into a coding assistant and swap in your language and framework. Test the result against a real Steam account before you deploy it.

    Attaching your existing bot or plugin file and asking for the integration to be added to it works better than asking for a new file.

    Prompt
    Build me a complete RustBanned integration in [LANGUAGE / FRAMEWORK].
    
    Goal:
    - Add a command called /check that accepts a SteamID64, Steam vanity name, or Steam profile URL.
    - Call GET https://rustbanned.net/api/lookup?steamId=INPUT
    - Set this header on the request:
      User-Agent: MyApp/1.0 (my-email@example.com)
    - Set Accept: application/json.
    - URL-encode the user's input.
    - Use a 10-second timeout.
    - Check Content-Type before parsing JSON because a security-layer response can be HTML.
    - Handle HTTP 400, 403, 404, 429, 500/502, and 503 cleanly.
    - If HTTP 429 includes Retry-After, respect it rather than retrying immediately.
    - Never spam retries.
    
    On success show:
    - player name
    - SteamID64
    - profile URL / avatar if supported
    - VAC ban count
    - game ban count
    - days since last ban
    - Rust hours, or "Private" when null
    
    If this is a Discord bot:
    - use a slash command
    - defer/acknowledge the interaction before calling the API
    - edit the deferred response with an embed/result
    - use non-blocking HTTP for async frameworks
    
    Return:
    1. install commands
    2. complete working code
    3. environment variables / secrets I need
    4. how to run it
    5. a short explanation written for a beginner.

    Before you ship#

    Worth going through before this sits in front of users.

    • Replace the example User-Agent with your app name and contact address.
    • URL-encode user input.
    • Set a timeout on every outbound request.
    • Check Content-Type before parsing a response as JSON.
    • Handle 400, 403, 404, 429, and 5xx without crashing.
    • Back off on 429 and cap the retry count.
    • Defer Discord interactions before calling the API.
    • Use non-blocking HTTP in async Python.
    • Keep tokens in environment variables.
    • Log failures without logging secrets.
    • Cache repeated lookups where stale data is fine.
    • Ban data supports a moderation call. It should not be the only thing behind a permanent ban.

    Support

    Email contact@rustbanned.net about blocked requests or unexpected errors. Include your public IP, the User-Agent you sent, the endpoint and method, the HTTP status, roughly when it happened with the timezone, and the Cloudflare Ray ID if you got a Cloudflare page.