With the rollout of UGC emotes, I’ve noticed that some are buggy, exploitable, or simply unwanted. While emotes are an important feature on Roblox, there doesn’t appear to be a built in way to currently disable UGC emotes This workaround filters them out, allowing only offical Roblox emotes to be used.
To handle this, I wrote a quick and simple function that blocks emotes that aren’t uploaded by Roblox, optionally replacing them with a blank placeholder, and caches emotes owned by Roblox to limit #GetProductInfo Calls.
With this patchy solution, there are some weird edge cases - some emotes are not considered Assets and will return 400 on #GetProductInfo. Eg: Charli xcx - Apple Dance
Emote Disabled Example:
Function:
local Players = game:GetService("Players")
local Market = game:GetService("MarketplaceService")
local ShouldEmotesBeCached = true
local ReplaceWithBlankEmote = true
local Cache = {}
local function BlockUGCEmotes(Character: Model)
local Humanoid = Character:FindFirstChildOfClass("Humanoid")
if not Humanoid then return end
local OwnedEmotes = Humanoid.HumanoidDescription:GetEmotes()
local RobloxEmotes = {}
Humanoid.HumanoidDescription:AddEmote("Emote Disabled", 1)
for _, Emote in Character.Humanoid.HumanoidDescription:GetEquippedEmotes() do
local Success, E = pcall(function()
local EmoteId = OwnedEmotes[Emote.Name][1]
if ShouldEmotesBeCached and table.find(Cache, EmoteId) then
table.insert(RobloxEmotes, {Slot = Emote.Slot, Name = Emote.Name})
return
end
local MarketInfo = Market:GetProductInfo(tonumber(EmoteId), Enum.InfoType.Asset)
if MarketInfo.Creator.Id == 1 then
if ShouldEmotesBeCached then
table.insert(Cache, EmoteId)
end
table.insert(RobloxEmotes, {Slot = Emote.Slot, Name = Emote.Name})
return
end
warn("UGC Emote removed.")
Humanoid.HumanoidDescription:RemoveEmote(Emote.Name)
if ReplaceWithBlankEmote then
table.insert(RobloxEmotes, {Slot = Emote.Slot, Name = "Emote Disabled"})
end
end)
-- There are some weird edge cases - Eg: "Charli xcx - Apple Dance"
if not Success then
table.insert(RobloxEmotes, {Slot = Emote.Slot, Name = Emote.Name})
end
end
Humanoid.HumanoidDescription:SetEquippedEmotes(RobloxEmotes)
end
Simple Implementation
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(Player: Player)
BlockUGCEmotes(Player.Character or Player.CharacterAdded:Wait())
Player.CharacterAdded:Connect(BlockUGCEmotes)
end)
Warning
- This is a patchy workaround until Roblox improves UGC emote moderation.
- Will not block “edge case” emotes that fail
GetProductInfocalls. - If Roblox later introduces official filtering, this script may be unnecessary.

