# esx_progressbar (/docs/core/esx_progressbar)

esx_progressbar shows a timed progress bar at the bottom of the screen, with an
optional animation or scenario and an optional player freeze. Use it for actions
that take time, such as lockpicking, crafting or searching a trash bin. Call it
from client code with `ESX.Progressbar`.

## Overview [#overview]

| | |
| --- | --- |
| Resource | `esx_progressbar` |
| Side | Client only |
| Dependencies | `esx_lib` and `es_extended` (both loaded via imports, not listed as manifest dependencies) |
| Config | None |
| Required | Yes if any script calls `ESX.Progressbar`; es_extended errors when it is missing |

## Functions [#functions]

### ESX.Progressbar [#esxprogressbar]

```lua
local started = ESX.Progressbar(message, length, options)
```

| Name | Type | Description |
| --- | --- | --- |
| `message` | `string?` | Text on the bar. Default `"ESX-Framework"`. Supports color codes such as `~g~`. |
| `length` | `number?` | Duration in milliseconds. Default `3000`. |
| `options` | `table?` | See the options table below. |

**Returns** `boolean`: `true` when the bar started, `false` when another bar is
already running.

#### Options [#options]

| Field | Type | Description |
| --- | --- | --- |
| `FreezePlayer` | `boolean?` | Freezes the player ped until the bar finishes or is canceled. |
| `animation` | `table?` | Animation to play, see below. |
| `onFinish` | `function?` | Called when the bar completes. |
| `onCancel` | `function?` | Called when the bar is canceled. |

`animation` has two forms:

| Field | Form | Description |
| --- | --- | --- |
| `type` | both | `"anim"` or `"Scenario"` (capital S, case-sensitive). |
| `dict` | `anim` | Animation dictionary. Loaded through `xLib.streaming.requestAnimDict`. |
| `lib` | `anim` | Animation name inside the dictionary. |
| `Scenario` | `Scenario` | Scenario name, e.g. `"PROP_HUMAN_BUM_BIN"` (capital S). |

```lua title="client/main.lua"
local function searchTrash()
    local started = ESX.Progressbar("Searching the trash...", 5000, {
        FreezePlayer = true,
        animation = {
            type = "Scenario",
            Scenario = "PROP_HUMAN_BUM_BIN",
        },
        onFinish = function()
            TriggerServerEvent("my_trash:searched")
        end,
        onCancel = function()
            ESX.ShowNotification("You stopped searching.", "info")
        end,
    })

    if not started then
        ESX.ShowNotification("You are already busy.", "error")
    end
end
```

Animation example:

```lua title="client/main.lua"
ESX.Progressbar("Unlocking storage", 3000, {
    FreezePlayer = true,
    animation = {
        type = "anim",
        dict = "anim@mp_player_intmenu@key_fob@",
        lib = "fob_click",
    },
    onFinish = function()
        TriggerServerEvent("my_storage:open")
    end,
})
```

### ESX.CancelProgressbar [#esxcancelprogressbar]

Cancels the active bar: closes the UI, clears the ped tasks, unfreezes the
player and calls `onCancel`. Does nothing when no bar is active.

```lua
ESX.CancelProgressbar()
```

Use it when the player dies, gets into a vehicle or leaves the area:

```lua title="client/main.lua"
AddEventHandler("esx:onPlayerDeath", function()
    ESX.CancelProgressbar()
end)
```

## Exports [#exports]

The ESX functions are thin wrappers around these exports.

| Export | Signature |
| --- | --- |
| `Progressbar` | `exports["esx_progressbar"]:Progressbar(message, length, options)` returns `boolean` |
| `CancelProgressbar` | `exports["esx_progressbar"]:CancelProgressbar()` |

## Controls [#controls]

| Key mapping | Default | Action |
| --- | --- | --- |
| `[ProgressBar] Cancel Progressbar` | Backspace | Cancels the active bar |

Players can rebind it in **Settings → Key Bindings → FiveM**. The key is
registered with `xLib.addKeybind`.

## Common issues [#common-issues]

- **Animation stops before the bar ends.** The animation plays with the bar
  length as its duration and flag `1` (loop). If your animation still stops,
  another script is clearing the ped tasks.
- **Players skip timed actions.** Every bar can be canceled with Backspace, and
  a modified client can call `onFinish` early. Never rely on the bar for
  timing on the server; check elapsed time server-side.
- **Scenario does not play.** Use `type = "Scenario"` and the key `Scenario`
  with a capital S. `"scenario"` in lowercase is ignored.
- **`ESX.Progressbar` returns `false`.** A bar is still running. Check the
  return value and tell the player they are busy, or cancel the old bar first.

## Related [#related]

- [Core resources overview](/docs/core)
- [Client functions](/docs/es_extended/client/functions)
- [esx_notify](/docs/core/esx_notify)
- [esx_lib](/docs/core/esx_lib)
