← Back to Articles
Tutorials—• #FiveM, #ox_inventory, #QB-Core, #ESX, #How To, #Game Dev

How to Add Custom Items and Images to ox_inventory, QB-Core and ESX

Step-by-step FiveM guide: where item definitions and inventory images go in ox_inventory, QB-Core and ESX Legacy, which weight units each one uses, and the mistakes that break custom items.

FiveM inventory grid with custom item icons and the ox_inventory, QB-Core and ESX file paths for adding items

Adding a new item to a FiveM server looks like a two-minute job until the item shows up as a blank square, weighs more than the whole inventory, or quietly replaces a real weapon. This guide shows exactly where custom items and their images go in ox_inventory, QB-Core and ESX Legacy, with code you can copy and the mistakes that cost server owners the most time.

Everything below was checked against the current source code of each framework (October 2026), not against old forum posts.


The Short Version: Three Things Every Custom Item Needs

Every inventory system needs the same three pieces. Only the file names and units change.

  1. An item name in lowercase with underscores, e.g. food_donut_pink_sprinkles. This name is the ID in your scripts, in /giveitem and in the database.
  2. An item definition with a label and a weight, in the file or table your framework reads.
  3. A PNG image called <item name>.png, in the folder your inventory loads images from.
ox_inventory (ESX, Qbox)QB-Core + qb-inventoryESX Legacy without ox
Item definitionox_inventory/data/items.luaqb-core/shared/items.luaitems table in the database
Image folderox_inventory/web/images/qb-inventory/html/images/esx_inventory/web/images/ or your inventory script
Weight unitgramsgrams~kilograms (whole numbers)
Default carry limit30 000 (30 kg)120 000 (120 kg)24
Default icon size100 × 100 px100 × 100 pxdepends on the script
Where one custom FiveM item goes in ox_inventory, QB-Core and ESX: item definition file, image folder and weight unit for each framework

Step 1: Pick Item Names You Will Never Have to Change

The item name ties everything together. If the name in the config is food_donut and the file is Food_Donut.png, the image will not load on a Linux host, because file names there are case-sensitive.

Rules that keep you out of trouble:

  • Lowercase letters, numbers and underscores only. No spaces, no dashes, no capitals.
  • Image file name = item name + .png. ox_inventory and esx_inventory build the image path from the item name automatically. QB-Core stores it in the image field, so keep it identical anyway.
  • Use a category prefix such as food_, drink_, tool_ or med_. It keeps a 1000-item list readable and prevents two packs from using the same name.
  • Keep ESX names under 50 characters. The name and label columns in ESX's items table are varchar(50).
  • Do not start custom item names with weapon_ in ox_inventory unless you follow the fix below. ox_inventory treats that prefix specially.

Renaming later is painful: every player inventory, stash and shop that already holds the old name keeps it.


How to Add Items to ox_inventory

ox_inventory is a common choice on ESX servers and the inventory Qbox is built around. Items live in one Lua table.

The item definition

Open ox_inventory/data/items.lua and add your entry inside the return { ... } table:

['food_donut_pink_sprinkles'] = {
    label = 'Donut Pink Sprinkles',
    weight = 220,     -- grams
    stack = true,
    close = true,
},

stack and close already default to true, so a minimal item only needs label and weight. For reference, the default burger in ox_inventory weighs 220 and the bandage 115.

Where ox_inventory looks for images

By default ox_inventory loads ox_inventory/web/images/<item name>.png. Drop the PNG there and it appears with no extra config.

Two options when you need something else:

  • One item with a different file: add client = { image = 'my_file.png' } to the item.
  • All images from another folder or a CDN: set the convar setr inventory:imagepath "nui://my_images/images" in your server.cfg.

The weapon_ prefix trap

This one is not in most tutorials. When ox_inventory looks up an item whose name starts with weapon_, it converts the name to uppercase first, because its real weapons are defined as WEAPON_PISTOL, WEAPON_SMG and so on. A custom item written as ['weapon_rusty_machete'] is stored in lowercase but searched for in uppercase, so /giveitem and AddItem answer invalid_item.

If your item names start with weapon_, write the key in uppercase and point the image at the lowercase file:

['WEAPON_RUSTY_MACHETE'] = {
    label = 'Rusty Machete',
    weight = 1000,
    client = { image = 'weapon_rusty_machete.png' },
},

The same rule applies to images of real weapons: ox_inventory looks for WEAPON_SMG.png, not weapon_smg.png. To replace a default weapon icon, save your file under the uppercase name.

ESX + ox_inventory: put items in the ox file, not the database

On ESX, ox_inventory reads ESX's items table when it starts and copies every item it does not know yet into data/items.lua, with the weight from the database. ESX weights are in kilograms (1), ox weights are in grams, so a copied item weighs 1 gram.

So on an ESX server with ox_inventory, add your items to ox_inventory/data/items.lua and skip the SQL import.


How to Add Items to QB-Core

On QB-Core, items are defined in the core resource and the images belong to the inventory resource.

The item definition

Open qb-core/shared/items.lua and add a line inside QBCore.Shared.Items = { ... }:

food_donut_pink_sprinkles = { name = 'food_donut_pink_sprinkles', label = 'Donut Pink Sprinkles', weight = 220, type = 'item', image = 'food_donut_pink_sprinkles.png', unique = false, useable = true, shouldClose = true, description = 'Fresh from the bakery' },

Weights are in grams, like ox_inventory: the default sandwich weighs 200 and the water bottle 500. Older QB versions write the key as ['food_donut_pink_sprinkles'] = { ... }. Both forms are valid Lua and work the same way.

