Assets & UI
FiveM loading screens — the first 40 seconds of your server
How FiveM loading screens work: the loadscreen manifest, manual shutdown, music and video that actually play, live player counts and common mistakes.
How a loading screen resource works
A loading screen is a resource whose manifest declares a `loadscreen` page instead of a `ui_page`. FiveM displays it from the moment a player starts connecting until the game finishes loading, then tears it down automatically — unless you tell it not to.
fx_version 'cerulean'
game 'gta5'
loadscreen 'html/index.html'
loadscreen_manual_shutdown 'yes'
files {
'html/index.html',
'html/**/*',
}- `loadscreen` points at the HTML entry point, exactly like ui_page.
- `loadscreen_manual_shutdown 'yes'` stops FiveM from closing the screen on its own — your client script decides when.
- Everything referenced must be listed in `files` and loaded with relative paths.
- Only one resource should declare a loadscreen. Two will fight and the result is undefined.
Manual shutdown and the "click to join" pattern
With manual shutdown enabled, the screen persists until your client script calls the shutdown native. That is how servers show a finished progress bar with a button, or hold the screen while a character-select UI initialises.
RegisterNUICallback('continue', function(_, cb)
ShutdownLoadingScreenNui()
cb({})
end)
-- safety net: never leave a player stuck on the loading screen
CreateThread(function()
Wait(120000)
ShutdownLoadingScreenNui()
end)Music and video that actually play
Browsers block autoplaying audio without user interaction — but the loading screen context in FiveM allows it, which is why loading screens are the one place you can reliably play music without a click. Keep it simple and it just works.
- Ship the audio file inside the resource. Streaming from an external URL fails, because there is no reliable network access during loading.
- Use compressed formats — a 3-minute MP3 at 128 kbps is around 3 MB, which is fine. A WAV is not.
- Provide a mute button and remember the choice in localStorage. Players who join twenty times a day will thank you.
- For video backgrounds, use a short looping MP4 with no audio track, `muted`, `loop`, `playsinline` and `autoplay`.
- Keep the video under about 10 MB. Everything in the resource has to reach the client before the screen renders.
<video autoplay muted loop playsinline
class="bg"
src="./assets/loop.mp4"></video>
<audio id="track" src="./assets/theme.mp3" autoplay loop></audio>Live data: player counts and progress
The loading screen receives the game's own loading events, so you can show a real progress bar rather than a fake animation. Your own server data — player counts, rules, staff, update notes — has to be pushed in from a client script.
window.addEventListener('message', (e) => {
const d = e.data
switch (d.eventName) {
case 'loadProgress':
setBar(d.loadFraction * 100)
break
case 'startInitFunction':
case 'startDataFileEntries':
case 'performMapLoadFunction':
setStage(d.eventName)
break
}
})For a live player count, have a small client script ask the server and forward the answer into the page with SendLoadingScreenMessage. It is the same message bus as SendNUIMessage, just aimed at the loading screen.
Designing something people actually read
- Lead with identity. Server name, tagline and one strong image — decided in the first two seconds.
- Give them one thing to do. A Discord link, and only one.
- Show what changed. A short "latest update" panel is the cheapest retention tool you have.
- Rules in three lines, not thirty. Nobody reads a wall of text while waiting.
- Show the current player count. Social proof works.
- Do not animate everything. A loading screen that flashes and slides constantly reads as amateur.
Common mistakes
- Absolute asset paths. `/img/logo.png` resolves nowhere; use `./img/logo.png`.
- Fonts from a CDN. Ship the woff2 and declare it with @font-face.
- A 60 MB background video. The player waits for it before they see anything at all.
- Two loadscreen resources enabled at once.
- No mute control on a track that plays every single join.
- Forgetting `files { 'html/**/*' }`, so half the assets 404 in production but work locally.
Frequently asked questions
How do I add a custom loading screen to FiveM?
Create a resource whose fxmanifest declares loadscreen 'html/index.html', list every asset under files, and ensure the resource in server.cfg. Only one resource on the server should declare a loadscreen.
Can a FiveM loading screen play music?
Yes. The loading screen is one of the few NUI contexts where autoplay works, so a plain audio element with autoplay and loop plays reliably. Ship the file inside the resource and include a mute button.
What does loadscreen_manual_shutdown do?
It prevents FiveM from closing the loading screen automatically, so your client script decides when to call ShutdownLoadingScreenNui. Use it for a press-to-continue button, and always add a timeout so nobody gets stuck.
Why do images not show on my FiveM loading screen?
Either the paths are absolute instead of relative, or the files are not listed in the files block of the manifest. There is also no external network access during loading, so anything hosted off-server will fail.
Need this built, not just explained?
Ten years of FiveM work, from Lua to NUI
Custom resources, React NUI, ESX / QBCore / Qbox integration, OneSync performance audits and security reviews — plus the websites and SEO around your server brand.
Related guides
- Assets & UIFiveM NUI developmentCEF quirks, the Lua↔JS contract, React/Next.js builds, NUI focus, and the CSS that silently fails inside the game.
- Assets & UICustom FiveM minimapHow minimap tiles and the LOD map work, installing a custom map, postal codes, and fixing blurry or missing tiles.
- Getting startedHow to make a FiveM serverFrom an empty VPS to a public GTA V roleplay server: artifacts, licence key, server.cfg, framework, database, OneSync and the launch checklist.