Universal Script – Spy - Verified script for Universal Roblox
Key RequiredUniversal

Universal Script – Spy

Universal ScriptNoobscripter7Noobscripter7 551 views 95 executesUpdated Oct 18, 2026
Unrated
00
Lua Script•442 lines (15365 chars)
-- =====================================================
-- HABILIDAD ESPIA: Tablet + Nanobot con cara de camara
-- 1) Equipa la "Spy Tablet" del inventario (se abre la lista de jugadores)
-- 2) Elige un jugador: el nanobot vuela hasta su cabeza y entra en ella
-- 3) Ves por sus ojos. "Players" para cambiar de jugador, "Exit" para salir
-- =====================================================
local Players = game:GetService("Players")
local RS = game:GetService("RunService")
local TS = game:GetService("TweenService")
local lp = Players.LocalPlayer
local genv = (getgenv and getgenv()) or _G
if genv.SpyOff then pcall(genv.SpyOff) end

-- ===== ajustes =====
local BOT_SPEED = 70                          -- velocidad del nanobot
local BOT_COLOR = Color3.fromRGB(90, 200, 255)
local FOV_SPY = 80                            -- campo de vision al espiar

local function new(class, props, parent)
	local o = Instance.new(class)
	for k, v in pairs(props) do o[k] = v end
	o.Parent = parent
	return o
end

local fxFolder = new("Folder", {Name = "SpyFX"}, workspace)
local fov0 = workspace.CurrentCamera.FieldOfView
local state = "idle"      -- idle / flying / entering / spying / returning
local target = nil
local tool = nil
local bot = nil
local conns = {}
local saved = nil
local hiddenOrig = {}
local hiddenChar = nil

-- ===== interfaz =====
local gui = new("ScreenGui", {Name = "SpyGui", ResetOnSpawn = false, DisplayOrder = 999}, nil)
pcall(function() gui.Parent = lp:WaitForChild("PlayerGui", 5) end)
if not gui.Parent then pcall(function() gui.Parent = gethui() end) end
if not gui.Parent then pcall(function() gui.Parent = game:GetService("CoreGui") end) end

local toastLbl = new("TextLabel", {
	AnchorPoint = Vector2.new(0.5, 0), Position = UDim2.new(0.5, 0, 0, 60), Size = UDim2.new(0, 300, 0, 34),
	BackgroundColor3 = Color3.new(0, 0, 0), BackgroundTransparency = 0.35, TextColor3 = Color3.new(1, 1, 1),
	Font = Enum.Font.GothamBold, TextSize = 14, TextWrapped = true, Visible = false, BorderSizePixel = 0, Text = "",
}, gui)
local function toast(txt, dur)
	toastLbl.Text = txt
	toastLbl.Visible = true
	task.delay(dur or 3, function()
		if toastLbl.Text == txt then toastLbl.Visible = false end
	end)
end

-- panel de la tablet (lista de jugadores)
local panel = new("Frame", {
	Position = UDim2.new(0, 20, 0.5, -150), Size = UDim2.new(0, 250, 0, 300),
	BackgroundColor3 = Color3.fromRGB(14, 18, 28), BorderSizePixel = 0, Visible = false, Active = true,
}, gui)
new("UICorner", {CornerRadius = UDim.new(0.04, 0)}, panel)
new("UIStroke", {Color = BOT_COLOR, Thickness = 2}, panel)
new("TextLabel", {
	Size = UDim2.new(1, 0, 0, 30), BackgroundTransparency = 1, Text = "SPY TABLET",
	TextColor3 = BOT_COLOR, Font = Enum.Font.GothamBold, TextSize = 16,
}, panel)
local list = new("ScrollingFrame", {
	Position = UDim2.new(0, 8, 0, 34), Size = UDim2.new(1, -16, 1, -80), BackgroundTransparency = 1,
	ScrollBarThickness = 4, BorderSizePixel = 0, CanvasSize = UDim2.new(0, 0, 0, 0),
	AutomaticCanvasSize = Enum.AutomaticSize.Y,
}, panel)
new("UIListLayout", {Padding = UDim.new(0, 4)}, list)
local closeP = new("TextButton", {
	Position = UDim2.new(0, 8, 1, -40), Size = UDim2.new(1, -16, 0, 32), Text = "Cerrar",
	BackgroundColor3 = Color3.fromRGB(150, 40, 40), TextColor3 = Color3.new(1, 1, 1),
	Font = Enum.Font.GothamBold, TextSize = 14, BorderSizePixel = 0,
}, panel)

