Setting Up Rich Presence in Roblox Experiences

Rich Presence is a client-side feature built into the Roblox engine that displays status information about the current experience on a player's profile and in their friends list. It uses the Players.Player.Chatted and Instance:SetRichPresence() API. Experience creators control what shows up there, not players directly unless the experience provides a custom UI for it. Each experience can set up to four key-value pairs: name, state, details, and join/links. The name field is required and appears as the experience title. State shows what the player is doing, details gives extra context, and the link fields provide direct join or spectate URLs. There's also a large_image_key and small_image_key for profile picture icons next to the status. These image keys have to be registered asset IDs from a place that's published to Roblox, so you can't just use any URL. I spent two weeks debugging why the state field wouldn't display on some players' profiles but worked fine on others. The issue turned out to be that I was setting Rich Presence before the player's CharacterAdded event fired on the client, which meant the RPC call got dropped silently by the Roblox client when the player wasn't fully spawned yet. The fix was wrapping the SetRichPresence call in a wait for player.Character guard with a 5-second timeout. That saved me from having to publish every time I wanted to test it.

Implementation basics

Inside a LocalScript, you access the player through game.Players.LocalPlayer, then call SetRichPresence(key, value). You can set multiple keys at once by calling it repeatedly. Here's what a minimal setup looks like: local players = game:GetService("Players")
local player = players.LocalPlayer
player:SetRichPresence("state", "In a match")
player:SetRichPresence("details", "Diamond League") The keys are strings. The values are also strings capped at roughly 200 characters each. If you exceed that, Roblox silently truncates the value without any error message, which is annoying. The name key is special — it has to match the experience name or it won't display properly. I learned this the hard way when my test build had a placeholder name and the Rich Presence showed blank everywhere.

There's no server-to-client enforcement on Rich Presence. That means any client can spoof it locally on their own machine, but it only affects their own visible status. The server can override it though, which is the intended pattern. Set the authoritative version from a server script using player:SetRichPresence() there instead, so exploiters can't change what others see.

Get the Full Details

StatEye - Discord Rich Presence for Roblox - Community Resources ...
StatEye - Discord Rich Presence for Roblox - Community Resources ...

Common problems and workarounds

The biggest issue I ran into was that Rich Presence doesn't update instantly across all clients. When you change the state or details, there's usually a 2-4 second delay before it reflects in friends lists and profiles. This is because Roblox batches the RPC calls. If your game logic depends on showing an accurate real-time status to other players, you can't rely on Rich Presence for that. Use a custom leaderboard or info frame instead for anything time-sensitive. Another problem: large_image_key and small_image_key require the assets to be published first and approved. I uploaded logos to Roblox, got asset IDs, and then tried to reference them in SetRichPresence, but they showed as broken icons for about an hour after publishing. The images needed to go through the asset review queue before they'd display in Rich Presence. Check that the asset is actually live by opening its page in a browser before committing to it in your code. Also, the join_url and spectate_url fields have restrictions. They can't contain external domains unless the experience has the appropriate cross-server privileges enabled. For a standard private server experience, you'd use something like roblox.com/games/{placeId}. If you're doing this wrong, the links appear but don't work, and players end up confused trying to join a dead URL.

When Rich Presence is not the right tool

Rich Presence won't work for displaying player-specific data like individual scores, kill counts, or custom stats that aren't meant for the profile. The API doesn't support dynamic per-player custom fields beyond the four standard keys. If you need that level of detail, build a custom info panel inside the experience or use the chat system for quick status sharing. There's also a maximum of 25 simultaneous SetRichPresence calls per second per player before Roblox starts throttling. I hit this limit in a lobby system where every player joining triggered a status update. The solution was to debounce the calls and only update when the state actually changed, reducing calls from roughly 50 per second down to about 3. Rich Presence data persists for the duration of the experience session. Once the player leaves, the status clears automatically. There's no way to set an expiration timestamp or keep it active after disconnecting. If you need persistent status across sessions, you'd have to store that externally and reapply it when the player reconnects, which is outside Rich Presence itself.

The feature is free and doesn't require any separate download or configuration. It's available in all published Roblox experiences by default through the engine. You just need to write the client or server script that calls the API at the right moments.

GitHub - char-ptr/roblox-RPC: Discord rich presence for Roblox · GitHub
GitHub - char-ptr/roblox-RPC: Discord rich presence for Roblox · GitHub