I’ve been recently working on a system where players can write notes and place them on the ground. This works well but I’m unsure on how to filter the text so that people can’t cuss when writing.
Hi there! To filter text in Roblox, you need to use the TextService on the Server.
When the player submits their note, send the text to a RemoteEvent. On the server, use this logic:
local TextService = game:GetService("TextService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Make sure you have a RemoteEvent in ReplicatedStorage named "FilterRequest"
local FilterRequest = ReplicatedStorage:WaitForChild("FilterRequest")
-- Function to handle the filtering logic
local function getFilteredText(text, playerFromId)
local filterResult
local success, errorMessage = pcall(function()
filterResult = TextService:FilterStringAsync(text, playerFromId)
end)
if success then
-- Use GetChatForUserAsync for text visible to all players (like notes)
return filterResult:GetChatForUserAsync(playerFromId)
else
warn("Error filtering text: " .. errorMessage)
return "###" -- Safe fallback
end
end
-- Listen for the player sending text from their TextBox
FilterRequest.OnServerEvent:Connect(function(player, rawText)
local cleanText = getFilteredText(rawText, player.UserId)
print("Filtered text is: " .. cleanText)
-- TO DO: Apply 'cleanText' to your note's SurfaceGui or BillboardGui
-- Example: workspace.NotePart.SurfaceGui.TextLabel.Text = cleanText
end)
Let me know if it works!
Its far better and more efficient to filter on the client
but you need the server instance to filter the text or else exploits can replicate the whole process while leaving out the filtering part.
It’s okay if the text isn’t filtered from some exploits. that’s okay. it wont. be that common. 'ya feel me?
thats a terrible statement to make. not only does this compromise player safety but also the safety of the creators. the creator is responsible for their experience to stay within Roblox’ ToS. a short communication between client-server via RemoteEvent to filter some text is not that server heavy and is an important step towards a polished, safe experience for everyone.
please stop saying something like this to roblox creators. its not beneficial for anyone except exploiters
This ends up printing the “filtered text is blank” every time no matter what is said
You shouldn’t assume the data sent from the client rawText is of type string as it may not be and cause the entire script to error
Have you tried publish and try the live game? Filtering often returns empty or unexpected results in Studio.
It still returns empty no matter what I type in the actual roblox player
Looks like you need to debug it so i could see it. You can use this to try debug it:
local TextService = game:GetService("TextService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local FilterRequest = ReplicatedStorage:WaitForChild("FilterRequest")
-- Improved function with detailed error tracking
local function getFilteredText(text, playerFromId)
print("2. Function started. ID:", playerFromId, "Text length:", #text)
local filterResult
local success, errorMessage = pcall(function()
-- Note: This requires a valid, positive UserID to work
filterResult = TextService:FilterStringAsync(text, playerFromId)
end)
if success and filterResult then
print("3. FilterStringAsync succeeded.")
local getSuccess, resultText = pcall(function()
return filterResult:GetChatForUserAsync(playerFromId)
end)
if getSuccess then
print("4. GetChatForUserAsync returned: '" .. tostring(resultText) .. "'")
return resultText
else
warn("4. GetChatForUserAsync FAILED: " .. tostring(resultText))
return "###"
end
else
warn("3. FilterStringAsync FAILED: " .. tostring(errorMessage))
return "###"
end
end
FilterRequest.OnServerEvent:Connect(function(player, rawText)
-- 1. Check if data even reached the server
print("1. Server Received. Type:", typeof(rawText), "| Value:", tostring(rawText))
-- Security: Ensure rawText is a string and not empty
if typeof(rawText) ~= "string" then
warn("ERROR: Server expected string, got " .. typeof(rawText))
return
end
if #rawText:gsub("%s+", "") == 0 then
warn("ERROR: Server received empty string or only spaces.")
return
end
local cleanText = getFilteredText(rawText, player.UserId)
print("5. Final Filtered Text: '" .. cleanText .. "'")
-- Replace this with your actual logic (SurfaceGui, BillboardGui, etc.)
-- Example: workspace.Note.SurfaceGui.TextLabel.Text = cleanText
end)
After running it, look at the log and send the output.
17:03:45.977 1. Server Received. Type: string | Value: shoot - Server - FilterText:38
17:03:45.977 2. Function started. ID: 548760727 Text length: 5 - Server - FilterText:7
17:03:45.977 3. FilterStringAsync succeeded. - Server - FilterText:16
17:03:45.977 GetChatForUserAsync is being deprecated. Use TextChatService instead which automatically filters text sent. - Studio
17:03:45.977 4. GetChatForUserAsync returned: ‘’ - Server - FilterText:23
17:03:45.977 5. Final Filtered Text: ‘’ - Server - FilterText:53
Responded to you here with an edit to your code: Why does the filter text return blank? - #2 by Ashtagreunited
Yep, it was mentioned too in the output, thank you for fixing the code!
this isnt human
like litterally
What? What do you mean it isnt human?
looks like it was generated from chatgpt or smth
I understand why it looks that way, but I chose this structured style and the numbered debug prints specifically to track the FilterStringAsync sequence. I prefer using verbose comments and strict error handling to make my scripts easier to debug later, even not always but sometimes, yeah.