-- pantalla del espia (mientras ves por la camara)
local hud = new("Frame", {Size = UDim2.new(1, 0, 1, 0), BackgroundTransparency = 1, Visible = false}, gui)
new("UIStroke", {Color = BOT_COLOR, Thickness = 5, Transparency = 0.3}, hud)
local rec = new("TextLabel", {
	Position = UDim2.new(0, 16, 0, 12), Size = UDim2.new(0, 260, 0, 24), BackgroundTransparency = 1,
	TextXAlignment = Enum.TextXAlignment.Left, TextColor3 = Color3.fromRGB(255, 90, 90),
	Font = Enum.Font.GothamBold, TextSize = 16, Text = "",
}, hud)
local function hudBtn(text, x, color)
	return new("TextButton", {
		AnchorPoint = Vector2.new(1, 0), Position = UDim2.new(1, x, 0, 12), Size = UDim2.new(0, 90, 0, 34),
		Text = text, BackgroundColor3 = color, TextColor3 = Color3.new(1, 1, 1),
		Font = Enum.Font.GothamBold, TextSize = 14, BorderSizePixel = 0,
	}, hud)
end
local swBtn = hudBtn("Players", -112, Color3.fromRGB(40, 110, 160))
local exitBtn = hudBtn("Exit", -16, Color3.fromRGB(170, 40, 40))
local flash = new("Frame", {Size = UDim2.new(1, 0, 1, 0), BackgroundColor3 = Color3.new(1, 1, 1), BackgroundTransparency = 1, BorderSizePixel = 0, ZIndex = 5}, hud)

-- ===== nanobot con cara de camara =====
local function makeBot()
	local m = Instance.new("Model")
	local parts = {}
	local function add(size, shape, color, neon, pos, rot, spin)
		local p = Instance.new("Part")
		if shape then p.Shape = shape end
		p.Size = size
		p.Color = color
		p.Material = neon and Enum.Material.Neon or Enum.Material.Metal
		p.Anchored = true
		p.CanCollide = false
		p.CanQuery = false
		p.CanTouch = false
		p.CastShadow = false
		p.Parent = m
		table.insert(parts, {part = p, size = size, pos = pos, rot = rot, spin = spin})
		return p
	end
	local CYL, BALL = Enum.PartType.Cylinder, Enum.PartType.Ball
	local AX = CFrame.Angles(0, math.rad(90), 0)   -- cilindro apuntando al frente
	local AY = CFrame.Angles(0, 0, math.rad(90))   -- cilindro vertical
	local body = add(Vector3.new(1.5, 1.5, 1.5), BALL, Color3.fromRGB(70, 75, 90), false, Vector3.new(0, 0, 0), CFrame.new(), false)
	add(Vector3.new(0.3, 1, 1), CYL, Color3.fromRGB(12, 12, 16), false, Vector3.new(0, 0, -0.65), AX, false)
	add(Vector3.new(0.12, 0.6, 0.6), CYL, BOT_COLOR, true, Vector3.new(0, 0, -0.82), AX, false)
	local halo = add(Vector3.new(0.1, 2.3, 2.3), CYL, BOT_COLOR, true, Vector3.new(0, 0, 0), AY, true)
	halo.Transparency = 0.4
	add(Vector3.new(0.12, 0.8, 0.12), nil, Color3.fromRGB(190, 195, 210), false, Vector3.new(0, 1, 0.1), CFrame.new(), false)
	add(Vector3.new(0.3, 0.3, 0.3), BALL, BOT_COLOR, true, Vector3.new(0, 1.45, 0.1), CFrame.new(), false)
	m.PrimaryPart = body
	m.Parent = fxFolder

	local a0 = new("Attachment", {Position = Vector3.new(0, 0.4, 0.6)}, body)
	local a1 = new("Attachment", {Position = Vector3.new(0, -0.4, 0.6)}, body)
	new("Trail", {
		Attachment0 = a0, Attachment1 = a1, Lifetime = 0.35, LightEmission = 1,
		Color = ColorSequence.new(BOT_COLOR),
		Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.2), NumberSequenceKeypoint.new(1, 1)}),
	}, body)
	new("PointLight", {Color = BOT_COLOR, Range = 14, Brightness = 2}, body)
	return {model = m, parts = parts}
