Reading player input: controls and keys
Almost every interaction in FiveM starts with a key. Open a door, talk to an NPC, loot a body, sprint, holster a weapon. FiveM does not hand you raw keyboard codes for these. It hands you control IDs, stable numbers that survive the player remapping their keys. This lesson teaches you to read those controls in a client thread, then proves it with a resource that detects the E key near a coordinate and takes over a second key while a menu is open.
Control IDs, not keycodes
When you press E, your operating system sees a raw keyboard scancode. FiveM does not. FiveM works one layer above that, in terms of controls: named game actions like "context interact", "jump", or "vehicle handbrake". Each control has a stable number, the control ID. You ask the game "is control 38 pressed right now" and the game answers, no matter which physical key the player has bound to that action.
This matters because players rebind keys. Someone on an AZERTY keyboard, someone using a controller, someone who moved interact off E on purpose, all of them still trigger control 38 when they hit their bound key. If you read raw keycodes you break for every one of those players. If you read control IDs you work for all of them. This is why every input native in this lesson takes a control ID, never a letter.
Here are the control IDs you will reach for most often, straight from the FiveM controls reference:
Do not memorize this table. The short descriptions above are informal notes on how scripts commonly use each control, not the official names. On the controls reference each ID has an official INPUT_ name (for example 38 is INPUT_PICKUP, 47 is INPUT_DETONATE, 246 is INPUT_MP_TEXT_CHAT_ALL); the default key is what matters here, and many scripts repurpose a control regardless of its original name. Bookmark the controls reference and look the number up when you need it, the same way you look up any other native.
The input group argument
Every input native starts with a number you will see set to 0 almost everywhere:
IsControlJustPressed(0, 38)
That leading 0 is the input group (also called the padIndex). It tells the game which input layer to read. Group 0 is the normal "in the world, controlling your player" layer, and it is what you want roughly all of the time. The other groups exist for special contexts like camera or frontend menus, and you will almost never touch them. Treat 0 as the default and move on. The control ID, the second argument, is the part that actually changes.
A player remaps interact from E to T. You wrote IsControlJustPressed(0, 38). Does your code still fire for them?
Yes. 38 is the control ID for the interact action, not the letter E. When the player rebinds interact to T, the game maps T to control 38 for that player. Your check reads the control, so it fires on T for them and on E for everyone who left the default. That is the entire reason FiveM gives you control IDs instead of raw keycodes: you write against the action, the player owns the key.
Keep reading the full lesson
Sign in to start, then unlock every step of this lesson and the full FiveM School with a membership.
- Build it
- How it works
- If something went wrong
- What you can do now
- Try it yourself
The remainder of Reading player input: controls and keys is available to FiveM School members.