Lua Academy · Lesson

HTTP Requests

Fetch web resources.

Lesson 4 of 413 steps

HTTP Requests is a free Lua Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, and your progress syncs across the web and the CoddyKit app. The Lua Academy course includes 4 lessons in total.

The socket.http Module

LuaSocket ships a high-level HTTP client in socket.http. It builds on raw TCP but handles request formatting, headers, and chunked decoding for you.

It speaks HTTP/1.1 over plain TCP. For HTTPS you need the companion ssl.https module from LuaSec.

local http = require("socket.http")
print(http.PORT)

A Simple GET

The simplest form takes a URL and returns the body, status code, response headers, and status line.

A status code of 200 means success. Any nil body indicates a transport-level failure rather than an HTTP error.

local http = require("socket.http")
local body, code, headers = http.request("http://example.com/")
print(code, #body)

Reading the Status

Always check the numeric code before trusting the body. A 404 still returns a body (the error page), so the call succeeded at the TCP level.

The fourth return value is the status line string, like "HTTP/1.1 200 OK", useful for logging.

local body, code, headers, status = http.request(url)
if code == 200 then
  process(body)
else
  print("unexpected:", status)
end

Inspecting Headers

The returned headers table has lowercased keys, so you read headers["content-type"] regardless of how the server cased it.

Common fields include content-length, content-type, and location for redirects.

local body, code, headers = http.request(url)
print(headers["content-type"])
print(headers["content-length"])

The Generic Request Form

Passing a table to http.request unlocks full control: method, custom headers, request body source, and a sink for the response.

This form returns 1 (not the body) plus code, headers, and status. You collect the body yourself via the sink.

local http = require("socket.http")
local ltn12 = require("ltn12")
local chunks = {}
http.request{
  url = "http://example.com/",
  sink = ltn12.sink.table(chunks)
}

Sending a POST

For POST, set method = "POST", supply a source with the body, and set content-length. The ltn12.source.string helper wraps a Lua string as a source.

Set content-type to match your payload, such as application/json.

local body = "{\"name\":\"Lua\"}"
http.request{
  url = url,
  method = "POST",
  source = ltn12.source.string(body),
  headers = {
    ["content-type"] = "application/json",
    ["content-length"] = tostring(#body)
  }
}

Collecting the Body with ltn12

LuaSocket streams data through ltn12 filters. A sink consumes chunks; ltn12.sink.table(t) appends them to a table you then table.concat.

This streaming model keeps memory low for large downloads instead of buffering everything at once.

local ltn12 = require("ltn12")
local t = {}
http.request{ url = url, sink = ltn12.sink.table(t) }
local full = table.concat(t)

Custom Request Headers

Add authentication, user agents, or cookies through the headers table. Keys should be lowercase to match how LuaSocket expects them.

For example, send a bearer token or a custom user-agent so the server identifies your client correctly.

http.request{
  url = url,
  headers = {
    ["authorization"] = "Bearer " .. token,
    ["user-agent"] = "lua-client/1.0"
  }
}

Following Redirects

By default socket.http follows redirects automatically for GET. You can disable this with redirect = false in the request table to inspect the 3xx response yourself.

When following is off, read headers["location"] to find the next URL.

local body, code, headers = http.request{
  url = url,
  redirect = false
}
if code == 301 then print("moved to", headers["location"]) end

Timeouts and HTTPS

Set a global timeout for HTTP calls with http.TIMEOUT = 10, since hung downloads otherwise block forever.

Because socket.http is plaintext only, use require("ssl.https") from LuaSec for https:// URLs; its API mirrors socket.http.

local http = require("socket.http")
http.TIMEOUT = 10
-- for TLS:
local https = require("ssl.https")
local body, code = https.request("https://example.com/")

Error Handling

Distinguish two failure layers. A transport failure returns nil and an error string such as "connection refused" or "timeout".

An application failure returns a body with a 4xx or 5xx code. Robust code checks the nil case first, then branches on the status code.

local body, code = http.request(url)
if not body then
  print("transport error:", code)
elseif code >= 400 then
  print("http error:", code)
end

Quick Check

Recall what the simple URL form of http.request returns.

Recap

You learned the socket.http module: simple GETs returning body/code/headers, the generic table form with ltn12 sinks and sources, POST bodies, custom headers, redirects, and timeouts.

You also separated transport errors (nil) from HTTP status errors, and saw that HTTPS needs LuaSec's ssl.https. That completes the networking journey from raw TCP to HTTP.

Free to start

Learn Lua with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
40
Lessons
159

Frequently Asked Questions

Is the “HTTP Requests” lesson free?

Yes — any 3 lessons of the Lua Academy learning path, including “HTTP Requests”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Lua Academy course includes 4 lessons in total.

What will I learn in “HTTP Requests”?

Fetch web resources. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Lua Academy?

No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

How long does the “HTTP Requests” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Lua Academy lesson?

Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. TCP Basics
  2. Building a Client
  3. Building a Server
  4. HTTP Requests
← Back to Lua Academy