end

local function placeBot(b, cf, scale, t)
	for _, e in ipairs(b.parts) do
		local rot = e.rot
		if e.spin then rot = CFrame.Angles(0, t * 9, 0) * e.rot end
		e.part.Size = e.size * scale
		e.part.CFrame = cf * CFrame.new(e.pos * scale) * rot
	end
end

local function flyBot(b, startPos, getDest, onDone)
	local pos = startPos
	local t0 = os.clock()
	local con
	con = RS.Heartbeat:Connect(function(dt)
		local dest = getDest()
		if not dest then
			con:Disconnect()
			onDone(false)
			return
		end
		local d = dest - pos
		local dist = d.Magnitude
		if dist < 1.2 then
			con:Disconnect()
			onDone(true)
			return
		end
		local dir = d.Unit
		pos = pos + dir * math.min(BOT_SPEED * dt, dist)
		local tt = os.clock() - t0
		local wob = Vector3.new(0, math.sin(tt * 9) * 0.5, 0)
		placeBot(b, CFrame.new(pos + wob, pos + wob + dir), 1, tt)
	end)
	table.insert(conns, con)
	return con
end

local function shrinkBot(b, pos, onDone)
	local t0 = os.clock()
	local con
	con = RS.Heartbeat:Connect(function()
		local k = (os.clock() - t0) / 0.35
		if k >= 1 then
			con:Disconnect()
			onDone()
			return
		end
		placeBot(b, CFrame.new(pos), math.max(1 - k, 0.05), os.clock())
	end)
	table.insert(conns, con)
end

local function burst(pos)
	local p = new("Part", {Anchored = true, CanCollide = false, CanQuery = false, Transparency = 1, Size = Vector3.new(1, 1, 1), Position = pos}, fxFolder)
	local e = new("ParticleEmitter", {
		Color = ColorSequence.new(BOT_COLOR), LightEmission = 1, Rate = 0,
		Lifetime = NumberRange.new(0.4, 0.8), Speed = NumberRange.new(8, 20),
		SpreadAngle = Vector2.new(180, 180),
		Size = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.6), NumberSequenceKeypoint.new(1, 0)}),
	}, p)
	e:Emit(40)
	task.delay(1.5, function() p:Destroy() end)
end

-- ===== ver por los ojos del jugador =====
local function hideTarget(ch, on)
	if not ch then return end
	for _, d in ipairs(ch:GetDescendants()) do
		if d:IsA("Decal") and d.Parent and d.Parent.Name == "Head" then
			if on then
				hiddenOrig[d] = d.Transparency
				d.Transparency = 1
			elseif hiddenOrig[d] ~= nil then
				d.Transparency = hiddenOrig[d]
				hiddenOrig[d] = nil
			end
		elseif d:IsA("BasePart") and (d.Name == "Head" or (d.Parent and d.Parent:IsA("Accoutrement"))) then
			d.LocalTransparencyModifier = on and 1 or 0
		end
	end
end

local function freeze(on)
	local hum = lp.Character and lp.Character:FindFirstChildOfClass("Humanoid")
	if not hum then
		saved = nil
		return
	end
	if on then
		saved = saved or {ws = hum.WalkSpeed, jp = hum.JumpPower, jh = hum.JumpHeight}
		hum.WalkSpeed = 0
		hum.JumpPower = 0
		hum.JumpHeight = 0
	elseif saved then
		hum.WalkSpeed = saved.ws
		hum.JumpPower = saved.jp
		hum.JumpHeight = saved.jh
		saved = nil
	end
end

local function stopSpyView()
	pcall(function() RS:UnbindFromRenderStep("SpyCam") end)
	hideTarget(hiddenChar, false)
	hiddenChar = nil
	local cam = workspace.CurrentCamera
	cam.CameraType = Enum.CameraType.Custom
	local hum = lp.Character and lp.Character:FindFirstChildOfClass("Humanoid")
	if hum then cam.CameraSubject = hum end
	cam.FieldOfView = fov0
	freeze(false)
	hud.Visible = false
