Lookup Presence

Read the live Discord presence of a member of the haunt.gg server.

Read the live Discord presence of a member of the haunt.gg Discord server by their account snowflake: status, current activity, profile media (avatar, banner, decoration, nameplate), server nickname, bio, guild tag and Discord badges — the same payload that powers the Discord presence widget on a profile.

GET/api/lookup/presence/{discordId}

Presence is only visible for members of the haunt.gg Discord server — that is where the bot observes it. A Discord account that exists but has not joined answers 404 with {"miss":"notMember"}, so you can tell "not a member" apart from "no such account" without a second request.

Authorizations

X-API-Keyheaderstringrequired
API key from your dashboard with the lookup:presence permission (granted by staff). Treat it like a password.

Path Parameters

discordIdpathstringrequired
The Discord account id (snowflake) to resolve — 17 to 19 digits. Anything else is rejected with 400 before the lookup runs. This is a Discord id, not a haunt.gg uid: to go the other way, resolve the haunt.gg user first with GET /api/lookup/user?type=username&value=… and read user.discordId.

Example Request

Request
curl -X GET "https://haunt.gg/api/lookup/presence/1363890885443452989" \
  -H "X-API-Key: YOUR_API_KEY"

Status values

status.status is the member's effective status, collapsed across their devices — the first non-offline of desktop, mobile and web. Streaming wins over everything: a member who is live reads streaming no matter what their manual status says.

ValueMeaning
onlineActive on at least one device.
idleAway — set manually or by inactivity.
dndDo Not Disturb.
streamingHas a Streaming activity running.
offlineOffline, invisible, or has no presence the bot can see.

status.url is a ready-to-embed icon on https://assets.haunt.gg/status/…, one PNG per value above.

Activities

activity is the single activity worth showing, picked in this order: Spotify first, then Playing / Streaming / Watching, then any other Listening activity, then a Custom Status. activities carries every activity the member has running, unfiltered and in Discord's own order — activity is always one of them (or null when there are none).

namestring
Activity name — the game, Spotify, or the app. Empty for a plain custom status with no text.
typenumber
Discord's activity type: 0 Playing, 1 Streaming, 2 Listening, 3 Watching, 4 Custom Status, 5 Competing.
statestring | null
The activity's state line — the party/detail line of a rich presence, or by <artist> shaped text for music.
detailsstring | null
The activity's details line — for Spotify, the track title.
tooltipstring | null
Hover text of the activity's large (or small) asset — for Spotify, the album name.
emojistring | null
Custom-status emoji. A CDN URL for a custom emoji, the literal unicode character for a standard one, null when there is none.
imagestring | null
Large activity artwork — album cover, game art or rich-presence asset — resolved to an absolute CDN URL. null when the activity ships none.

Badges

badges is an object keyed by badge id, ordered the way the presence widget renders it. Every entry carries a display name and a ready-to-embed url on https://assets.haunt.gg/badges/discord/…. Only badges the account actually holds are present, so iterate the object rather than indexing fixed keys.

Possible keys, in canonical order: nitro, staff, partner, moderator, events, bravery, brilliance, balance, bughunter1, bughunter2, developer, earlysupporter, boosted, legacy, quest, leaf, orb, gifting.

Response

Response
The member's presence. Every key is always present; the ones that do not apply to this account are null (or an empty object / array).
{
  "id": "1363890885443452989",
  "username": "john",
  "globalName": "John",
  "serverNick": "john the third",
  "avatar": "https://cdn.discordapp.com/avatars/1363890885443452989/a1b2c3d4e5f6.png",
  "serverAvatar": null,
  "banner": "https://cdn.discordapp.com/banners/1363890885443452989/f6e5d4c3b2a1.png",
  "serverBanner": null,
  "decoration": "https://cdn.discordapp.com/avatar-decoration-presets/a_9f8e7d6c5b4a.png",
  "nameplate": "https://cdn.discordapp.com/assets/collectibles/nameplates/twilight/asset.webm",
  "biography": "just here for the music",
  "activity": {
    "name": "Spotify",
    "type": 2,
    "state": "by Burial",
    "details": "Archangel",
    "tooltip": "Untrue",
    "emoji": null,
    "image": "https://i.scdn.co/image/ab67616d0000b273a1b2c3d4e5f6"
  },
  "activities": [
    {
      "name": "Spotify",
      "type": 2,
      "state": "by Burial",
      "details": "Archangel",
      "tooltip": "Untrue",
      "emoji": null,
      "image": "https://i.scdn.co/image/ab67616d0000b273a1b2c3d4e5f6"
    },
    {
      "name": "Custom Status",
      "type": 4,
      "state": "building things",
      "details": null,
      "tooltip": null,
      "emoji": "https://cdn.discordapp.com/emojis/1234567890123456789.png",
      "image": null
    }
  ],
  "badges": {
    "nitro": {
      "name": "Discord Nitro",
      "url": "https://assets.haunt.gg/badges/discord/premium.png"
    },
    "boosted": {
      "name": "Server Boosting since 12 Jan 2025",
      "url": "https://assets.haunt.gg/badges/discord/guild_booster_lvl9.png"
    }
  },
  "status": {
    "status": "online",
    "url": "https://assets.haunt.gg/status/online.png"
  },
  "last_online": 1756400000,
  "clan": {
    "tag": "HNT",
    "badge": "https://cdn.discordapp.com/guild-tag-badges/1363890885443452989/a1b2c3d4.png"
  }
}

Rate limits

Two buckets apply at once:

BucketLimit
Per API key30 requests/minute, or 60 if the key's owner has premium.
Per IP address60 requests/minute across all of /api/*.

A free-tier key is therefore effectively capped at 30 requests per minute.

Things worth knowing

  • Freshness. Status and activities are read live on every request. The member record behind the names, avatars, banner and guild tag is cached for 30 seconds, and the Discord profile behind biography and the external badges (Nitro, Server Booster, Quest, …) for 24 hours — a fresh Nitro subscription can take up to a day to appear here.
  • Server profile vs. account profile. serverNick, serverAvatar and serverBanner are the member's haunt.gg-server profile and are null for most members. Fall back to globalNameusername for the name and to avatar / banner for the media, which is what the profile widget does.
  • last_online is a Unix timestamp in seconds, recorded by the bot when the member last went offline. It is null for a member who has never been seen going offline.
  • nameplate is a WebM video, not an image — render it in a muted, looping <video> rather than an <img>.
  • clan is the member's Discord guild tag (the short badge next to their name), null when they display none.
  • Any /api/* request that reaches the origin without Cloudflare's cf-connecting-ip header is refused with 403 and {"error":"errors.forbidden"} before the route runs. This only affects callers that bypass Cloudflare.