
Converting FiveM Scripts: ESX, QBCore & QBOX Framework Guide
This is a code‑first, no‑fluff easy converting FiveM scripts guide that shows you exactly how to Convert FiveM Scripts between ESX, QBCore, QBOX (qbx_core), and framework‑agnostic (standalone) setups. You’ll get tri‑way API mappings, adapter code, SQL migration steps (mysql‑async → oxmysql), QBOX specifics, testing checklists, and production hardening tips.
TL;DR — Migration in 10 Steps
- Snapshot & staging: Back up DB/files. Spin up a local test server with the target framework.
- Identify dependencies: inventory, target, menu/UI, callbacks, DB layer, core access.
- Pin versions & order: oxmysql → ox_lib → framework (es_extended / qb-core / qbx_core) → your resources.
- Read the code path: Find all player, money, job/duty, inventory, callback/event, and DB calls.
- Map APIs: Use the Rosetta tables below to map ESX ↔ QBCore ↔ QBOX.
- Bridge it: Add a bridge.lua adapter that auto‑detects the framework and normalizes calls.
- Convert callbacks: ESX/QB callbacks → QBOX/ox_lib
lib.callback.*when needed. - Migrate DB: Move identifiers, accounts, items, vehicles; switch to oxmysql
*.awaitstyle. - Harden events: Validate
source, bounds, groups/jobs, ownership; never trust client. - QA & release: Run the checklists; tag, changelog, and rollback plan.
Are you a developer that is looking for an Adapter solution? Check out our free adapter script here
1) Frameworks 101: ESX vs QBCore vs QBOX vs Standalone
Architectural overview
| Category | ESX | QBCore | QBOX |
|---|---|---|---|
| Architecture / Core Access | exports['es_extended']:getSharedObject() → ESX | exports['qb-core']:GetCoreObject() → QBCore | No global core object; use exports.qbx_core:* for player, groups, and notifications |
| Player Object | ESX.GetPlayerFromId(src) → xPlayer | QBCore.Functions.GetPlayer(src) → Player | exports.qbx_core:GetPlayer(src) → Player with PlayerData |
| Identifiers | Historically identifier (license/steam) | citizenid as primary key | citizenid as primary key |
| Money Handling | xPlayer.addMoney() / `addAccountMoney(‘bank’ | ‘black_money’)` | `Player.Functions.AddMoney(‘cash’ |
| Jobs & Duty | xPlayer.job.name, .job.grade | Player.PlayerData.job.name, .grade.level, OnDuty | Job/group helpers via exports.qbx_core:* (group checks, duty setters) |
| Inventory | ESX default / ox_inventory / qb-inventory (recommended: ox_inventory) | qb-inventory / ox_inventory | ox_inventory recommended |
| Callbacks | ESX.RegisterServerCallback / ESX.TriggerServerCallback | QBCore.Functions.CreateCallback / TriggerCallback | Prefer ox_lib callbacks (lib.callback.register/await) or QBOX exports |
| Database Layer | Old: mysql-async → Now: oxmysql (MySQL.query.await, MySQL.update.await) | oxmysql | oxmysql |
| UI – Notifications | ESX Notify | QB Notify | QBOX notify helpers or lib.notify |
| UI – Menus | esx_menu_default / ox_lib:registerContext | qb-menu / ox_lib:registerContext | ox_lib:registerContext / lib.inputDialog |
| UI – Target System | esx_target / ox_target | qb-target / ox_target | ox_target recommended |
Where QBOX differs
- Resource name and exports:
qbx_core(noGetCoreObject). - Leans on ox_lib (callbacks, notify) and oxmysql by default.
- Built‑ins for multicharacter/queue/groups; opinionated helpers for jobs/duty.

2) Preflight: Environment & Tooling
- Server: current FXServer artifacts, Lua 5.4, CFX
ensureorder - Order:
ensure oxmysql→ensure ox_lib→ensure framework→ensure yourResource - Editor: VS Code + Lua LS, stylua; optional ripgrep for quick pattern scans
- Test setup: clean database snapshot; verbose logging; small seeded data set
- Search patterns you’ll use:
ESX\.xPlayer\.QBCore\.PlayerDataqbx_coreexports\.ox_inventorymysql%-asyncMySQL\.
3) Rosetta Stone: ESX ↔ QBCore ↔ QBOX (Tri‑way Mapping)
Copy/paste friendly reference. Use it to replace calls or wire your adapter.
Core & Player
Concept ESX QBCore QBOX Get core exports['es_extended']:getSharedObject()exports['qb-core']:GetCoreObject()(n/a — use exports) Get player (src) ESX.GetPlayerFromId(src)QBCore.Functions.GetPlayer(src)exports.qbx_core:GetPlayer(src)Get by citizenid (custom query) QBCore.Functions.GetPlayerByCitizenId(id)exports.qbx_core:GetPlayerByCitizenId(id)(if present)Identifiers
Concept ESX QBCore QBOX Primary identifier(license/steam)citizenidcitizenidCrosswalk table id_map(identifier, citizenid)same same Money
Action ESX QBCore QBOX Add cash xPlayer.addMoney(a)Player.Functions.AddMoney('cash', a)Player.PlayerData.money.cash += a(via adapter + save)Add bank xPlayer.addAccountMoney('bank', a)Player.Functions.AddMoney('bank', a)Player.PlayerData.money.bank += a(adapter + save)Add dirty xPlayer.addAccountMoney('black_money', a)item or extra account (server‑defined) map to item/alt wallet (e.g., crypto) (adapter choice)Jobs, Duty, Groups
Concept ESX QBCore QBOX Read job xPlayer.job.name,.gradePlayer.PlayerData.job.name,.grade.levelPlayer.PlayerData.job.*+ group helpersOn duty (varies) Player.PlayerData.job.ondutySetJobDuty/group helpers via exportsGroup check (add-on) (add-on) exports.qbx_core:HasGroup(src, group)(example)Inventory
Action ESX QBCore QBOX Add item xPlayer.addInventoryItem(n, c)Player.Functions.AddItem(n, c, ...)prefer ox_inventoryexport via adapterox_inventory exports.ox_inventory:*exports.ox_inventory:*exports.ox_inventory:*Callbacks
Concept ESX QBCore QBOX Server register ESX.RegisterServerCallbackQBCore.Functions.CreateCallbacklib.callback.register(ox_lib)Client trigger ESX.TriggerServerCallbackQBCore.Functions.TriggerCallbacklib.callback.awaitDB Layer
Concept ESX/QB (legacy) oxmysql (target) Fetch MySQL.Async.fetchAll(sql, params, cb)local rows = MySQL.query.await(sql, {p1, ...})Update MySQL.Async.execute(sql, params, cb)local aff = MySQL.update.await(sql, {p1, ...})UI / Notify / Target
Concept ESX QBCore QBOX Notify ESX.ShowNotification(msg)QBCore.Functions.Notify(msg, type)exports.qbx_core:Notify(...)orlib.notify({...})Menu (varies) qb-menuox_lib:registerContext/ inputsTarget (add-on) qb-targetox_targetTip: favor ox_lib, ox_inventory, ox_target to stay neutral across frameworks.
4) Tutorial A — ESX → QBCore (Hands‑on)
Goal: Convert a simple shop resource from ESX to QBCore.
Step 1 — Dependencies
- Ensure
oxmysql,ox_lib,qb-coreare started. - If the script uses ESX inventory, migrate to ox_inventory (recommended) or map to QB inventory.
Step 2 — Detect framework & add a bridge
Create
bridge.luato normalize players/money/inventory:- Ensure
Step 3 — Convert callbacks
- ESX → QB: replace
ESX.RegisterServerCallbackwithQBCore.Functions.CreateCallback. - Client uses
QBCore.Functions.TriggerCallback.
Step 4 — Money & inventory paths
- Replace
xPlayer.addAccountMoneywithPlayer.Functions.AddMoney(for QB) or adapter. - Standardize all inventory changes through the adapter.
Step 5 — Events (server‑side security)
Step 6 — DB migration (identifiers, accounts)
- Create a crosswalk
id_map(identifier, citizenid). - Populate
citizenidfor QB from ESXuserstable via rule of choice (existing column or generated).
mysql‑async → oxmysql
Step 7 — QA
- Spawn items, buy/sell, ensure balances change correctly.
- Verify callbacks return under load.
- Check that inventory metadata is preserved.
5) Tutorial B — QBCore → ESX (Hands‑on)
Key caveats:
- ESX uses accounts for
bank/black_money. Port QB’s dirty‑money item (if used) to ESX account or keep it as an item. - Job schema differs (grade vs level). Map carefully.
Example: Money mapping via adapter
Example: Callback conversion (server)
Testing checklist
- Job set/promotions persist.
- Bank/dirty balances mutate as expected.
- Vehicle ownership and plate formats validated.
6) Tutorial C — QBCore ↔ QBOX (Hands‑on)
QBCore → QBOX
- Replace
QBCore.Functions.*withexports.qbx_core:*or ox_lib callbacks. - Player:
QBCore.Functions.GetPlayer(src)→exports.qbx_core:GetPlayer(src). - Notify:
QBCore.Functions.Notify→exports.qbx_core:Notifyorlib.notify. - Duty/groups: use QBOX exports (
SetJobDuty,HasGroup, etc.).
QBOX → QBCore
- Replace
exports.qbx_core:*withQBCore.Functions.*equivalents or your adapter. - Reintroduce QB callbacks and menu/target equivalents as needed.
Before/After snippets
7) Tutorial D — Framework → Standalone with Adapters
Write your scripts once and run them anywhere:
- Create a bridge exposing a stable API:
getPlayer,getIdentifier,add/removeMoney,add/removeItem,notify,hasGroup,onDuty,callbackswrapper. - Detect framework at runtime (
qbx_core→qb-core→es_extended→none). - Use ox_lib for callbacks and notifications when no direct framework helper exists.
Minimal standalone fallback
8) Performance & Security (Production Hardening)
Server‑side validation (never trust client)
- Validate types and bounds on every event.
- Check ownership, cooldowns, distance (if relevant), job/group.
- Ensure money can’t go negative; clamp amounts.
- Compare price server‑side; don’t accept client‑provided totals.
Event structure
- Use one server event per action; do not expose raw inventory/money functions to clients.
- Prefer callbacks for request/response flows.
DB & performance
- Switch to oxmysql await APIs; batch writes; avoid per‑tick queries.
- Index frequently queried columns (
citizenid,identifier,plate). - Cache config/price lists in memory; export them to clients once, then diff on change.
- Use
GlobalStatesparingly; avoid hot‑loop updates.
9) Common Pitfalls & Debugging Playbook
- Assuming
GetCoreObjectexists on QBOX → it doesn’t; useexports.qbx_core:*. - Callbacks never return after migrating to QBOX → ESX/QB callbacks aren’t registered; switch to
lib.callback.register/await. - Dirty money semantics differ → decide item vs account vs alt wallet and standardize in your adapter.
- Mixed inventory assumptions → normalize on
ox_inventory. - Start order issues →
oxmysql→ox_lib→ framework → your resources. - Vehicle metadata drift → ensure JSON columns and plate formats match target framework.
10) fxmanifest.lua Best Practices
- Declare Lua 5.4 (
lua54 'yes'). - Keep
escrow_ignoreminimal; never attempt escrow bypass.
11) Data Migration: SQL Snippets (Examples)
Adjust table/column names to your schema. Always run on a copy first.
Identifiers: ESX → QB/QBOX
Accounts/Money
Vehicles
12) Adapters You Can Reuse (Starter)
Drop this into
bridge.luaand expand per your needs. It auto‑detects ESX/QB/QBOX and exposes a stable API.
13) Final Checklists (Copy & Ship)
A) Discovery & Preflight
- Snapshot DB/files; create a staging server
- Pin artifacts and resource versions; define start order
- Inventory/target/menu dependencies listed
- Decide identifier strategy (citizenid crosswalk)
B) Code Audit
- Grep for ESX/QB/QBOX/ox_*/mysql‑async
- List all money/inventory/job/duty calls
- List callbacks and server/client events
C) Mapping & Design
- Choose adapter surface (player, ids, money, items, notify, callbacks)
- Decide dirty‑money strategy (account vs item vs alt wallet)
- Favor ox_lib/ox_inventory/ox_target
D) Data Migration
- Build citizenid crosswalk
- Convert accounts/money
- Normalize vehicle metadata and plates
- Switch to oxmysql await calls
E) QA Testing
- Event security: types/bounds/ownership/cooldowns
- Callbacks: return values under load
- Inventory metadata preserved
- Jobs/duty/group logic matches design
F) Release & Rollback
- Tag release; changelog
- Keep pre‑migration snapshot for 7–14 days
- Monitor errors/latency; index hot queries
14) FAQ (with JSON‑LD Schema)
Q: Can I port QBCore scripts to QBOX without a full rewrite?
A: With adapters and ox_lib callbacks, most scripts need only call remapping.
Q: What do I do with black/dirty money?
A: Standardize in your adapter: ESX → black_money account; QB → item or extra account; QBOX → item or alt wallet (e.g., crypto). Keep one strategy project‑wide.
Q: Why do callbacks hang after moving to QBOX?
A: ESX/QB callbacks won’t fire on QBOX. Use lib.callback.register/await.
Q: Best way to migrate mysql‑async?
A: Replace with oxmysql await APIs; remove callback pyramids.
Q: How do I convert qb‑target to ox_target?
A: Replace addBoxZone/Entity API calls one‑for‑one; event payloads remain similar. Keep target names stable.
15) Visuals (Suggestions)
- Flowchart (Discover → Map → Adapt → Migrate DB → Test → Release)
- Adapters Diagram: Script → Bridge → Framework (ESX/QB/QBOX)
- Rosetta Table: included above (export as CSV for downloads)
16) Legal & Ethical
- Respect licenses (MIT/GPL/NC). Do not bypass escrow or obfuscation.
- Convert only scripts you own or have permission to adapt.
17) Downloadables & Quick Reference
You can also use this converter (not tested though):
https://github.com/sledgehamm3r/ESX-QBCore-Converter
28) Next Steps
- Drop the bridge.lua into your resource and start converting your highest‑value scripts first.
- Standardize on ox_lib + ox_inventory + ox_target + oxmysql to stay framework‑agnostic.
- Use the checklists during review and release.
Also read SQL & Identifiers Migration: steam/license → citizenid and Accounts → Money (ESX → QBCore/QBOX)
Mantente al Día
Recibe los últimos tutoriales de FiveM, lanzamientos de mods y actualizaciones exclusivas en tu correo.
Sin spam. Cancela cuando quieras.