end

local function startSpy()
	state = "spying"
	local cam = workspace.CurrentCamera
	cam.CameraType = Enum.CameraType.Scriptable
	cam.FieldOfView = FOV_SPY
	freeze(true)
	panel.Visible = false
	hud.Visible = true
	rec.Text = "REC  " .. target.DisplayName
	flash.BackgroundTransparency = 0.2
	TS:Create(flash, TweenInfo.new(0.5), {BackgroundTransparency = 1}):Play()
	pcall(function() RS:UnbindFromRenderStep("SpyCam") end)
	RS:BindToRenderStep("SpyCam", Enum.RenderPriority.Camera.Value + 1, function()
		local ch = target and target.Character
		if ch ~= hiddenChar then
			hideTarget(hiddenChar, false)
			hiddenChar = ch
			hideTarget(ch, true)
		end
		local head = ch and ch:FindFirstChild("Head")
		if head then cam.CFrame = head.CFrame * CFrame.new(0, 0.2, -0.9) end
	end)
end

local function exitSpy(msg)
	if state ~= "spying" then return end
	local head = target and target.Character and target.Character:FindFirstChild("Head")
	local from = head and head.Position
	stopSpyView()
	target = nil
	if msg then toast(msg, 3) end
	if not from then
		state = "idle"
		return
	end
	state = "returning"
	local b = makeBot()
	bot = b
	flyBot(b, from, function()
		local h = lp.Character and lp.Character:FindFirstChild("Head")
		return h and h.Position
	end, function()
		b.model:Destroy()
		bot = nil
		state = "idle"
	end)
end

-- ===== enviar el nanobot =====
local function launch(p)
	if state == "flying" or state == "entering" or state == "returning" then
		toast("El nanobot esta ocupado", 2)
		return
	end
	local ch = p.Character
	if not (ch and ch:FindFirstChild("Head")) then
		toast(p.DisplayName .. " no tiene personaje", 2)
		return
	end
	local startPos = nil
	if state == "spying" then
		local oh = target and target.Character and target.Character:FindFirstChild("Head")
		startPos = oh and oh.Position
		stopSpyView()
	end
	if not startPos then
		local lh = lp.Character and lp.Character:FindFirstChild("Head")
		if not lh then
			toast("Sin personaje", 2)
			return
		end
		startPos = lh.Position + Vector3.new(0, 1.5, 0)
	end

	target = p
	state = "flying"
	panel.Visible = false
	toast("Nanobot enviado a " .. p.DisplayName, 3)
	local b = makeBot()
	bot = b
	flyBot(b, startPos, function()
		local h = target and target.Character and target.Character:FindFirstChild("Head")
		return h and h.Position
	end, function(ok)
		if not ok then
			b.model:Destroy()
			bot = nil
			state = "idle"
			target = nil
			toast("Se perdio la senal del jugador", 3)
			return
		end
		state = "entering"
		local h = target.Character and target.Character:FindFirstChild("Head")
		local hp = h and h.Position or startPos
		burst(hp)
		shrinkBot(b, hp, function()
			b.model:Destroy()
			bot = nil
			if target and target.Character and target.Character:FindFirstChild("Head") then
				startSpy()
			else
				state = "idle"
				target = nil
				toast("Se perdio la senal del jugador", 3)
			end
		end)
	end)
end

-- ===== lista de jugadores =====
local function refreshList()
	for _, c in ipairs(list:GetChildren()) do
		if c:IsA("TextButton") then c:Destroy() end
	end
	for _, p in ipairs(Players:GetPlayers()) do
		if p ~= lp then
			local b = new("TextButton", {
				Size = UDim2.new(1, -6, 0, 34), Text = p.DisplayName .. "  (@" .. p.Name .. ")",
				BackgroundColor3 = Color3.fromRGB(28, 36, 52), TextColor3 = Color3.new(1, 1, 1),
				Font = Enum.Font.Gotham, TextSize = 13, BorderSizePixel = 0, TextTruncate = Enum.TextTruncate.AtEnd,
			}, list)
			b.MouseButton1Click:Connect(function() launch(p) end)
		end
	end
