Spoofer | Test your games with any User ID!

Spoofer

v1.01b, @saaawdust


What is Spoofer?

Spoofer is a server-sided module for Roblox that allows you to assign any user ID to a client, with the server interpreting the client as if they truly have that separate ID. When a specific ID is set on the server, Spoofer ensures all actions, requests, and events from the client appear to the server as originating from this defined ID.

For instance, if you assign the ID of Builderman, any requests or actions the client initiates will be interpreted by the server as if Builderman performed them.

This is especially useful for:

  • DataStore testing: Simulate interactions under specific user IDs to verify correct data handling.
  • Negative IDs: Replace negative IDs which a seperate ID.
  • Perspectives: View the perspectives of other players for UX / UI testing &/ troubleshooting.
  • Bug reproduction: If a particular user reports a bug, you could spoof their ID to reproduce the issue from their perspective.
  • Permission Testing: Simulate different permission levels by assigning IDs associated with specific roles, like admin, moderator, or regular user, to ensure appropriate access and restrictions are in place.

How does it work?

Spoofer acts as a middleware wrapper that transforms the client’s UserId into the specified alternate UserId. This allows the server to recognize and interact with the client as if they were the designated user. This is done transparently, so the client itself is unaware of the change, making Spoofer particularly effective for testing purposes.

API & Tutorial

The Spoofer API is simple to use. First, grab yourself a copy of the spoofer-server here (or, if you want the GitHub source code, here)! Once downloaded, place it somewhere such as ServerStorage. We can now start using Spoofer!

To spoof a user, use the pretend submodule. The being function accepts a username or UserId as an argument. Then, use as to specify the player to assign the spoofed ID to:

-- ServerScriptService/Server.lua

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")

local spoofer = require(ServerStorage.spoofer)
local pretend = spoofer.pretend

-- When the player joins, make them a spoofer
Players.PlayerAdded:Connect(function(player: Player) 
    -- Make `player` the user "Roblox"
	pretend.being("Roblox").as(player)
end)

Upon joining the game, you’ll see that you now appear as “Roblox,” complete with the avatar and chat name, meaning the spoof was successful.

To integrate this with RemoteEvents / UnreliableRemoteEvents, we can use the remotes sub-module of Spoofer. Since Spoofer is just making a wrapper around an instance here, we can give Spoofer a RemoteEvent, in which it will return the normal RemoteEvent functions on a server (meaning by changing 1 line of code, you could use Spoofer in your game!):

-- ServerScriptService/Server.lua

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")

local spoofer = require(ServerStorage.spoofer)
local pretend = spoofer.pretend
local remotes = spoofer.remotes

-- When the player joins, make them a spoofer
Players.PlayerAdded:Connect(function(player: Player) 
	-- Make `player` the user "Roblox"
	pretend.being("Roblox").as(player)
end)

-- Connect Spoofer to a RemoteEvent, and print when received
-- If a player isn't spoofing anyone, they "spoof their own UserId",
-- meaning this code can be ran in public servers with no issues!
local myRemoteEvent = remotes.use(workspace.Remote)
myRemoteEvent.OnServerEvent:Connect(function(client, ...: any) 
	print(`Received signal from: {client.Name}!`)	
end)

-- StarterPlayerScripts/Client.lua

-- Fire a message to the server
local myRemoteEvent = workspace.Remote
myRemoteEvent:FireServer()

And this code results in the output being: Received signal from: Roblox!, meaning our code worked and the server interpreted our message as if Roblox sent it!

If you want to “stop spoofing”, you can use the short-hand function pretend.toBeSelf, which “spoofs” the player into themselves:

pretend.toBeSelf(player)
-- is not the same as
pretend.being("PlayerName").as(player)

-- as "toBeSelf" sets the "isFake" property to false, meaning the player is their normal self.

:warning: Occasionally, Spoofer may take some time to initialize. If events are sent immediately when the player joins, there’s a chance Spoofer may lag behind, causing the server to recognize the actual player ID rather than the spoofed ID.

You can, however, change the ID you’re spoofing during runtime, and Spoofer will disconnect any of its in-built events for you, meaning you can start spoofing after a certain event, or multiple times. E.x:

pretend.being("Roblox").as(player) -- The player is now Roblox
pretend.being("Builderman").as(player) -- The player is now Builderman

For this reason, Spoofer provides a function on the spoofer-client (which will be explained later) that allows the client to yield until they have been indexed.

When you call the pretend.being function, or receive a client in a RemoteEvent, you’re actually receiving a SpooferPlayer (SPlayer), which mimics a player object. Since you can’t “create” a player, Spoofer provides some helpful utility methods inside of the SpooferPlayer:

:GetCharacter -> Model? – Gets the players character
:GetProperty(name: string) -> any – Gets a property of the spoofers actual player
:SetProperty(name: string, value: any) -> nil – Sets a property of the spoofers actual player
:CallMethod(name: string, ...any) -> any – Calls a method of the spoofers actual player
:GetInstance -> Player – Gets the spoofers actual player

The CharacterAdded and CharacterRemoving events are also provided without need to use of the functions above, like normal. Other properties attached to a SpooferPlayer are:

.Name: string – Spoofers name
.DisplayName: string – Spoofers DisplayName
.UserId: string – Spoofers UserId
.PlayerGui: string – Spoofers PlayerGui
.Backpack: string – Spoofers Backpack
.isFake: boolean – Whether the information provided above is the players actual data (Whether this is a real player, or a spoofed player)