Images in qb-inventory

Copy the PNG to qb-inventory/html/images/. The file name must match the image field exactly, including .png. Most forks of qb-inventory keep the same html/images folder, but check your fork's fxmanifest.lua if images do not appear.

Do not overwrite default weapons

QB-Core defines its weapons in the same table, with type = 'weapon'. If you add an item named weapon_smg with type = 'item', it replaces the real SMG, and players can no longer equip it. To give a default weapon a new look, only replace its image file and leave its entry alone.


How to Add Items to ESX Legacy

Without ox_inventory, ESX keeps items in the database and loads them when es_extended starts.

The SQL insert

INSERT IGNORE INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES
    ('food_donut_pink_sprinkles', 'Donut Pink Sprinkles', 1, 0, 1);

Use INSERT IGNORE for anything with more than a few rows. A plain INSERT stops the whole import at the first name that already exists ("Duplicate entry"), and nothing gets added. INSERT IGNORE skips existing items and adds the rest.

Weight in ESX is not grams

ESX's default carry limit is Config.MaxWeight = 24, and its default items weigh 1 to 3 (bread 1, bandage 2). An item copied from an ox or QB config with weight = 220 cannot be picked up at all. Divide gram weights by 1000 and round, with 1 as the minimum.

Where ESX item images go

Recent ESX Legacy builds include esx_inventory, a slot grid inventory that loads esx_inventory/web/images/<item name>.png and shows a fallback icon when the file is missing. Older setups use the text-only F2 menu (no images at all) or a third-party inventory with its own images folder; check that script's documentation.


Item Weights: Grams vs Kilograms

Mixing up units is the most common reason a new item "cannot be carried". Realistic reference values from the frameworks' own default items:

Item typeox_inventory / QB-Core (grams)ESX Legacy (~kg)
Card, document, key0–501
Food (burger, sandwich)200–2201
Drink (bottle)350–5001
Phone7001
Pistol1 000–1 1301
Laptop4 0004
Rifle4 5004–5
Body armor5 0005

The ESX column is rounded. Do not set ESX weights to 0 unless you really want an item to weigh nothing.


Which Image Size to Use in Your Inventory

The default icons in both ox_inventory and qb-inventory are 100 × 100 px. That is the size each slot was designed around.

The same FiveM inventory icon at 64, 100, 128 and 256 px with file sizes, compared in an inventory slot
  • 100 px matches the defaults exactly.
  • 128 px stays sharp on 1440p and 4K screens and still loads fast. This is the size we recommend for FiveM.
  • 256 px only makes sense for large tooltips or item previews.
  • 512 px is source quality. Do not ship it in-game: one 512 px icon weighs about 10× more than the same icon at 128 px (226 KB vs 22 KB in our tests), and with hundreds of items players download all of it.

Use transparent PNGs with the same padding on every icon, so items sit at the same size in every slot.


Adding Hundreds of Items at Once

Writing three config files by hand works for five items. For a full economy it does not: 300 items means 300 Lua entries, 300 SQL rows and 300 file names that must all match.

The faster route is a pack that ships all three already matched: icons named after the item, plus ready config files for each framework. Our free Modern RP Starter Pack is built exactly that way, and you can use it to test the whole process from this guide on your own server:

What is inside: 52 transparent PNG icons in 64, 96, 100, 128, 256 and 512 px, and config files for ESX (INSERT IGNORE), QB-Core and ox_inventory, each in a "standard" version (one weight for all) and a "realistic" version (weight by item type, in the right unit for each framework).

If it works for your server, the full Modern RP series has five volumes with more than 7 000 FiveM item images, plus 224 bonus UI icons in the bundle. Every volume uses unique file names, so all of them install into the same folder without overwriting anything:


Troubleshooting Custom Items

The item shows a blank square or a question mark. The PNG name does not match the item name. Check capital letters and the .png extension, and make sure the file sits in the folder your inventory actually reads (web/images for ox, html/images for qb-inventory).

/giveitem says the item does not exist (invalid_item). The definition did not load: a missing comma in the Lua file, an item added to the wrong file, or, in ox_inventory, a lowercase weapon_ name (see the fix above). All three frameworks use /giveitem <player id> <item name> <amount> for testing.

The item exists but cannot be picked up. The weight is in the wrong unit. 220 in ESX means about 220 kg.

The ESX import added nothing. One of the names already existed and a plain INSERT stopped the whole import. Use INSERT IGNORE.

A default weapon stopped working after adding a pack. An entry with the same name as the weapon replaced it. Remove that entry and keep only the image.

The item exists but nothing happens on use. A definition only makes the item exist. To make it do something, register it with ESX.RegisterUsableItem (ESX), QBCore.Functions.CreateUseableItem (QB-Core) or a client.export / server.export in the item definition (ox_inventory).

Changes do not show up. Items are loaded when the resources start. Restart the server rather than a single resource, so every script sees the new item list.


Summary

  • One name everywhere: item name = image file name, lowercase, with a category prefix.
  • ox_inventory: data/items.lua + web/images/, grams, uppercase keys for weapon_ items.
  • QB-Core: shared/items.lua + qb-inventory/html/images/, grams, never reuse a default weapon name.
  • ESX Legacy: items table with INSERT IGNORE, weights in kilograms; with ox_inventory, use the ox file instead.
  • 100 px is the default icon size, 128 px is the sharp, safe choice.
Pixarts logo
Written by Pixarts Team

Dedicated to empowering game developers with premium digital assets. We specialize in crafting immersive UI designs, distinct logos, and web solutions that take your game project to the next level.