HTTP/1.1
The web's language: readable text, a request line, headers, a blank line.
A request
Every byte is readable text. The ASCII row under the hex shows the letters.
Whole frame
The whole request is readable ASCII: a request line, three headers and a blank line. There is no length field; the blank line is the delimiter.
| Field | Offset | Example value | Meaning |
|---|---|---|---|
| Method | Byte 0–2 | GET | What to do with the resource. GET = fetch it. Others: POST (send data), PUT (replace), DELETE, HEAD (headers only). |
| Space | Byte 3 | 0x20 | A single space (0x20) separates the parts of the request line. |
| Target | Byte 4 | / | The path (and query) being requested. '/' is the site root. |
| Space | Byte 5 | 0x20 | Another separator. |
| Version | Byte 6–13 | HTTP/1.1 | The protocol version, spelled out in ASCII. |
| CRLF | Byte 14–15 | 0D 0A | Carriage Return + Line Feed (0D 0A) ends every line. HTTP/1.1 is a text protocol: you could type this into a raw TCP connection by hand. |
| Host header | Byte 16–34 | Host: example.com | 'Name: value' lines are headers. Host is the only mandatory one in HTTP/1.1: it tells a server hosting many sites which one you want, since the IP address alone cannot. |
| User-Agent header | Byte 35–56 | User-Agent: curl/8.4 | Identifies the client software. Servers use it for statistics, and sometimes for guessing what content to send. |
| Accept header | Byte 57–69 | Accept: */* | Which content types the client can handle. */* means anything. |
| Blank line | Byte 70–71 | 0D 0A | An empty line (just CRLF) marks the end of the headers. A GET has no body, so the request ends here; for a POST the body would follow. |
Overview
HTTP/1.1 is the text format browsers and servers have used since 1997. A request is a request line (method, path, version), headers, a blank line, and an optional body; a response mirrors it with a status line. Everything is plain ASCII up to the body, and every line ends in CRLF.
HTTP/2 and HTTP/3 change the encoding (binary frames, header compression, QUIC) but keep the same ideas: methods, status codes and headers.
Key facts
- Transport
- TCP (80, or 443 with TLS)
- Encoding
- ASCII text, CRLF lines
- Style
- Request / response
- Mandatory header
- Host
- Body length
- Content-Length or chunked
- Standard
- RFC 9112 / 9110
A response
A status line, headers, a blank line and then exactly Content-Length bytes of body.
Whole frame
Status line, headers, blank line, body. Content-Length says exactly how many body bytes to read.
| Field | Offset | Example value | Meaning |
|---|---|---|---|
| Version | Byte 0–7 | HTTP/1.1 | The server's HTTP version. |
| Space | Byte 8 | 0x20 | Separator. |
| Status code | Byte 9–11 | 200 | The outcome as a number: 2xx success, 3xx redirect, 4xx client error (404 not found), 5xx server error. |
| Space | Byte 12 | 0x20 | Separator. |
| Reason phrase | Byte 13–14 | OK | A human-readable label for the code. Programs ignore it and look at the number. |
| CRLF | Byte 15–16 | 0D 0A | Carriage Return + Line Feed (0D 0A) ends every line. HTTP/1.1 is a text protocol: you could type this into a raw TCP connection by hand. |
| Content-Type header | Byte 17–42 | Content-Type: text/plain | What kind of data the body is, so the client knows how to interpret it (text/plain, text/html, application/json, image/png...). |
| Content-Length header | Byte 43–62 | Content-Length: 13 | The body length in bytes. This is how the client knows where the body ends, since the connection may stay open for the next request. |
| Blank line | Byte 63–64 | 0D 0A | End of the headers. |
| Body | Byte 65–77 | Hello, world! | The content itself: exactly Content-Length bytes. |
Requests on one connection
Keep-alive reuses the TCP connection.
Whole exchange
HTTP is request and response, one after another, on top of a reliable TCP stream.
1Request
Sent inside the established TCP connection (see the TCP page for the handshake that comes before this).
2Response
The server answers on the same connection. With HTTP/1.1 keep-alive the connection stays open, so the next request skips the handshake.
3Next request, no new handshake
Reusing the connection saves a round trip per request. HTTP/2 and HTTP/3 go further and interleave many requests at once.
Where you meet it
- Every website and nearly every web API (REST, JSON over HTTP)
- `curl -v` prints exactly these lines, which is the quickest way to see HTTP
- Webhooks, package downloads, software updates
Watch out for
- A bare LF instead of CRLF, or a missing blank line, makes strict servers answer 400 Bad Request.
- Content-Length must match the body byte count (not characters): multibyte text breaks naive length code.
- Plain HTTP is readable by anyone on the path. HTTPS wraps the same text in TLS.
Standards
- RFC 9112: HTTP/1.1
- RFC 9110: HTTP Semantics