The three parts of an HTTP request
An HTTP request has three parts. The request line names the action and the resource. Headers describe the request and the client, and an optional body carries data such as JSON or form fields.
In HTTP/1.1 all of this is plain text. Each line ends with a carriage return and line feed (CRLF), and a blank line separates the headers from the body. This request, sent by a shop's web page to its own API, adds two items to a cart:
POST /api/cart/items HTTP/1.1
Host: shop.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36
Accept: application/json
Accept-Encoding: gzip, deflate, br, zstd
Cookie: session_id=8f3a2c91; theme=dark
Authorization: Bearer 2f8c41a9e07b
Content-Type: application/json
Content-Length: 36
{"sku":"TSHIRT-M-BLUE","quantity":2}The request line: method, target and version
In the example, the first line, POST /api/cart/items HTTP/1.1, holds three fields separated by spaces. The method says what the client wants done. Next comes the request target, usually a path plus any query string such as /search?q=dns, and last the protocol version.
HTTP/2 and HTTP/3 carry the same information in pseudo-header fields named :method, :scheme, :authority and :path, which is what developer tools show for those requests. The fragment of a URL, the part after #, is never sent to the server.
These are the methods you will meet most often:
- GET reads a resource and should never change anything on the server.
- HEAD is GET without the response body, useful for checking headers or whether a URL exists.
- POST submits data for the server to process, such as a form, an upload or a new order.
- PUT replaces the resource at the target URL with the request body.
- PATCH changes part of a resource.
- DELETE removes the resource.
- OPTIONS asks which methods and features a resource supports. Browsers send it as the CORS preflight before some cross-origin requests.
The request headers that matter most
Each header is a name, a colon and a value. Names are case-insensitive, and HTTP/2 and HTTP/3 send them in lowercase. A browser request can carry dozens of headers, but these eight do most of the work:
- Host names the site being requested, such as shop.example.com. One IP address can serve many sites, so the server uses Host to pick one, and an HTTP/1.1 request without it gets 400 Bad Request.
- User-Agent identifies the client software and version. Servers use it for logs and compatibility fixes, but any client can send any value, so it proves nothing.
- Accept lists the media types the client can handle, such as text/html or application/json, optionally ranked with q values.
- Accept-Encoding lists the compression formats the client can decode, such as gzip, br (Brotli) and zstd. The server picks one and names it in its Content-Encoding header.
- Cookie returns the cookies the browser stored for this site, as name=value pairs separated by semicolons.
- Authorization carries credentials: Bearer followed by an access token, or Basic followed by a user name and password in base64. Base64 hides nothing, so this header must only travel over HTTPS.
- Content-Type describes the body, such as application/json, application/x-www-form-urlencoded for a simple HTML form, or multipart/form-data for file uploads.
- Content-Length gives the body size in bytes. A wrong value can cut the body short or leave the server waiting for bytes that never arrive.
The request body
The body starts after the blank line that ends the headers. Its format is whatever Content-Type says, and its size comes from Content-Length or, in HTTP/1.1, from chunked transfer encoding when the size isn't known in advance.
GET, HEAD and DELETE requests normally have no body. RFC 9110 gives a body on a GET request no defined meaning. Some servers and proxies reject or drop it, so send read parameters in the query string.
Safe and idempotent methods
A method is safe if it only reads: GET, HEAD, OPTIONS and TRACE. It is idempotent if sending the same request twice has the same effect as sending it once. That covers the safe methods plus PUT and DELETE. POST and PATCH are neither by default.
These properties decide what clients may do on their own. HTTP libraries and proxies may retry an idempotent request after a dropped connection. A browser asks before resending a POST form, because a repeat could place a second order.
Crawlers, link checkers and browser prefetching follow GET links freely. Any of them can trigger a GET link that deletes a record or signs a user out. State changes belong in POST, PUT, PATCH or DELETE requests.