Skip to main content
Two avatar sources ship out of the box. Each player picks which one they want from the in-game Settings panel; the choice persists per-character (not just per-license, so two characters on the same license can have distinct avatars).
config.lua

Sources toggle

Setting either to false hides that source from the player’s picker. Players currently using a disabled source fall back to initials on their next connect.
New players default to initials (hardcoded server-side). They keep using the letter tile until they actively pick a URL in the Settings panel.

URL allowlist

The biggest reason this isn’t a free-form text field: a player can otherwise paste any URL into the chat and force every other player’s CEF to fetch it. That’s a vector for tracking pixels, DDOS reflection, and IP-grabbing. The allowlist caps that.

Validation rules

A URL is accepted iff all are true:
  1. Starts with http:// or https://.
  2. Hostname (just the host, no path) appears verbatim in allowedHosts (case-insensitive).
  3. File extension appears verbatim in allowedExtensions (case-insensitive).
  4. Total length ≤ 512 chars.
Failed validation surfaces an inline red error in the player’s Settings panel under the URL field, plus a chat system warning. The avatar doesn’t change.

Per-character storage

Avatars are saved keyed by the framework’s character id (e.g. QBOX citizenid), not just the license. Two characters on the same license each have their own avatar.
When the player switches character mid-session:
  • Bridge fires qbx_core:server:onPlayerLoaded (or equivalent).
  • Server pushes the new character’s avatar fields to the NUI via settingsSaved.
  • Settings panel + every chat row updates live.

Standalone fallback

On a standalone server (no framework, no character id), the per-character layer doesn’t apply. Avatars save as flat avatarSource + avatarUrl keys on the settings row, applying license-wide. That’s the legacy behaviour pre-multichar.

Avatar in anonymous channels

For channels with anonymous = true:
  • The server strips avatarUrl from the payload before broadcasting.
  • The chat row renders a neutral grey silhouette tile (fa-user-secret icon) instead of the player’s real avatar.
  • Every recipient sees the same silhouette - the avatar tile is keyed to the channel, not the player.
The moment the player sends in a non-anonymous channel, their real avatar is back in the same chat session - no relog needed. See Categories for the full anonymous flag behaviour.

Avatar in Discord webhooks

When archiving messages to Discord:
  • The author block’s avatar uses the player’s URL avatar (if set).
  • Players using initials mode have no URL - the Discord embed shows a default Discord icon.
For anonymous channels with anonymousInWebhook = true, the avatar is omitted from the Discord embed too (matching the “Anonymous” label).