end

local function setPanel(v)
	panel.Visible = v
	if v then refreshList() end
end

closeP.MouseButton1Click:Connect(function() setPanel(false) end)
swBtn.MouseButton1Click:Connect(function() setPanel(true) end)
exitBtn.MouseButton1Click:Connect(function() exitSpy() end)

table.insert(conns, Players.PlayerAdded:Connect(function()
	if panel.Visible then refreshList() end
end))
table.insert(conns, Players.PlayerRemoving:Connect(function(p)
	if p == target and state == "spying" then exitSpy("El jugador salio del juego") end
	task.defer(function()
		if panel.Visible then refreshList() end
	end)
end))

-- ===== la tablet en el inventario =====
local function makeTool()
	local t = new("Tool", {Name = "Spy Tablet", CanBeDropped = false, RequiresHandle = true, ToolTip = "Spy Tablet"}, nil)
	local h = new("Part", {Name = "Handle", Size = Vector3.new(1.6, 0.18, 1.1), Color = Color3.fromRGB(25, 28, 36), Material = Enum.Material.SmoothPlastic, CanCollide = false}, t)
	local s = new("Part", {Name = "Screen", Size = Vector3.new(1.4, 0.04, 0.9), Color = BOT_COLOR, Material = Enum.Material.Neon, CanCollide = false, Massless = true}, t)
	s.CFrame = h.CFrame * CFrame.new(0, 0.11, 0)
	new("WeldConstraint", {Part0 = h, Part1 = s}, h)
	t.Equipped:Connect(function() setPanel(true) end)
	t.Unequipped:Connect(function() setPanel(false) end)
	t.Activated:Connect(function() setPanel(not panel.Visible) end)
	return t
end

local function ensureTool()
	if tool and tool.Parent then return end
	local bp = lp:FindFirstChildOfClass("Backpack") or lp:WaitForChild("Backpack", 5)
	if not bp then return end
	tool = makeTool()
	tool.Parent = bp
end
ensureTool()

table.insert(conns, lp.CharacterAdded:Connect(function()
	if state == "spying" then
		stopSpyView()
		target = nil
		state = "idle"
	end
	task.wait(1)
	ensureTool()
end))

-- ===== cerrar todo =====
genv.SpyOff = function()
	for _, c in ipairs(conns) do pcall(function() c:Disconnect() end) end
	pcall(stopSpyView)
	pcall(function() if tool then tool:Destroy() end end)
	pcall(function() fxFolder:Destroy() end)
	pcall(function() gui:Destroy() end)
end

toast("Spy Tablet lista: equipala desde tu inventario", 4)

How to Execute Universal Script – Spy

Step 1: Copy Code: Click the Copy Code button in the viewer above to grab the clean Lua loadstring.

Step 2: Launch Executor: Open a compatible, unpatched executor. If you need one, check our Roblox Executors Directory.

Step 3: Join Experience: Launch Roblox and join Universal Script.

Step 4: Attach & Run: Attach/inject your executor into the Roblox process, paste the code into the script tab, and press Execute.

Created By

Noobscripter7
Noobscripter7
Script Creator
View Author Profile

Features & Information

Execute Universal Script – Spy. Key system required, created by Noobscripter7, updated Oct 18, 2026. Tested and working on supported executors.

Script Changelog (1)

@Noobscripter7Oct 18, 2026

Create script

Community Comments (0)

No comments yet for this script.

Frequently Asked Questions

How do I execute Universal Script – Spy in Roblox?

To run Universal Script – Spy, copy the Lua loadstring from the code viewer above, launch Roblox and join Universal Script, attach a working executor (such as Potassium, Solara, or Delta from our Executors directory), paste the code into your executor console, and click Execute.

Is Universal Script – Spy keyless or does it require an access key?

Universal Script – Spy requires an access key. You can retrieve the official key directly using the Get Script Key link provided above.

Is Universal Script – Spy currently safe and working?

This script is active and operational. Always test scripts using a secondary (alt) Roblox account to safeguard your main profile against anti-cheat bans.