HTTP (Hypertext Transfer Protocol) is the stateless, request-response application protocol in which a client sends a request for a resource identified by a URL and a server returns a response with a status code, header fields and an optional body. Among Internet protocols it is the foundation of the web and of most APIs, software updates and machine-to-machine traffic.
HTTP defines semantics that stay constant across versions: methods, status codes, header fields and caching rules. Only the way messages travel on the wire changes, from text over TCP in HTTP/1.1 to binary frames in HTTP/2 and streams over QUIC in HTTP/3.
How an HTTP exchange works
Every HTTP exchange consists of one request and one final response, and the client always speaks first. A request names a method, a target such as /orders/42, the protocol version and a set of header fields; the server answers with a three-digit status code, its own header fields and usually a body.
Before the exchange, the client resolves the host name through DNS and opens a transport connection, usually protected by TLS when the scheme is HTTPS. Persistent connections let many exchanges reuse the same connection, which avoids repeated handshakes.
Statelessness means that each request carries everything the server needs to process it. Applications build sessions on top of HTTP with cookies, tokens or other header fields, not with the protocol itself.
HTTP methods and their properties
The method states what the client wants to do with the resource, and two formal properties govern how intermediaries and clients may treat it. A safe method must not change server state, and an idempotent method produces the same result whether it is sent once or several times, which makes automatic retries possible.
The table below lists the methods that appear in most web and API traffic.
| Method | Purpose | Safe | Idempotent |
|---|---|---|---|
| GET | Retrieve a representation of a resource | Yes | Yes |
| HEAD | Retrieve only the header fields | Yes | Yes |
| POST | Submit data for processing | No | No |
| PUT | Create or replace a resource at a known URL | No | Yes |
| PATCH | Apply a partial modification | No | Not guaranteed |
| DELETE | Remove a resource | No | Yes |
| OPTIONS | Ask which communication options are allowed | Yes | Yes |
A common design error is to change data with GET requests. Crawlers, prefetchers and caches assume GET is safe, so such endpoints can delete or modify data without any user action.
Status codes and header fields
The status code tells the client how the server handled the request, and its first digit defines the class. Clients that do not recognize a specific code must treat it as the generic x00 code of its class.
| Class | Meaning | Typical examples |
|---|---|---|
| 1xx informational | Interim response, request continues | 100 Continue, 103 Early Hints |
| 2xx success | Request accepted and processed | 200 OK, 201 Created, 204 No Content |
| 3xx redirection | Further action is needed elsewhere | 301, 304 Not Modified, 308 |
| 4xx client error | The request is faulty or not allowed | 400, 401, 403, 404, 429 |
| 5xx server error | The server failed a valid request | 500, 502, 503, 504 |
Header fields carry metadata about the message and the resource: content type and length, caching instructions, authentication, compression and content negotiation. Key fields include Host, Content-Type, Cache-Control, ETag, Authorization and Accept. Field names are case-insensitive, and HTTP/2 and HTTP/3 transmit them in lowercase with header compression.
HTTP versions compared
Each HTTP version keeps the same semantics but changes the wire format and transport to reduce latency. Servers and clients negotiate the version during the TLS handshake through ALPN, or discover HTTP/3 through an Alt-Svc header field or an HTTPS DNS record.
| Version | Wire format | Transport | Key limitation addressed |
|---|---|---|---|
| HTTP/1.1 | Text messages | TCP | Persistent connections, Host field |
| HTTP/2 | Binary frames, multiplexed streams | TCP | Request-level head-of-line blocking |
| HTTP/3 | Binary frames over QUIC streams | QUIC over UDP | TCP-level head-of-line blocking |
HTTP/2 multiplexes many requests on one TCP connection, but a single lost packet stalls every stream on that connection. HTTP/3 removes that bottleneck because QUIC recovers losses per stream, and it also survives network changes such as a phone moving from Wi-Fi to mobile data.
Caching and common pitfalls
HTTP has a built-in caching model that lets browsers, proxies and content delivery networks reuse responses. Cache-Control sets freshness, while validators such as ETag and Last-Modified let a cache revalidate a stale copy with a conditional request that returns 304 Not Modified instead of the full body.
The problems below account for many HTTP-related incidents and performance issues.
| Symptom | Likely cause | Fix |
|---|---|---|
| Users see outdated content | Long max-age on changing resources | Version file names, revalidate HTML |
| Private data in a shared cache | Personalized response marked public | Send Cache-Control: private or no-store |
| Duplicate orders after retries | Non-idempotent POST retried | Use idempotency keys |
| Redirect loops | Conflicting HTTP and HTTPS redirects | Redirect once, then use HSTS |
| Credentials exposed in transit | Plain HTTP without TLS | Serve everything over HTTPS |
Plain HTTP offers no confidentiality or integrity: any party on the path can read or alter the traffic. For that reason, current practice is to serve all traffic over HTTPS and to treat unencrypted HTTP only as a redirect to the secure version.
Stripped to the essentials
HTTP is the common language of the web. Your browser or app sends a short request, such as asking for a page or saving a form, and the server sends back an answer with a number that says how it went, like 200 for success or 404 for not found.
Each request stands on its own, much like separate letters rather than one phone call. Everything you load on a website travels as HTTP requests and responses, usually wrapped in encryption.
Where it is applied
A mobile banking app shows a customer’s recent transactions. When the screen opens, the app sends a GET request with an access token in the Authorization header, and the API returns 200 OK with a JSON body and an ETag value.
When the customer refreshes the list a minute later, the app sends a conditional request with If-None-Match. Nothing has changed, so the server answers 304 Not Modified with no body, which saves bandwidth and battery. A transfer is sent as a POST with an idempotency key, so a retry after a dropped mobile connection cannot create a duplicate payment. All of this runs over HTTP/3, which keeps the session alive when the phone switches networks.