The HTTP protocol
By Flavio Copes
Learn how HTTP requests and responses power the web, including URLs, methods, headers, status codes, bodies, versions, HTTPS, and statelessness.
HTTP stands for Hypertext Transfer Protocol.
It is the application-layer protocol browsers, servers, APIs, command-line clients, and intermediaries use to exchange messages on the web.
A client sends a request. A server returns a response.
HTTP transfers more than HTML. It carries JSON, images, video, fonts, form data, and any other representation described by its metadata.
HTTP and HTTPS
Plain HTTP does not encrypt a message.
HTTPS protects HTTP with TLS. It encrypts the connection, authenticates the server certificate, and protects data from modification while in transit.
Use HTTPS for websites and APIs. Redirecting plain HTTP to HTTPS is useful, but the first unencrypted request is still exposed unless the browser already knows to use HTTPS.
HTTP semantics stay mostly the same across HTTP/1.1, HTTP/2, and HTTP/3:
- HTTP/1.1 uses a textual message format over TCP
- HTTP/2 uses binary frames and multiplexes streams over one TCP connection
- HTTP/3 maps HTTP semantics to QUIC, which runs over UDP and includes TLS
Applications normally let the browser, server, and network negotiate the available version.
Read a URL
Consider this URL:
https://flaviocopes.com/http/?format=markdown#methods
Its main parts are:
httpsis the schemeflaviocopes.comis the host/http/is the pathformat=markdownis the querymethodsis the fragment
The fragment is handled by the client and is not sent in the HTTP request.
The default port is 80 for HTTP and 443 for HTTPS. A URL can specify another port explicitly.
An HTTP request
An HTTP/1.1 request can look like this:
GET /http/ HTTP/1.1
Host: flaviocopes.com
Accept: text/html
User-Agent: tutorial-client/1.0
The first line contains:
- the method
- the request target
- the HTTP version
Headers follow. An empty line ends the header section. Some requests then contain a body.
HTTP/2 and HTTP/3 do not send this exact textual format on the wire, but they preserve the same method, target, header, and content concepts.
An HTTP response
An HTTP/1.1 response can look like this:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 19
Cache-Control: max-age=60
<h1>Hello HTTP</h1>
The response contains:
- a version
- a status code
- headers
- optional content
Content-Type describes the representation. Content-Length gives its size when the sender knows it and uses that framing.
HTTP/2 and HTTP/3 use different framing and do not use the HTTP/1.1 status line, but clients still expose the status and headers.
Common HTTP methods
The method describes the request’s purpose.
GET
GET retrieves a representation of a resource:
GET /posts/42 HTTP/1.1
Host: api.flaviocopes.com
GET is safe and idempotent by definition. It should not ask the server to change application state.
HEAD
HEAD asks for the same headers a GET request would return, without response content.
It is useful for checking metadata such as modification time, size, or cache validators.
POST
POST submits content for the resource to process:
POST /comments HTTP/1.1
Host: api.flaviocopes.com
Content-Type: application/json
{"message":"Great tutorial"}
POST can create a resource, trigger an action, or process a form. Its meaning comes from the target resource.
POST is not idempotent by default. Repeating it can create another result.
PUT
PUT creates or replaces the state of the target resource with the request content:
PUT /profiles/42 HTTP/1.1
Host: api.flaviocopes.com
Content-Type: application/json
{"name":"Flavio"}
PUT is idempotent: repeating the same request should have the same intended effect as sending it once.
PATCH
PATCH applies a partial modification described by the request content.
Its idempotency depends on the patch format and operation.
DELETE
DELETE asks the server to remove the association for the target resource.
It is idempotent in HTTP semantics. Repeating it does not promise the same status code, only the same intended server state.
OPTIONS
OPTIONS asks about communication options for a resource or server.
A response can include an Allow header. Browsers also use OPTIONS for some CORS preflight requests.
The protocol defines other methods, including CONNECT and TRACE. Servers often restrict them unless an application specifically needs them.
Safe and idempotent are different
A safe method asks only to read or inspect state. GET, HEAD, and OPTIONS are safe.
An idempotent method has the same intended effect when repeated. Safe methods are idempotent, and PUT and DELETE are idempotent too.
These are protocol semantics, not automatic enforcement. A server can still implement a method incorrectly.
The distinction matters when a client, proxy, or load balancer considers retrying a request.
Status codes
The response status describes the result.
The first digit gives the category:
1xx: informational2xx: successful3xx: redirection4xx: client-side request problem5xx: server-side failure
Common examples include:
200 OK201 Created204 No Content301 Moved Permanently304 Not Modified400 Bad Request401 Unauthorized403 Forbidden404 Not Found429 Too Many Requests500 Internal Server Error503 Service Unavailable
The response body can provide more details. Clients should use the numeric status, not depend on the optional reason phrase used by HTTP/1.1.
Headers
Headers carry metadata and control how a message is handled.
Request headers can describe:
- acceptable response formats
- authorization credentials
- cookies
- cache conditions
- the requesting origin
Response headers can describe:
- content type and encoding
- caching rules
- cookies to store
- redirects
- security policies
- cross-origin permissions
Header names are case-insensitive. Header values have rules defined by each field.
Do not put secrets in URLs. URLs can appear in browser history, logs, analytics, and referrer information. Use an authorization header or protected request content according to the API design.
HTTP is stateless, but sessions exist
HTTP does not automatically connect one request’s application state to the next.
Applications add state with cookies, authorization tokens, URL data, or server-side session storage.
The transport connection can still be persistent. HTTP/1.1 can reuse a TCP connection, HTTP/2 multiplexes streams on one connection, and HTTP/3 multiplexes streams over QUIC.
Protocol statelessness and connection reuse are different concepts.
Intermediaries
A request can pass through proxies, gateways, load balancers, and content delivery networks before reaching the origin server.
Intermediaries can:
- cache responses
- terminate TLS
- compress content
- route traffic
- authenticate requests
- enforce security rules
HTTP headers let the origin and intermediaries coordinate this behavior.
Inspect HTTP with curl
Use curl -i to include response headers:
curl -i https://flaviocopes.com/http/
Use -I to make a HEAD request:
curl -I https://flaviocopes.com/http/
Use verbose mode to inspect connection and request details:
curl -v https://flaviocopes.com/http/
The output changes with the server, CDN, negotiated protocol, and current configuration. Learn the structure instead of copying one old response literally.
For the current definitions, see MDN’s HTTP overview and HTTP methods, RFC 9110: HTTP Semantics, and RFC 9114: HTTP/3.
Related posts about network: