Teleport between places

Many games are subdivided into multiple places, such as a fantasy world with towns, castles, dungeons, and a vast forest. Use TeleportService to teleport users between places, to different servers, or even to other games.

Teleport players

To teleport players, use TeleportService:TeleportAsync(). This method accepts three parameters:


local Players = game:GetService("Players")
local TeleportService = game:GetService("TeleportService")
local TARGET_PLACE_ID = 12345678901234 -- replace with your own
local playerToTeleport = Players:GetPlayers()[1] -- get the first user in the game
TeleportService:TeleportAsync(TARGET_PLACE_ID, {playerToTeleport})

To get the appropriate players to teleport, you might use a BasePart.Touched or a ProximityPrompt.Triggered event to get an individual Player. Then you can check if the player is part of a team (Player.Team) or party (Player.PartyId). Finally, you can use Team:GetPlayers() or SocialService:GetPlayersByPartyId() if you want to teleport the entire group rather than just the individual.

Configure secure teleportation

Three settings handle teleport security.

SettingDescription
(Creator Dashboard) Audience > Access Settings > Access Control for PlacesControls whether players can join any place in your game or must first join the start place.
(Creator Dashboard) Place > Access > Direct Access ControlOverrides your game-level Access Control for Places setting for a non-start place.
(Studio) File > Experience Settings > Security > Allow Third Party TeleportsControls teleports from your game to games that you don't own. You can leave this setting disabled and still teleport players between published games you own.

Access Control for Places controls players teleporting into your game and is the most critical setting for preventing teleport-based exploits.

Access control for places on the Creator Hub

  • If you choose Fully open, players can join any place in your game through teleports from any game, including deep links, game invites, joining a friend, and more.

    This is a good choice if your game has several places and you want friends to be able to easily join each other no matter which place they're in. If you don't choose this option, players who try to join their friends in non-start places will instead join your game's start place.

  • If you choose Limited to same universe, players can only join non-start places through teleports within your games. This setting allows both client- and server-initiated teleports.

    This is a good choice if you have a legacy game that you don't want to migrate to secure teleports.

  • If you choose Secure within universe only, players can only join non-start places through server-initiated teleports within this game.

    This is a good choice if your game has a strict progression system before players can access certain areas. It's also a good choice if your game has a test place that players shouldn't have access to or for places that exclusively use reserved servers.

Migrate to secure teleports

If you have an existing game that uses client-side teleports and want to require server-initiated teleports, the goal is to move all teleport logic out of client scripts and into server scripts:

  1. Find all client scripts that call Teleport().
  2. Change these calls to instead fire remote events. Alternatively, you can change the calls to instead use ProximityPrompts, ClickDetectors, or even just the BasePart.Touched event.
  3. Reimplement the teleport in a server script using TeleportAsync().
  4. When no more Teleport() calls exist, change Access Control for Places to Secure.

Create custom teleport screens

When a user triggers a teleport, they see the standard Roblox loading screen as they wait for the new place to load. If desired, you can add a custom teleport screen by calling TeleportService:SetTeleportGui() on the client.

The following example sets a customized ScreenGui from ReplicatedStorage. Any scripts within the ScreenGui do not run.


