Skip to main content

Roblox API Essentials

These are the services and APIs you'll use in almost every script. Learn these well — everything else builds on top of them.

Getting Services

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local CoreGui = game:GetService("CoreGui")
local HttpService = game:GetService("HttpService")

Players Service

local Players = game:GetService("Players")

-- The local player (you)
local me = Players.LocalPlayer

-- All connected players
for _, player in Players:GetPlayers() do
print(player.Name, player.UserId)
end

-- React to players joining/leaving
Players.PlayerAdded:Connect(function(player)
print(player.Name .. " joined")
end)

Players.PlayerRemoving:Connect(function(player)
print(player.Name .. " left")
end)

The LocalPlayer object gives you:

  • .Name — username
  • .UserId — numeric ID
  • .Character — their character model (or nil if not spawned)
  • .CharacterAdded — fires when a new character spawns
  • .Team — their Team object
  • .DisplayName — display name (may differ from Name)

Characters and Humanoids

The character is a Model in workspace containing the player's body parts:

local me = Players.LocalPlayer
local char = me.Character or me.CharacterAdded:Wait()

-- Key parts
local hrp = char:WaitForChild("HumanoidRootPart") -- position/movement
local humanoid = char:WaitForChild("Humanoid")
local head = char:WaitForChild("Head")

-- Humanoid properties
print(humanoid.Health) -- current HP
print(humanoid.MaxHealth) -- max HP
humanoid.WalkSpeed = 50 -- movement speed (client-only change)
humanoid.JumpPower = 100 -- jump height (client-only)

-- Humanoid states
humanoid.Died:Connect(function()
print("I died")
end)

humanoid.StateChanged:Connect(function(old, new)
print("state:", new) -- e.g. "Running", "Jumping", "Freefall"
end)

Getting another player's character:

local target = Players:FindFirstChild("TargetName")
if target and target.Character then
local theirHRP = target.Character:FindFirstChild("HumanoidRootPart")
end

Workspace

local ws = game.Workspace -- or workspace (global shorthand)

-- Camera
local cam = ws.CurrentCamera
print(cam.CFrame) -- where the camera is
print(cam.FieldOfView) -- FOV in degrees
cam.FieldOfView = 90 -- change it (client-only)

-- World properties
ws.Gravity = 196.2 -- default is 196.2

-- Finding things
ws:FindFirstChild("Name") -- returns child or nil
ws:WaitForChild("Name", timeout) -- waits up to timeout seconds
ws:GetChildren() -- direct children only
ws:GetDescendants() -- all descendants (slow on large worlds)

Instance API

These work on any Instance (parts, models, scripts, etc.):

local inst = someInstance

-- Finding children
inst:FindFirstChild("Name") -- nil if not found
inst:FindFirstChildOfClass("Humanoid") -- by class name
inst:FindFirstChildWhichIsA("BasePart") -- class or subclass
inst:WaitForChild("Name") -- yields until found
inst:WaitForChild("Name", 5) -- timeout after 5s

-- Checking
inst:IsA("Model") -- true if Model or subclass
inst.ClassName -- exact class: "Model", "Part", "RemoteEvent"
inst.Name -- instance name
inst.Parent -- parent instance
inst:GetFullName() -- "workspace.PlayerName.HumanoidRootPart"

-- Tree traversal
inst:GetChildren() -- array of direct children
inst:GetDescendants() -- all descendants (can be thousands)

RunService

RunService gives you per-frame events:

local RS = game:GetService("RunService")

-- Heartbeat: fires every frame AFTER physics (most common for scripts)
RS.Heartbeat:Connect(function(deltaTime)
-- deltaTime is seconds since last frame (~0.016 at 60fps)
end)

-- RenderStepped: fires every frame BEFORE rendering (use for camera)
RS.RenderStepped:Connect(function(deltaTime)
end)

-- Stepped: fires every frame BEFORE physics
RS.Stepped:Connect(function(time, deltaTime)
end)

-- BindToRenderStep: lets you control render order with priority
RS:BindToRenderStep("MyStep", Enum.RenderPriority.Camera.Value + 1, function(dt)
end)
-- Cleanup: RS:UnbindFromRenderStep("MyStep")

Use Heartbeat for most per-frame logic (ESPs, loops). Use RenderStepped or BindToRenderStep when you need to run just before the frame renders (camera, aim).

UserInputService

local UIS = game:GetService("UserInputService")

-- Key/mouse events
UIS.InputBegan:Connect(function(input, gameProcessed)
-- gameProcessed = true if Roblox UI consumed the input (e.g. chat box)
if gameProcessed then return end

if input.KeyCode == Enum.KeyCode.E then
print("E pressed")
end
if input.UserInputType == Enum.UserInputType.MouseButton1 then
print("Left click")
end
end)

UIS.InputEnded:Connect(function(input, gameProcessed)
-- key/button released
end)

-- Continuous check (use in loops)
if UIS:IsKeyDown(Enum.KeyCode.LeftShift) then
-- shift is held
end

-- Mouse position
local mousePos = UIS:GetMouseLocation() -- Vector2, screen pixels

Mouse Object

The player's mouse gives you world-space information:

local mouse = Players.LocalPlayer:GetMouse()

-- Where the mouse points in 3D space
print(mouse.Hit) -- CFrame (position + rotation)
print(mouse.Hit.Position) -- Vector3

-- What instance the mouse is over
print(mouse.Target) -- Instance or nil

-- Screen position
print(mouse.X, mouse.Y) -- screen pixels

-- Ray from camera through mouse
local ray = workspace:Raycast(
mouse.UnitRay.Origin,
mouse.UnitRay.Direction * 1000,
RaycastParams.new()
)

Camera

local cam = workspace.CurrentCamera

-- Read camera state
print(cam.CFrame) -- position + orientation
print(cam.FieldOfView) -- FOV degrees
print(cam.CameraType) -- "Custom", "Scriptable", etc.

-- World to screen conversion (essential for ESP)
local screenPos, onScreen = cam:WorldToViewportPoint(worldPos)
-- screenPos.X, screenPos.Y = screen coordinates
-- screenPos.Z > 0 means in front of camera (visible)

if onScreen and screenPos.Z > 0 then
-- draw something at screenPos.X, screenPos.Y
end

-- Screen to world ray
local ray = cam:ViewportPointToRay(screenPos.X, screenPos.Y)

Events: Connect, Disconnect, Once, Wait

local connection = someEvent:Connect(function(...)
-- fires every time event fires
end)

-- Disconnect when done
connection:Disconnect()

-- Fire once, then auto-disconnect
someEvent:Once(function(...)
end)

-- Yield until event fires, returns the event arguments
local arg1, arg2 = someEvent:Wait()

Store connections when you need to clean them up:

local connections = {}
table.insert(connections, RS.Heartbeat:Connect(myFn))
table.insert(connections, UIS.InputBegan:Connect(myOtherFn))

-- Cleanup all at once
for _, conn in connections do
conn:Disconnect()
end
connections = {}

CoreGui

CoreGui is the Roblox system UI layer. You can parent your own UI here — it persists across character respawns and isn't destroyed when the game resets player GUIs:

local CoreGui = game:GetService("CoreGui")

local container = Instance.new("ScreenGui")
container.Name = "MyContainer"
container.ResetOnSpawn = false
container.Parent = CoreGui -- only executors can do this

This is where you should parent ESP highlights and billboard labels so they don't get destroyed when your character reloads.