Grand opening25% off everything with FAM-261023-261025-UL4B9this weekendAdded for you at checkout Halloween Edition36 maps, limited runlimited runShop the drop

FREE TOOL · GetHashKey / joaat

FiveM hash calculator

Type a model, ped or weapon name and the joaat hash appears as you type — the unsigned number, the negative one your console prints, and the hex the dumps are written in, all three at once, because they are all the same thirty-two bits. Paste a hash into the second box and it searches back the other way.

The arithmetic is done in your browser; nothing is sent anywhere. The implementation is checked against the hashes this site already stores for 921 vehicles, 860 peds and 113 weapons — all 1,894 match.

Unsigned (uint32)3078201489
Signed (int32)-1216765807
Hex0xB779A091

10110111011110011010000010010001

That is a known vehicle model — adder.

Searching 921 vehicle models, 860 ped models and 113 weapons. A joaat hash cannot be undone, so a reverse lookup is always a search over names somebody already has.

GetHashKey("adder") = -1216765807

Client or server — GetHashKey exists on both, and the number it returns is the same on both.

-- Three ways to say the same thing. The engine sees one number.
local byName   = GetHashKey("adder")   -- -1216765807
local byNumber = -1216765807               -- what print() shows you
local byHex    = 0xB779A091                  -- what the dumps are written in

print(byName == byNumber)                 -- true
print(byName == byHex)                    -- true

-- So a model can be requested either way.
local model = `adder`                  -- the backtick is Lua 5.4 sugar for GetHashKey
RequestModel(model)
while not HasModelLoaded(model) do
    Wait(0)
end

HOW TO USE IT

One number, three ways of writing it

A hash is thirty-two bits. How it looks on screen depends only on what printed it. Lua prints a signed integer, so anything with the top bit set comes out negative; the published model dumps use unsigned decimal; the native documentation and CodeWalker use hex. Treating those as three different values is the single most common reason a model comparison silently never matches.

Requesting a model — name, number and hex are interchangeable

Client-side. The backtick syntax is FiveM's Lua 5.4 compile-time hash — it is GetHashKey evaluated once instead of every call.

-- Three ways to say the same thing. The engine sees one number.
local byName   = GetHashKey("adder")   -- -1216765807
local byNumber = -1216765807               -- what print() shows you
local byHex    = 0xB779A091                  -- what the dumps are written in

print(byName == byNumber)                 -- true
print(byName == byHex)                    -- true

-- So a model can be requested either way.
local model = `adder`                  -- the backtick is Lua 5.4 sugar for GetHashKey
RequestModel(model)
while not HasModelLoaded(model) do
    Wait(0)
end
Comparing a hash you did not choose

Client-side. GetEntityModel and GetSelectedPedWeapon both return hashes, so the other side of the comparison has to be a hash too.

-- The useful half: checking what the player is in or holding.
-- Both natives return a hash, never a string, so compare against a hash.
CreateThread(function()
    while true do
        Wait(500)
        local ped = PlayerPedId()
        local veh = GetVehiclePedIsIn(ped, false)

        if veh ~= 0 and GetEntityModel(veh) == GetHashKey("adder") then
            print("in an Adder")
        end

        -- GetSelectedPedWeapon returns WEAPON_UNARMED's hash when empty-handed,
        -- which is 2725352035 -- not 0. Comparing against 0 never matches.
        if GetSelectedPedWeapon(ped) == GetHashKey("WEAPON_PISTOL") then
            print("holding a pistol")
        end
    end
end)
The lowercase step

The hash folds A–Z to a–z before it starts, which is why case never matters and why a wrong name, not a wrong capitalisation, is always the real bug.

Why the arithmetic is fussy

Each round multiplies and shifts inside thirty-two bits. JavaScript numbers are doubles, so this tool uses Math.imul and >>> 0 to keep every step exact. Calculators that skip that drift on long names.

What a reverse lookup really is

A search, not a decode. joaat discards information, so the only route from number back to name is hashing names you already have — which is why this page says when a hash is simply not in its list.

Object models are elsewhere

The 21,631 createable objects are too large to ship into a browser tab, so they live on the prop list with a search of their own.

QUESTIONS

About hashes and GetHashKey

What is GetHashKey in FiveM?
GetHashKey turns a string into the 32-bit number the game stores internally. Every vehicle, ped, weapon, object and animation dictionary has a name, but the engine only ever compares hashes, so GetHashKey("adder") gives 3078201489 and CreateVehicle accepts either. The algorithm is Jenkins one-at-a-time, usually written joaat, and it is the same function on the client and the server.
Why do GetHashKey("PROP_X") and GetHashKey("prop_x") give the same number?
Because the hash lowercases the string before it starts. The engine walks the bytes and folds A–Z down to a–z first, so the case you type is thrown away before any arithmetic happens. That is why model names in dumps are written lowercase and why a capitalised model name in your script still works. It also means capitalisation can never be the reason a model fails to load — if it fails, the name itself is wrong.
Why is the hash in my server console negative?
Because a hash is 32 bits and Lua printed it as a signed integer. If the top bit is set, the same bits read as a negative number: 3078201489 unsigned is -1216765807 signed, and 0xB779A091 is both. Nothing has gone wrong and nothing needs converting — add 4294967296 to a negative hash to get the unsigned one, or just paste it into the box above.
Can I turn a hash back into a name?
Not by calculation. joaat throws information away, so there is no inverse — the only way back is to hash a list of names you already have and look for a match. The reverse box on this page does exactly that over the vehicle, ped and weapon names this site keeps, and says plainly when a number is not in that list. Anyone claiming to decode an arbitrary hash is hashing a bigger list, not reversing anything.
Do two different names ever produce the same hash?
In principle, yes. A 32-bit hash has about 4.29 billion possible values and there are far more possible strings than that, so two names colliding is mathematically unavoidable rather than a bug. We have not verified a collision between two real GTA asset names and are not going to claim one. What is worth taking from it: the game compares nothing but hashes, so it cannot tell two colliding names apart either — keep your own resource and event names distinctive rather than short and generic.