How do I filter a text box?

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.

2 Likes

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!

1 Like

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?

1 Like

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

1 Like

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

1 Like

Yep, it was mentioned too in the output, thank you for fixing the code!

1 Like

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.