HTTP
On this page
The core.http module provides asynchronous HTTP requests from Lua scripts. Requests run in the background and deliver results via callbacks on the main thread, so they never block game logic.
Responses are delivered on the next game tick after they complete. Your callback will not fire immediately — it runs when the main thread polls for results.
Cookies and authentication state persist within a script's own requests but never leak between scripts. Two scripts talking to the same host hold their own separate state — calls from one script never see headers, cookies, or auth from another.
A script can also create additional clients explicitly via core.http.client() when it needs more than one independent HTTP context (e.g. two separate auth contexts, or isolated bot vs telemetry traffic).
Using core.http to scrape, collect, exfiltrate, or otherwise harvest a user's script data, settings, credentials, account data, or private gameplay data is strictly prohibited. Only send data with clear user approval and for the specific workflow the user agreed to.
Functions
All functions take a callback as the last argument. The callback receives a single response table.
core.http.get(url: string [, headers: table], callback: function)
Sends a GET request.
core.http.get("https://api.example.com/data", function(response)
core.log("Status: " .. response.status)
core.log("Body: " .. response.body)
end)core.http.post(url: string, body: string [, content_type: string [, headers: table]], callback: function)
Sends a POST request. content_type defaults to "application/json".
core.http.post("https://api.example.com/data", '{"key":"value"}', function(response)
core.log("Status: " .. response.status)
end)core.http.put(url: string, body: string [, content_type: string [, headers: table]], callback: function)
Sends a PUT request. content_type defaults to "application/json".
core.http.delete(url: string [, headers: table], callback: function)
Sends a DELETE request.
core.http.request(method: string, url: string [, body: string [, headers: table]], callback: function)
Sends a request with any HTTP method.
core.http.request("PATCH", "https://api.example.com/data", '{"updated":true}', function(response)
core.log("Status: " .. response.status)
end)Explicit Clients
core.http.client() -> http_client
Returns a brand-new client object with its own cookie jar, auth state, and connection pool — fully isolated from your script's default client and from any other clients you create. Use this when one script needs multiple independent HTTP contexts.
local api = core.http.client()
local logs = core.http.client()
api:get("https://api.example.com/login", function(r) ... end)
logs:post("https://logs.example.com/ingest", payload, function(r) ... end)Cookies set on api will never be sent by logs, and vice versa — the same applies to authentication. The client lives until your script unloads or you drop all references to it (Lua GC then closes the underlying session and aborts any in-flight requests on it).
Methods
The client object exposes the same five verbs as the free functions, with : instead of .. Each takes a callback as its last argument and receives a single response table.
client:get(url: string [, headers: table], callback: function)
Sends a GET request on this client.
client:post(url: string, body: string [, content_type: string [, headers: table]], callback: function)
Sends a POST request on this client. content_type defaults to "application/json".
client:put(url: string, body: string [, content_type: string [, headers: table]], callback: function)
Sends a PUT request on this client. content_type defaults to "application/json".
client:delete(url: string [, headers: table], callback: function)
Sends a DELETE request on this client.
client:request(method: string, url: string [, body: string [, headers: table]], callback: function)
Sends a request with any HTTP method on this client.
Response Object
The callback receives a table with the following fields:
| Field | Type | Description |
|---|---|---|
status | number | HTTP status code (200, 404, etc.) or 0 if the request failed |
body | string | Response body as a string |
headers | table | Response headers as key-value pairs |
Custom Headers
Pass a table of string key-value pairs before the callback to set request headers.
core.http.get("https://api.example.com/data", {
["Authorization"] = "Bearer my-token",
["Accept"] = "application/json"
}, function(response)
core.log(response.body)
end)Examples
Simple GET
local has_run = false
function on_tick()
if has_run then return end
has_run = true
core.http.get("https://httpbin.org/get", function(response)
core.log("Status: " .. response.status)
core.log("Body: " .. string.sub(response.body, 1, 200))
end)
endPOST JSON Data
core.http.post("https://api.example.com/webhook",
'{"event":"evasion","player":"SomeName"}',
"application/json",
{ ["Authorization"] = "Bearer token123" },
function(response)
if response.status == 200 then
core.log("Webhook sent successfully")
else
core.log_error("Webhook failed: " .. response.status)
end
end
)Discord Webhook
function on_evasion(player_names)
local names = table.concat(player_names, ", ")
local payload = '{"content":"Evasion triggered by: ' .. names .. '"}'
core.http.post("https://discord.com/api/webhooks/YOUR_WEBHOOK_URL",
payload,
"application/json",
function(response)
if response.status ~= 204 then
core.log_error("Discord webhook failed: " .. response.status)
end
end
)
endReading Response Headers
core.http.get("https://httpbin.org/response-headers?X-Custom=hello", function(response)
for name, value in pairs(response.headers) do
core.log(name .. ": " .. value)
end
end)