PiTyUs.Hire me

Engineering

Calling web APIs from FiveM scripts

Use PerformHttpRequest in FiveM: the callback (statusCode, body, headers, errorData), GET and POST with JSON, custom headers and auth, awaiting results with promises, timeouts and error handling, keeping API keys on the server, rate limits, and JavaScript alternatives.

Updated 9 min readBy PiTyUs · FiveM developer

Overview

Discord bots, web panels, licence checks, analytics — sooner or later a resource needs to talk to the web. FiveM’s PerformHttpRequest does it from Lua with a callback; wrapped in a promise it reads like a normal function call.

A basic request

server.lualua
PerformHttpRequest('https://api.example.com/status', function(status, body, headers, err)
    if status ~= 200 then
        print(('request failed: %s %s'):format(status, err or ''))
        return
    end
    local data = json.decode(body)
    print('players online on the website:', data.online)
end, 'GET')

POST with JSON and headers

server.lualua
local API_KEY = GetConvar('myres_api_key', '')

local function post(url, payload, cb)
    PerformHttpRequest(url, cb, 'POST', json.encode(payload), {
        ['Content-Type'] = 'application/json',
        ['Authorization'] = 'Bearer ' .. API_KEY,
    })
end

Store the key with set myres_api_key "..." (server-only, not setr) — see convars.

Awaiting the result

server.lualua
local function request(url, method, body, headers)
    local p = promise.new()
    PerformHttpRequest(url, function(status, resBody, resHeaders, err)
        p:resolve({ status = status, body = resBody, headers = resHeaders, error = err })
    end, method or 'GET', body or '', headers or {})
    return Citizen.Await(p)
end

CreateThread(function()
    local res = request('https://api.example.com/status')
    if res.status == 200 then print(res.body) end
end)

Citizen.Await must run inside a thread, event handler or callback. Thread basics: threads and Wait.

Safety and limits

  • Never put API keys in client files — every player can read them.
  • Respect the API’s rate limits; queue or batch requests.
  • Do not make requests per frame or per player action without caching.
  • Validate responses before using them in game logic.
  • For logging to Discord, see webhook logging.

JavaScript alternative

Server-side JavaScript resources run on Node.js and can use fetch or npm HTTP clients directly — see TypeScript scripts.

Frequently asked questions

How do I make an HTTP request in FiveM Lua?

Call PerformHttpRequest(url, callback, method, data, headers); the callback receives status code, body, headers and error data.

How do I send JSON?

Pass json.encode(table) as the data and set the Content-Type: application/json header.

Can I wait for the response?

Yes — resolve a promise in the callback and Citizen.Await it inside a thread.

Should I call APIs from the client?

Not with secrets. Make authenticated requests from the server.

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