A Typical HTTP Session

An HTTP session is a sequence of request-response exchanges between a client and a server. The client establishes a connection, sends a request, and the server returns a response. HTTP is stateless by design, so each request is independent. State persistence across requests relies on mechanisms like Cookies or server-side session storage.

Usage

HTTP follows a client-server model. The client (typically a browser) initiates the exchange by opening a connection, sending a request message, and waiting for the server's response. The protocol defines the message format, but the underlying transport differs by HTTP version.

Every HTTP session follows three stages:

  1. Connection establishment opens a transport channel between client and server.
  2. Request transmits the client's message, including the method, target resource, headers, and an optional body.
  3. Response returns the server's answer, including a status code, headers, and an optional body.

HTTP versions and transport

HTTP/1.1

HTTP/1.1 uses TCP as the transport protocol. A TCP three-way handshake (SYN, SYN-ACK, ACK) establishes the connection before any HTTP data flows. For HTTPS, a TLS handshake follows the TCP handshake, adding one or two additional round-trips depending on the TLS version.

HTTP/1.1 introduced persistent connections (keep-alive) as the default behavior. The connection remains open after a response, allowing multiple request-response exchanges over the same TCP connection. The Connection header with close signals the end of persistence.

Connection: keep-alive

Pipelining allows the client to send multiple requests without waiting for each response, but responses must arrive in order. Head-of-line blocking occurs when a slow response delays all subsequent responses on the same connection.

HTTP/2

HTTP/2 multiplexes multiple request-response streams over a single TCP connection. Each stream is independent, removing the head-of-line blocking at the HTTP layer, eliminating the bottleneck of HTTP/1.1 pipelining. Binary framing replaces the text-based format of HTTP/1.1, and HPACK header compression reduces overhead for repeated headers across requests.

Server Push removed

HTTP/2 server push allowed the server to send resources before the client requested them. Browsers have deprecated and removed support for server push due to low adoption and difficulty predicting which resources to push. HTTP/2 retains the feature in the specification, but browsers no longer honor push responses.

HTTP/3

HTTP/3 replaces TCP with QUIC as the transport protocol. QUIC runs over UDP and provides built-in TLS 1.3 encryption, connection multiplexing with independent streams, and faster connection establishment. Because QUIC streams are independent at the transport level, a lost packet on one stream does not block other streams. This eliminates the TCP-level head-of-line blocking present in HTTP/2.

QUIC combines the transport and TLS handshake into a single round-trip for new connections. Resumed connections support zero round-trip (0-RTT) data, allowing the client to send HTTP requests immediately.

Connection establishment

The default port for HTTP is 80. The default port for HTTPS is 443. A different port is specified in the URL:

https://www.example.re:8443/api

For HTTP/1.1, the client opens a TCP connection to the server's IP address and port. For HTTP/3, the client establishes a QUIC connection. The server advertises HTTP/3 support through the Alt-Svc response header or a DNS HTTPS record, prompting the client to upgrade.

The request

An HTTP request consists of a request line, headers, an empty line, and an optional body.

Request line

The request line contains the HTTP method, the request target (path and query), and the protocol version, each separated by a space:

GET /index.html HTTP/1.1

Request line format

The method comes first, followed by the target and protocol version. There is no protocol prefix before the method.

Request headers

Headers provide metadata about the request. Each header is a field name, a colon, optional whitespace, and the field value. In HTTP/1.1, the Host header is the only required header.

Host: www.example.re
Accept: text/html
Accept-Encoding: gzip, br

Message body

The body carries data for methods like POST and PUT. The Content-Length header declares the body size in bytes. Alternatively, Transfer-Encoding: chunked sends the body in pieces without knowing the total size in advance.

Request examples

A simple GET request fetches the root page:

GET / HTTP/1.1
Host: www.example.re

A PUT request sends JSON data to update a resource:

PUT /customers/100 HTTP/1.1
Host: www.example.re
Content-Type: application/json
Content-Length: 72

{
    "CustID": 100,
    "Name": "David Smith",
    "Address": "123 Bank Street"
}

The response

The server processes the request and returns a response consisting of a status line, headers, an empty line, and an optional body.

Status line

The status line contains the protocol version, a three-digit status code, and a human-readable reason phrase:

HTTP/1.1 200 OK

Status codes are grouped by the first digit: 1xx informational, 2xx success, 3xx redirection, 4xx client error, and 5xx server error.

Response headers

Response headers describe the server, the content being returned, and Caching or security directives:

Content-Type: text/html; charset=utf-8
Content-Length: 4821
Cache-Control: max-age=3600

Response body

The body contains the requested resource. For an HTML page, the body is the HTML document. For an API response, the body is JSON, XML, or another data format. Responses to HEAD requests and 204 No Content responses carry no body.

Connection persistence

In HTTP/1.0, the connection closes after each response by default. The client opens a new TCP connection for every request, adding latency from repeated handshakes.

HTTP/1.1 keeps connections open by default. Multiple request-response exchanges reuse the same connection, reducing handshake overhead. The server or client closes the connection by sending Connection: close.

HTTP/2 and HTTP/3 use a single connection for the entire session, multiplexing all requests and responses over independent streams.

Statefulness

HTTP is a stateless protocol. The server does not retain information about previous requests from the same client. Each request is self-contained.

Applications build statefulness on top of HTTP through:

  • Cookies store small values on the client and send them with each request, allowing the server to associate requests with a session.
  • Server-side sessions store state in server memory or a database, keyed by a session identifier carried in a cookie or URL parameter.
  • Tokens such as Bearer tokens carry Authentication state in request headers without server-side storage.

Example

A complete HTTP/1.1 session. The client establishes a TCP connection, sends a GET request, and receives an HTML response.

Request

GET /report HTTP/1.1
Host: www.example.re
Accept: text/html
Accept-Encoding: gzip, br
Connection: keep-alive

Response

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 4821
Connection: keep-alive
Cache-Control: max-age=600

<!doctype html>
<html>
  <head><title>Report</title></head>
  <body>
    <p>Annual report data.</p>
  </body>
</html>

The Connection: keep-alive header on both sides signals the connection stays open for additional requests. The client reuses the same TCP connection for subsequent requests without a new handshake.

A 404 Not Found response on the same connection:

Request

GET /missing HTTP/1.1
Host: www.example.re
Accept: text/html

Response

HTTP/1.1 404 Not Found
Content-Type: text/html; charset=utf-8
Content-Length: 135

<!doctype html>
<html>
  <head><title>Not Found</title></head>
  <body>
    <p>The requested page does not exist.</p>
  </body>
</html>

Takeaway

An HTTP session follows a three-stage pattern: connection establishment, request, and response. The transport layer differs by HTTP version, with HTTP/1.1 using TCP, HTTP/2 multiplexing over TCP, and HTTP/3 running over QUIC. Persistent connections reduce latency by reusing the transport channel across multiple exchanges. HTTP remains stateless at the protocol level, with Cookies and server-side sessions providing application-level state management.

See also

Last updated: March 6, 2026