local TeleportService = game:GetService("TeleportService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local teleportGui = ReplicatedStorage.TeleportGui
TeleportService:SetTeleportGui(teleportGui)

Customize teleport options

You can customize teleportations, such as teleporting users to a specific server and sending user data along with teleports, by setting the TeleportOptions instance and passing it to the TeleportService:TeleportAsync() method.

Teleport to specific servers

To teleport users to specific servers, set the target server using TeleportOptions and pass it to the TeleportAsync() method. If you don't specify a server, users are teleported into a public server; the information of the first user in the list is used for matchmaking.

To teleport users to a specific public server, set the TeleportOptions.ServerInstanceId property as a valid instance ID, which is a unique identifier for a public server.


local teleportOptions = Instance.new("TeleportOptions")
teleportOptions.ServerInstanceId = targetServerId

To teleport users to a specific reserved server, set a valid TeleportOptions.ReservedServerAccessCode, which is a unique code for entering a reserved server.


local teleportOptions = Instance.new("TeleportOptions")
teleportOptions.ReservedServerAccessCode = reservedServerCode

To teleport users to a new reserved server, set TeleportOptions.ShouldReserveServer to true.


local teleportOptions = Instance.new("TeleportOptions")
teleportOptions.ShouldReserveServer = true

Send user data along with teleports

Teleporting a user between places discards any local data associated with that user. You can use the following approaches to handle data persistence between places:

  • If your game utilizes secure user data like in-game currency or inventory, implement data stores or memory stores to maintain data from place to place.

  • To send basic non-secure data from place to place, call TeleportOptions:SetTeleportData() before passing it to TeleportAsync(). Don't pass secure data using this method; the data is visible to the client and unencrypted.


local teleportData = {
randomNumber = RNG:NextInteger(1, 100),
}
local teleportOptions = Instance.new("TeleportOptions")
teleportOptions:SetTeleportData(teleportData)

To retrieve all data when a user arrives at the new place after a teleport, use the Player:GetJoinData() function, which returns a dictionary with a TeleportData key.


local Players = game:GetService("Players")
local function onPlayerAdded(player)
local joinData = player:GetJoinData()
local teleportData = joinData.TeleportData
local randomNumber = teleportData.randomNumber
print(player.Name .. " joined with the number " .. randomNumber)
end
Players.PlayerAdded:Connect(onPlayerAdded)

To retrieve only the teleport data on the client, you can use TeleportService:GetLocalPlayerTeleportData().

Handle failed teleports

Like any API call that involves network requests, teleports can fail and throw an error. Wrap them in protected calls (pcall()). Some failures benefit from retries, particularly those involving reserved servers, so we recommend retrying some number of times on failure.

Even if a call succeeds and the teleport initiates, it can still fail at the last moment without throwing an error and leave the user in the server. When this happens, it triggers the TeleportService.TeleportInitFailed event.

The following example ModuleScript returns a single SafeTeleport function that teleports players in a protected call with retry logic. It also has a handleFailedTeleport function to deal with situations in which the call was successful, but the teleport didn't occur.


local TeleportService = game:GetService("TeleportService")
local ATTEMPT_LIMIT = 5
local RETRY_DELAY = 1
local FLOOD_DELAY = 15
local function SafeTeleport(placeId, players, options)
local attemptIndex = 0
local success, result -- define pcall results outside of loop so results can be reported later on
repeat
success, result = pcall(function()
return TeleportService:TeleportAsync(placeId, players, options) -- teleport the user in a protected call to prevent erroring
end)
attemptIndex += 1
if not success then
task.wait(RETRY_DELAY)
end
until success or attemptIndex == ATTEMPT_LIMIT -- stop trying to teleport if call was successful, or if retry limit has been reached
if not success then
warn(result) -- print the failure reason to output
end
return success, result
end
local function handleFailedTeleport(player, teleportResult, errorMessage, targetPlaceId, teleportOptions)
if teleportResult == Enum.TeleportResult.Flooded then
task.wait(FLOOD_DELAY)
elseif teleportResult == Enum.TeleportResult.Failure then
task.wait(RETRY_DELAY)
else
-- if the teleport is invalid, report the error instead of retrying
error(("Invalid teleport [%s]: %s"):format(teleportResult.Name, errorMessage))
end
SafeTeleport(targetPlaceId, {player}, teleportOptions)
end
TeleportService.TeleportInitFailed:Connect(handleFailedTeleport)
return SafeTeleport

The SafeTeleport function receives the same arguments as the TeleportAsync() function. You can use the following script with the SafeTeleport function to perform teleports from anywhere in your game:


local Players = game:GetService("Players")
local TeleportService = game:GetService("TeleportService")
local ServerScriptService = game:GetService("ServerScriptService")
local SafeTeleport = require(ServerScriptService.SafeTeleport)
local PLACE_TO_TELEPORT_TO = 12345678
local function teleport(touchPart)
local playerToTeleport = game.Players:GetPlayerFromCharacter(touchPart.Parent)
if playerToTeleport then
SafeTeleport(PLACE_TO_TELEPORT_TO, {playerToTeleport})
end
end
script.Parent.Touched:Connect(teleport)
©2026 Roblox Corporation. Roblox, the Roblox logo and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.