You can also interface with the spoofer-server securely using the spoofer-client, which you can get here (or on the GitHub, here). The spoofer-client contains the following functions:

.getSpoofId – Gets the ID of the person the client is spoofing.
.getLocalPlayer – Returns a “sanitized” version of an SPlayer without functions.
.isIndexed – Returns if the client has been indexed by Spoofer.
.isSpoofing – Returns if the client is currently spoofing
.requestSpoof – Requests the server if the client can spoof

For the requestSpoof function, you can write your own custom server-sided logic to either allow or deny access to spoof. By default, Spoofer denies the request. You can replace the default function by assigning Spoofer.events.onRequested with your own function:

-- Let the chaos begin
-- This allows any user to spoof into any other user
spoofer.events.onRequested = function()
    return true
end

Finally, Spoofer also provides a collection of general-purpose-use functions:

.getAllFakePlayers – Returns all fake players.
.getAllRealPlayers – Returns all real players.
.getPlayerInstanceFromId – Given a userId, returns the spoofed player if any.
.getPlayerInstanceFromUsername – Given a username, returns the spoofed player if any.
.isPlayerSpoofing – Given a player, returns if that player is spoofing.
.isPlayerSpoofingFromId – Given a UserId, returns if that player is spoofing.
.isPlayerSpoofingFromUsername – Given a username, returns if that player is spoofing.
.doesPlayerExist – Given a username, returns if the player has been indexed in Spoofer.
.forceIndex – Forcibly indexes a player into Spoofer as themselves.
.forceRemove – Forcibly removes an indexed player and returns the old indexed player
.getRealPlayerFromUsername – Given a username, returns a spoofer instance if they’re actually in the game
.getRealPlayerFromUserId – Given a UserId, returns a spoofer instance if they’re actually in the game

Ethical concerns regarding Spoofer

While Spoofer is designed for testing, it can be misused. This tool is intended for responsible use, and I am not liable for anything you do with this module. Please abide by the Roblox TOS.

Contribution

Spoofer is now available on GitHub! The spoofer-server can be found here and the spoofer-client, here. These are in 2 different repositories as they do not depend on eachother to run - as the client API is completely optional. You can read CONTRIBUTING.md to get started.

Credits

As with all resources I post, credit is not needed for the use of this, but acknowledging the original creator is always appreciated (but entirely optional). You are free to modify the source code as you wish, but please refrain from reuploading or claiming the asset as your own work.

34 Likes

This is great! Looking forward to the GitHub, would love to browse it.

2 Likes

This is awesome! I suppose a function like stopPretending wasn’t added since you could just pretend as the original player, thus not over-complicating the scripts?

2 Likes

Yeah, I could add it as a simple utility function if you want though

1 Like

The GitHub is now up! You can see the source code for whichever part of Spoofer you like:

1 Like

Spoofer Release


This update adds more functionality to the spoofer-client, and some extra functions to the server. Full changelog:

General:

  • Bug fixes

Spoofer server:

  • pretend.toBeSelf to “stop spoofing”
  • forceRemove - Forcibly removes an indexed player and returns the old indexed player

Spoofer client:

  • .getLocalPlayer – Returns a “sanitized” version of an SPlayer without functions.
  • .isIndexed – Returns if the client has been indexed by Spoofer .
  • .isSpoofing – Returns if the client is currently spoofing
  • .requestSpoof– Requests the server if the client can spoof
1 Like

Spoofer Update vb 1.0.1


You can find the latest release on the marketplace, or here
This version of Spoofer works with the Spoofer client versions vb1.0.0 to vb1.0.0

Full changelog:

Spoofer server:

– Added 2 utility functions to the player sub-module:

  • getRealPlayerFromUsername - Given a username, returns a spoofer instance if they’re actually in the game
  • getRealPlayerFromUserId - Given a UserId, returns a spoofer instance if they’re actually in the game
1 Like

Hello,

thank you for this module.
I’m currently trying to use it, but I’m not able to make it fully work.

When I’m using it, my character’s appearance is changed to the pretended user, but the rest is still mine.

As we can see on the picture, I have the appearance of Builderman, but in the leaderboard, I’m still myself and I still got my database (a new user should have 0 bubbles and 0 keys). Also, I’m not prompted with the FTUE which is the primary reason I would like to use the module to test easily the FTUE multiple times.

Here how I tried to use it to make sure I’m not doing anything wrong.

I downloaded the rbxm file on GitHub and I inserted it in ServerStorage.

I copied this script

-- ServerScriptService/Server.lua

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")

local spoofer = require(ServerStorage.spoofer)
local pretend = spoofer.pretend

-- When the player joins, make them a spoofer
Players.PlayerAdded:Connect(function(player: Player) 
    -- Make `player` the user "Roblox"
	pretend.being("Builderman").as(player)
end)

And inserted it in a script in ServerScriptService

Then I click play or start a local server, I get the appearance but nothing else.

Thank you alot :smiley:

1 Like

In the Roblox leaderboard, nothing will change (as I don’t have access to the Roblox CoreGUI), as for the database stuff, you need to implement your own server logic that gets data from the Fake user ID instead of the real user ID.

1 Like

Oh, alright, thank you for your fast answer!

1 Like