Deleting a chat message

at the time I wrote this post, I didn’t know how to program correctly.

Could someone help me with this script? I am trying to create an anti-spammers system, which when detecting the sent spam message, would delete it, would delete yes if not if this error, could someone help me to delete the message when sent?
Whenever I try to delete the message the script stops working.

local Players = game:GetService(“Players”)
local spamMessage = “Scam test”
local GuiService = game:GetService(“StarterGui”)

local function onPlayerChatted(User, message)
if message:sub(1, spamMessage:len()):lower() == spamMessage:lower() then

local function onPlayerAdded(User)
User.Chatted:Connect(function (…)
onPlayerChatted(User, …)

for _, player in pairs(Players:GetPlayers()) do


Not entirely sure if this is possible, as :Destroy()only works on instances. It will be easier to create a custom chat and filter any ‘spam’ coming through there.

If it were possible to delete messages you can be sure that more complex games would have already implemented an anti-spam system! :sweat_smile:

Edit: I really didn’t search properly, there is a way to stop messages before being sent. The topic can be found linked here: How do you delete a chat message? - #7 by colbert2677


The roblox chat system is very modular, perhaps you could add a filter module that addresses this problem.

That way the scam chats would never actually reach anyone.

There’s a brief tutorial on how to modify the chat system here.


I’ve set up a basic module that does exactly what you want. If the player posts a scam message, it is never displayed to other players, and the player is kicked from the game.

--	// FileName: ChatScamDetector.lua
--	// Written by: Meta_data
--	// Description: Module that filters messages as spam and kicks the offending player.

local function getPlayer(speaker)
	return game.Players:FindFirstChild(speaker)

-- Modify this to something more complex.
local function isScam(content)
	if content == "scam message" then
		return true

local function Run(ChatService)
	local function ParseMessage(speakerName, message, channel)
		if isScam(message) then
			local player = getPlayer(speakerName)
			if player then
				player:Kick("Message detected as scam.")
			return true
		return false
	ChatService:RegisterProcessCommandsFunction("scamDetector", ParseMessage)

return Run

Basically, join a game in studio, and copy the ChatModules folder from the Chat service into your game. Then open it and insert a ModuleScript called “ChatScamDetector” and paste my script in it.

The end result will look like this:


Three glaring issues should be addressed in your code sample.

The getPlayer method is unnecessary and reinvents the wheel for ChatSpeaker methods, remove it. The ChatService has a GetSpeaker method for which you can pass a string to in order to get the speaker object that represents an entity that can chat. After you get the speaker, run GetPlayer. This will return the player if the speaker has an associated player.

Kicking players makes for bad UX, especially when the system is capable of flagging false positives. The majority of scam bots will leave themselves after sending a certain amount of messages (either once or several times), so you just need to reject the message from being processed and you’re gold. You can improve UX as well by informing legitimate users if their message is declined due to being flagged as a scam post.

Don’t fork the entire ChatModules folder with its contents. Create a ChatModules folder and then an InsertDefaultModules BoolValue in the folder with it checked off. This prevents forking of modules that you don’t majorly edit. From there, include your ChatScamDetector module. All default modules that are up to date will be inserted along with any modules pre-placed there from Studio.


1 and 2 are a nitpick, but 3 is new to me. Thanks.


It’s not really a nitpick. Reinventing the wheel is a code anti-pattern, which should be avoided. The ChatService already provides the API needed to get an associated player properly.

local function Run(ChatService)
    local function ParseMessage(speakerName, message, channel)
        local speaker = ChatService:GetSpeaker(speakerName)
        local player = speaker:GetPlayer()

UX suggestions for code should never be disregarded in a production environment as “nitpicks”. It’s important that you don’t kick users for developer-preventable actions such as rejecting the processing of their message altogether. You should never disconnect a client from the server without just cause that can’t be reasonably prevented with your own code.


It helps if you think about it from a player’s perspective. If they type “I got free coins from my friend” and suddenly get kicked because your system hit a false positive, how likely is it that they’ll want to play the game again?


The system could be modified to detect offending words instead, so there’s always room for a screwup. I believe, personally, that you’d probably only need to delete the message and tell them why, instead of :Kick()ing the player. I agree with Deferend here; kicking the player for a false positive would decrease their chances of playing the game again.


Hacked people just join paste the message and leave, so why to kick them, when they leave themself.

1 Like

Is this message filtered by roblox or do we have to do that ourselves? If we have to do that ourselves, is there a way of getting the post-roblox-filter message to then apply our own spam filter?

1 Like

There is a diagram of the chat workflow available on the Lua Chat System API page. Command modules are ran before the message is sent through the filter, so you will have the raw message to work with in a command module. For easier viewing, the workflow is attached below.

1 Like

I don’t think you should kick the player you should just block the message being sent because say someone was coping a message that a scambot sent to mock them, they would get kicked and that would be unfair.

If I understand correctly, does that mean the script runs before roblox’s filter runs, so I can detect the spam, and then roblox filters it if I approve of it?

That’s right.

Command modules are ran on a message and you can return a boolean to determine if the message should continue to be processed or not (true for stop processing, false for continue). If a command module returns true, the message won’t get processed (no filter, no sending to a channel). If the module returns false, the message will continue through the system. This part allows you to effectively approve or reject messages from even being shown in the chat window.

Command modules are all executed on a message first. If none of them return true (the message should not be stopped processing somewhere), it moves onto the filter functions, first developer filters (in this case, these are mainly used for modifying messages) and then the Roblox filter. Finally, the message will get sent to the channel.

That’s the goal of the code sample. If the message trips a scam function, it doesn’t process it through to the chat (no one will see it) and the player will get kicked.

Yes, it’s been said multiple times over the months. But I did it like that since that’s how OP wanted it.

1 Like