How Keys Work#
A key is a vehiclekeys item that carries a plate. Whenever the script has to decide whether a player may use a car — locking it, starting the engine, swapping its plate, fitting a tracker — the server answers, and any one of these is enough:
Check | Grants access when |
|---|---|
Master key | The player carries |
A key for this car | A key item with the car's plate. The model written on the key does not have to match, so a car reported under another name still opens. |
Ownership | The player owns the car in the framework's vehicle table and |
Driving only | The model is exempt (no-lock list or a whitelist), or this player hotwired the car during this session. |
Plates and models are compared trimmed and upper-cased, so abc 123 and ABC 123 are the same key.
Config.VehicleKeysItem = 'vehiclekeys' -- the key item
Config.AdminKeyItem = 'adminvehiclekey' -- the master key
Config.OnlyAdminsCanUseAdminKey = true -- master-key access for admins only
Config.OwnerAccessWithoutKey = true -- database owners need no key itemKeys and ownership are separate on purpose. A player can hold the key to a car they do not own — a friend's, a stolen one — and, with
OwnerAccessWithoutKeyoff, an owner who loses every key is locked out of their own car until they recover one.
Locking and Unlocking#
Press U (/usekey) beside a car you can use, or use a key item. On foot, the character clicks the fob with the key in hand; the doors lock or unlock for everyone, the lights flash twice and a notification says which. The keybind works on the nearest car; a key item works on the car it belongs to.
Setting | Default | What it does |
|---|---|---|
| 5.0 | How close, in metres, the player must be to lock or unlock — keybind, key item or master key. |
| 20.0 | How far a key item looks for its own car. It must still be the closest car, and within reach. |
| fob click | The animation and the key prop held while locking. |
| true | Play the fob beep through interact-sound — the file named in |
| false | Mute GTA's own door lock and unlock sounds. |
Config.LockDistance = 20.0
Config.UseCommandKeyDistance = 5.0
Config.KeySettings = {
Animation = {
Dict = 'anim@mp_player_intmenu@key_fob@',
Clip = 'fob_click_fp',
Duration = 900,
Flag = 48
},
Prop = {
Model = 'p_car_keys_01'
}
}
Config.Sounds = true
Config.SoundsDisableDefault = false
Config.SoundsVolume = 0.3
Config.SoundsFileName = 'carkeys'
Config.SoundsDistance = 4.0The server remembers each car's lock state by plate, so a garage can put a car back out exactly as it was left — see Commands and Exports.
The Engine#
M (/engine) switches the engine of the car you are driving on and off. With RequireKey, only a player who may use the car can start it — anybody else reads You are not allowed to control this engine.
Setting | Default | What it does |
|---|---|---|
| true | The engine needs access to the car. |
| true | Getting out with the engine running leaves it running — even when holding the exit key. |
| false | Start the engine the moment a player with access takes the driver's seat. |
| true | The front wheels stay turned the way they were when the driver got out. |
| true | The throttle does not start a stopped engine — it has to be switched on. |
Config.Engine = {
RequireKey = true,
KeepEngineOn = true,
AutoStartOnEnter = false,
MaintainSteeringAngle = true,
DisableAutoStartWithAccelerate = true
}Locked NPC Traffic#
Every few seconds the script looks at the cars around each player. Any car with an NPC at the wheel is locked and flagged as needing a hotwire, so taking one means a lockpick or the driver's key at gunpoint.
Config.NpcVehicleLock = {
Enabled = true,
ScanDistance = 40.0, -- metres around the player
ScanInterval = 2500, -- ms between scans
LockedState = 2 -- native lock state applied (2 = locked)
}Cars that never need a key#
Models in Config.NoLockVehicles are never locked by the scan, are unlocked the moment a player tries to get in, and drive without a key or a hotwire — handy for emergency fleets that live outside the key system. Use spawn names in any case, or model hashes:
Config.NoLockVehicles = {
'police',
'ambulance',
}Models in the hotwire or lockpick Whitelist — bicycles by default — need no key to ride either.
Hotwiring#
Sit at the wheel of a car you have no access to and the engine is cut, the pedals stop answering and a prompt appears above the car: Press H to hotwire the vehicle. Press H (/hotwire): a progress circle runs with the hotwire animation, then an ox_lib skill check. Pass it and the engine starts — and, with GiveKeyOnSuccess, a key for that plate lands in the inventory. Fail it and you can try again.
Setting | Default | What it does |
|---|---|---|
| true | Off removes the key requirement for driving: any car a player gets into will go. |
| 10000 | The progress circle, in ms. |
| easy, easy, medium | One ox_lib circle per entry, in order. |
| true | A successful hotwire also hands over a key. |
| false · 0 | Refuse to start unless this many police are online. |
| 35 | Percent chance, on every attempt — passed or failed — that police are alerted. |
| bicycles | Models that never need hotwiring — or a key. |
Config.Hotwire = {
Enabled = true,
Duration = 10000,
SkillCheck = { 'easy', 'easy', 'medium' },
GiveKeyOnSuccess = true,
RequirePolice = false,
MinimumPolice = 0,
DispatchChance = 35,
Whitelist = { 'bmx', 'cruiser', 'enduro', 'fixter', 'scorcher', 'tribike', 'tribike2', 'tribike3' }
}Lockpicking#
Use a carlockpick — or type /lockpick — on foot beside a locked car, and an ox_lib skill check begins. A pass unlocks the doors; a fail leaves them shut. Either way the alarm may go off and the police may be alerted. Picking the lock only opens the doors: the engine still needs a key or a hotwire.
The caradvancedlockpick works the same way, from the item only, and with AdvancedBypassPolice it ignores the police requirement.
Outcome | What happens to the lockpick |
|---|---|
Success | Kept with a |
Failure | Removed when |
Setting | Default | What it does |
|---|---|---|
| 4.0 | How close the car has to be. |
| easy, easy, medium | The skill check sequence. |
| true · 0 | Police needed online. With |
| true | The advanced lockpick skips the police requirement. |
| 45 · 35 | Percent chances, rolled on success and on failure. |
| false | Hand over a key as well as opening the doors. |
| bicycles | Models that cannot be lockpicked — and need no key to ride. |
| 12000 | Not used by the current lockpick, which goes straight to the skill check. |
Config.Lockpick = {
Enabled = true,
Item = 'carlockpick',
AdvancedItem = 'caradvancedlockpick',
Distance = 4.0,
Duration = 12000,
SkillCheck = { 'easy', 'easy', 'medium' },
RequirePolice = true,
MinimumPolice = 0,
AdvancedBypassPolice = true,
DispatchChance = 45,
AlarmChance = 35,
KeepChance = 50,
RemoveOnFail = true,
RemoveAdvancedOnFail = true,
GiveKeyOnSuccess = false,
Whitelist = { 'bmx', 'cruiser', 'enduro', 'fixter', 'scorcher', 'tribike', 'tribike2', 'tribike3' }
}Stealing Keys from NPC Drivers#
Draw a gun, aim at an NPC driving a car and press G (/stealnpckey). A driver who gives in steps out with their hands up, a progress circle runs while you take the key, and they run for it. Some drivers — ShootChance percent of them — pull a pistol and fight back instead.
It only starts when all of this is true:
The player is armed and aiming at an NPC — not a player — in a driver's seat, within
MaxDistance.The player does not already have access to that car, and its driver has not been robbed already.
The
Cooldownsince the last attempt has passed, and enough police are online.
Setting | Default | What it does |
|---|---|---|
| 5000 · 6000 | Taking the key, and the wait between attempts, in ms. |
| 12.0 | How far away the driver can be. |
| 25 | Percent of drivers who fight back. |
| true | The player may abort while taking the key. |
| 300.0 | How far the robbed driver runs. |
| true · 2 | Police needed online. |
| 60 | Rolled after a robbery, and when a driver fights back. |
| true | The driver gets out before handing over the key. |
| true | Off: the robbery gives no key, and the car still has to be hotwired. |
| true | Unlock the doors after the robbery. Off keeps them locked. |
Config.NpcDriverKeySteal = {
Enabled = true,
Duration = 5000,
Cooldown = 6000,
MaxDistance = 12.0,
ShootChance = 25,
ProgressCanCancel = true,
NpcFleeDistance = 300.0,
RequirePolice = true,
MinimumPolice = 2,
DispatchChance = 60,
ForceNpcExit = true,
GiveKeysOnSuccess = true,
LeaveUnlocked = true
}Sharing Keys#
The key transfer menu#
F7 (/keytransfer) opens a window with the players around you — within 10 m, nearest first — and the keys you hold. Pick one of each and press Transfer Key: your character hands it over, and the other player is told who gave them which key.
The giver keeps their own key — a transfer hands over a copy. It is refused when the other player has moved more than 8 m away or already holds that key.
Config.KeyTransfer = {
Enabled = true, -- false removes the menu, its command and its key
CommandName = 'keytransfer',
EnableKeyMapping = true, -- false: no key bound, the command still works
Key = 'F7'
}/givekeys#
Admins can give the key of the car they are sitting in with /givekeys [id] — to that server id, or to the nearest player within 8 m when no id is given. The receiver gets a key even if they already hold one.
The interaction menu#
F4 (/vehiclekeys_interaction), inside a vehicle, opens a quick menu: use the key, the key transfer menu, clean keys and — at the wheel of a boat — the anchor. Each entry disappears when its feature is switched off.
Cleaning Keys#
Job vans and borrowed cars leave keys behind. /cleankeys removes, in one go, every key whose plate is not a car the player owns in the database, and says how many went. /openkeys opens a small menu with the same action.
Config.CleanKeys = {
Enabled = true,
CommandName = 'cleankeys',
MenuCommandName = 'openkeys' -- false or nil: no menu command
}Recovering a Lost Key#
A bank clerk stands at the spot set in the config. Walk up and press E: a menu lists every car you own as MODEL [PLATE]. Pick one and a new key goes into your inventory — free, and only if you do not already hold a key for that plate.
Config.KeyRecovery = {
Enabled = true,
NPCs = { -- add as many clerks as you like
{
coords = vec4(214.219788, -817.727478, 30.661499, 249.448822),
model = 'cs_bankman'
}
},
TextUiDistance = 2.0, -- where the prompt appears
InteractionDistance = 2.0, -- where the key works
OpenControl = 'E' -- 'E', 'G', 'H' or a control number
}The Key Copy Shop#
A mechanic with a toolbox — and a Copy keys blip on the map — sells spare keys, plates and screwdrivers. Press E beside him, or use the target option when targeting is on.
Service | Price | What it does |
|---|---|---|
Copy nearby vehicle key | $500 | A spare for the car parked right beside you, within |
Copy from owned key | $250 | Pick any key you hold from a list and get a spare. Only offered when you hold one. |
Buy plate | $500 | A plate item with a fresh number no owned car uses. |
Buy screwdriver | $150 | The tool for plate swaps. |
A copy is made even when you already hold that key — that is the point: one to keep, one to give. Payment comes from the account in Account — money on ESX, cash on QBCore. With RequireOwnership, copies are only cut for cars the player owns in the database.
Config.CopyShop = {
Enabled = true,
TextUiDistance = 2.0, -- where the prompt appears
InteractDistance = 2.0, -- where the key works, and how close the car must be
PedRenderDistance = 10.0, -- the mechanic spawns within this range
UseBlip = true,
UseTarget = true, -- also needs Config.UseTarget
OpenControl = 'E',
Npc = {
Model = 's_m_y_xmech_01',
Coords = vec4(-31.40, -1647.44, 29.28, 68.45),
-- Animation and Prop: the idle pose and the toolbox in his hand
},
Blip = { Name = 'Copy keys', Sprite = 186, Colour = 3, Scale = 0.8 },
Services = { -- switch each one off on its own
CopyNearbyVehicleKey = true,
CopyFromOwnedKey = true,
Plate = true,
Screwdriver = true
},
RequireOwnership = false,
Prices = {
CopyNearbyVehicleKey = 500,
CopyFromOwnedKey = 250,
Plate = 500,
Screwdriver = 150
},
Account = Config.Framework == 'esx' and 'money' or 'cash',
Items = {
Plate = Config.Plate.ItemName,
Screwdriver = Config.Plate.ToolItemName
}
}License Plates#
A plate item carries a plate number. Stand beside a car with a screwdriver in your pockets and use the plate: the number is checked, a progress circle runs while you work, and the car wears the new plate for everyone.
What a swap changes#
Where | What happens |
|---|---|
The car | Shows the new plate to every player. |
The database |
|
Garage |
|
Trunk and glovebox | ox_inventory or qs-inventory move them to the new plate; legacy |
GPS tracker | Moves to the new plate. |
Keys | The player's keys for that car are re-cut for the new plate. |
The old plate | Comes back as a plate item, so the swap can be undone. |
Last, the server event vehiclekeys:server:plateChanged fires with the old and the new plate, for any other script that stores plates.
The rules#
The plate number must have the configured length — letters, numbers and the space if there is one.
It must not already belong to an owned car.
With
RequireOwnedVehicle, the player needs access to the car and the car must be in the database. Turn it off and a plate goes on any car — when that car is not in the database the change lives on the car only and nothing is saved, which is how false plates on stolen cars work.With
RequireScrewdriver, the screwdriver must be carried. It is never used up.
Config.Plate = {
Enabled = true,
Letters = 3, -- ABC
Numbers = 3, -- 123
UseSpace = true, -- ABC 123
ChangeDuration = 5000,
RequireScrewdriver = true,
RequireOwnedVehicle = true,
UseBootForTarget = false, -- not used: the swap starts from the item
ItemName = 'plate',
ToolItemName = 'screwdriver'
}A dealership or garage that generates plates can read the same format with
GetPlateFormat, so every plate on the server looks alike. GTA plates hold eight characters at most.
GPS Trackers#
Two items work together. The GPS (vehiclegps) is the tracker: use it beside a car and, after a short progress circle, it is fitted and used up — one per car. The tracker (vehicletracker) is the receiver: use it, or /tracker while carrying it, to open the list of tracked cars. Pick one and a pulsing blip and a waypoint mark it for LocateDuration.
The list shows every tracker the player fitted, and every tracker on a car they hold a key to. To strip one off, ox_target adds Remove GPS tracker to those cars: an optional skill check, a progress circle, and the GPS item comes back.
Config.Tracker = {
Enabled = true,
GPSItemName = 'vehiclegps', -- fitted to the car, used up
TrackerItemName = 'vehicletracker', -- the receiver that lists tracked cars
RequireOwnedVehicle = true, -- key access needed to fit or remove
UseTarget = true, -- removal through ox_target
UseBootForTarget = false, -- put the removal option on the boot
InstallDistance = 3.0,
RemoveDistance = 2.5,
InstallDuration = 2500,
RemoveDuration = 2500,
LocateDuration = 20000, -- how long the blip stays
EnableMenuKeyMapping = false, -- true: bind MenuKey to the menu
MenuCommand = 'tracker',
MenuKey = 'K',
RemoveMinigame = {
Enabled = true,
SkillCheck = { 'easy', 'easy', 'medium' }
},
Blip = { Sprite = 161, Colour = 1, Display = 2, Scale = 1.1, ShortRange = false }
}Diagnostics and Window Tint#
Mechanics and police plug a tablet into the nearest car — /diagnostic, or the target option Run vehicle diagnostic — and, after a scan, read a report that keeps refreshing while it is open:
Tab | Shows |
|---|---|
Overview | Model, plate, engine and body health, oil, fuel and engine temperature. |
Performance | Turbo, and the engine, brakes, transmission and suspension upgrade levels. |
Tires & Tint | Every tyre — intact or burst — on four- and six-wheel vehicles, and the window tint. |
The target option Measure window tint shines a torch at the glass and reports None, Light, Medium, Dark or Limo — a roadside check for traffic stops. Without a target resource, trigger the client event vehiclekeys:client:diagnostic:tint from a radial menu instead.
Config.Diagnostic = {
Enabled = true,
NeedKey = false, -- require access to the car to scan it
AllowedJobs = { -- an empty table lets everyone scan
mechanic = true,
police = true
},
AllowedTintJobs = {
mechanic = true,
police = true
},
UseCommand = true,
CommandName = 'diagnostic',
UseTarget = true, -- also needs Config.UseTarget
TargetDistance = 2.5,
FindVehicleDistance = 5.0,
ScanDuration = 5000,
TintMeasureDuration = 5000,
TempUnit = 'c', -- 'c' or 'f'
RefreshWhileOpen = 1500 -- ms between live updates
}Boat Anchor#
At the wheel of a boat moving slower than SpeedLimitMps, /anchor — or the interaction menu — lowers the anchor after a short progress circle and holds the boat where it is. Run it again to raise it. With UseSound, interact-sound plays anchordown and anchorup.
Config.Anchor = {
Enabled = true,
CommandName = 'anchor',
SpeedLimitMps = 2.0, -- metres per second
ProgressDuration = 1500,
AllowCancel = true,
UseSound = true,
Animation = {
Dict = 'melee@unarmed@streamed_variations',
Clip = 'plyr_takedown_front_slap'
}
}The Admin Panel#
/vkadmin opens the Admin Vehicle Manager for admins — every owned vehicle on the server, read from the framework's own table, loaded a page at a time as you scroll.
Part | What it does |
|---|---|
Search | By plate, owner identifier, or the owner's first or last name. |
Filters | All, In garage and Outside, with a total for each. |
Give Owner Key | Sends the car's key to its owner, who has to be online. |
Give Self Key | Puts the key in your own inventory. |
Go To Vehicle | Teleports you behind the car — for cars that are outside and loaded near enough for your game to see. |
Config.AdminPanel = {
Enabled = true,
CommandName = 'vkadmin',
EnableKeyMapping = false, -- true: bind Key to the panel
Key = 'F6',
PageSize = 30 -- vehicles loaded per page
}In garage and Outside come from the framework's stored flag —
storedon ESX,stateon QBCore — so they are only as accurate as your garage script keeps them.
Police Alerts#
Hotwiring, lockpicking and robbing NPC drivers each roll their own DispatchChance. When it hits, an alert goes out at the thief's position through Config.Dispatch. With default, every player whose job is in Config.PoliceJobs gets a notification and a flashing blip. Integrations covers qs-dispatch, qs-smartphone and Origen.
Config.PoliceJobs = {
police = true,
sheriff = true
}The same list is what police requirements count: every online player with one of those jobs, on duty or not.
Global Settings#
Setting | Default | What it does |
|---|---|---|
| 'en' | The language — any file in |
| 'ox_lib' | How prompts are drawn: |
| false | Target options for the copy shop and diagnostics, sized by |
| nui://qs-vehiclekeys/web/ | Where the interface loads its files. Leave as is. |
| true | Extra console output. Turn it off on a live server. |
Every value is read when the resource starts. After editing
config/main.lua, runrestart qs-vehiclekeys.



