Collapse Sidebar


The FilterStringAsync function filters a string being received from a user, using the TextService, and returns a TextFilterResult which can be used to distribute the correctly filtered text accordingly.


This method should be called once each time a user submits a message. Do not cache the results of this function and re-use them for separate messages. If a user submits the same text multiple times this method must be called again each time the message is sent. If the results are cached and reused spam detection and many forms of context-aware filtering will be broken and potentially put user safety at risk. Games that improperly use cached results may face moderation.

However, it is encouraged to keep these result objects to display the same message to users who join the server later. For example: this can be used to safely and efficiently implement a server chat log that always uses the least restrictive filtering for users who join later, or for efficiently displaying text like a pet name to a user who joins the game after the pet was first spawned and name filtered.

The optional Enum/TextFilterContext parameter will not impact the filtered result of the query. This value will be used to improve Roblox’s text filtering.

Private text is anything that is seen only by specific players, rather than every player. For example, if the chat is seen by a single player, or by a selected group of players, then the chat is considered private. Chat for teams or chat that is potentially visible to a wider group, such as the server, is considered public. If you are unsure what your text qualifies as, leave the optional field blank.


  • This method always yields to make a text filtering service call
  • This method may throw if there is a service error that can not be resolved. If this function throws an error please do not retry the request; this method implements it’s own retry logic internally. If this method fails do not display the text to any user.
  • This method currently throws if fromUserId is not online on the current server. We plan to support users who are offline or on a different server in the future.


Name Type Default Description

The text to be filtered.

The userId of the player filtering the text.


The context that the filtered message will be used in. The default is PrivateChat.


Return Type Summary

Can be used to distribute the correctly filtered text accordingly.

Code Samples

Pet Name Filter Example

This code sample includes a simple demonstration of how TextService/FilterStringAsync should be implemented in a system where players are allowed to name their pets.

Note, this code sample includes the server-side implementation only (to be placed in a Script). Examples of how to implement the client-side of this system are included under the RemoteEvent and RemoteFunction examples.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TextService = game:GetService("TextService")
local Players = game:GetService("Players")

-- Define remotes for communication with client
local Remotes = Instance.new("Folder", ReplicatedStorage)
Remotes.Name = "PetNamingRemotes"

local UserNamedPet = Instance.new("RemoteEvent", Remotes)
UserNamedPet.Name = "UserNamedPet"
	RemoteEvent UserNamedPet

	Paramaters: petName (string)

	To be fired by the client when the user has picked a name for their pet.


	local userNamedPet = ReplicatedStorage:WaitForChild("PetNamingRemotes"):WaitForChild("UserNamedPet")

local SendPetName = Instance.new("RemoteEvent", Remotes)
SendPetName.Name = "SendPetName"
	RemoteEvent SendPetName

	Paramaters: userId (int), petName (string)

	Fired by the server when a user changes their pet's name


	local sendPetName = ReplicatedStorage:WaitForChild("PetNamingRemotes"):WaitForChild("SendPetName")
	sendPetName.OnClientEvent:Connect(function(userId, petName)
		local player = Players:GetPlayerByUserId(userId)
		if player then
			print(player.Name.." has named their pet ".. petName)

local RequestAllPetNames = Instance.new("RemoteFunction", Remotes)
RequestAllPetNames.Name = "RequestAllPetNames"
	RemoteEvent SendPetName

	Paramaters: n/a

	Fetches the names of every player's pet. To be invoked by the client when a user joins the game. 


	local requestAllPetNames = ReplicatedStorage:WaitForChild("PetNamingRemotes"):WaitForChild("RequestAllPetNames")
	local petNames = requestAllPetNames:InvokeServer()
	for userId, petName in pairs(petNames or {}) do
		local player = Players:GetPlayerByUserId(userId)
		if player then
			print(player.Name.." has a pet named ".. petName)


local filterResults = {}

local function broadcastPetName(userId)
	local filterResult = filterResults[userId]
	if filterResult then
		for _, player in pairs(Players:GetPlayers()) do 
			if player then

				-- spawn a new thread so as to not yield the update

					-- grab the filtered string for this user
					local toUserId = player.UserId
					local filteredString = filterResult:GetNonChatStringForUserAsync(toUserId)
					filteredString = filteredString or ""
					-- send the remote event
					SendPetName:FireClient(player, userId, filteredString)

UserNamedPet.OnServerEvent:Connect(function(player, petName)
	local fromUserId = player.UserId

	-- pcall to catch errors
	local success, result = pcall(function()
		return TextService:FilterStringAsync(

	if success then
		filterResults[fromUserId] = result
		print("Could not filter pet name")

RequestAllPetNames.OnServerInvoke = (function(player)
	local toUserId = player.UserId

	local petNames = {}

	-- go through filter results and filter the pet name to be sent
	for fromUserId, filterResult in pairs(filterResults) do
		local filteredString = filterResult:GetNonChatStringForUserAsync(toUserId)
		filteredString = filteredString or ""

		-- need to convert userId to string so it can't be sent via a remote function
		petNames[tostring(fromUserId)] = filteredString

	return petNames

-- Listen for players being removed, and clean up old filter results
	local userId = oldPlayer.UserId
	filterResults[userId] = nil