HTTP Cheatsheet

Request and Response

Use this HTTP reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Anatomy of a request

An HTTP/1.1 request is a start line, header fields, a blank line, then an optional body. Line endings are CRLF.

POST /api/orders?draft=true HTTP/1.1
Host: api.example.com
User-Agent: curl/8.7.1
Accept: application/json
Content-Type: application/json
Content-Length: 38
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

{"sku":"HU-100","qty":2,"currency":"usd"}
PartValue aboveRules
MethodPOSTcase sensitive, always uppercase
Request target/api/orders?draft=trueorigin form for normal requests
VersionHTTP/1.1absent in HTTP/2 and /3, which are binary
Hostapi.example.comrequired in 1.1, becomes :authority in 2 and 3
HeadersName: valuefield names are case insensitive
Blank lineCRLF CRLFends the header block
Bodythe JSONlength set by Content-Length or chunked framing

Request target forms: origin (/path?query, the normal case), absolute (https://host/path, used to a proxy), authority (host:port, only for CONNECT), and asterisk (*, only for OPTIONS).

Anatomy of a response

HTTP/1.1 201 Created
Date: Tue, 15 Sep 2026 10:04:11 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 52
Location: /api/orders/8814
Cache-Control: no-store
ETag: "9c1f2a"

{"id":8814,"sku":"HU-100","qty":2,"status":"draft"}

The status line is version, a three-digit code, and a reason phrase. The reason phrase carries no meaning and HTTP/2 and /3 drop it entirely, so never parse it.

URL structure

 https://user:pw@api.example.com:8443/v1/orders?limit=20&sort=-date#top
 \___/   \_____/ \_____________/ \__/\________/ \________________/ \_/
 scheme  userinfo    host        port   path         query      fragment
ComponentNotes
schemehttp (port 80) or https (port 443), case insensitive
userinfodeprecated, browsers strip it, treat it as a phishing signal
hostDNS name, IPv4, or a bracketed IPv6 literal [2001:db8::1]
portomitted when it is the scheme default
pathsent to the server, case sensitive by convention
query?k=v&k2=v2, percent-encoded, repeated keys are allowed
fragmentnever sent to the server, client side only

Reserved characters must be percent-encoded inside a component: space is %20 (or + in a form body), & is %26, = is %3D, ? is %3F, # is %23, / is %2F, + is %2B, % is %25.

Message framing

The receiver has to know where the body ends. There are exactly three ways.

MechanismHeaderUsed when
Fixed lengthContent-Length: 512the size is known up front
ChunkedTransfer-Encoding: chunkedstreaming, size unknown (HTTP/1.1 only)
Connection closeneitherHTTP/1.0 legacy, response ends at EOF
HTTP/1.1 200 OK
Transfer-Encoding: chunked

1a
{"partial":"first chunk"}
10
{"more":"data"}
0

Each chunk is a hex length, CRLF, the bytes, CRLF. A zero-length chunk ends the body, optionally followed by trailer fields.

Sending both Content-Length and Transfer-Encoding: chunked is the source of request smuggling, because a proxy and an origin may disagree on which one wins. Compliant servers must reject such a message. HTTP/2 and /3 have explicit frame lengths, so the ambiguity disappears.

Connection reuse and pipelining

HTTP/1.1 keeps the TCP connection open by default, so subsequent requests skip the handshake.

HeaderEffect
Connection: keep-alivereuse, the 1.1 default, only explicit in 1.0
Connection: closeclose after this exchange
Keep-Alive: timeout=5, max=100non-standard hint on idle time and count

Pipelining (sending several requests before reading replies) is defined but effectively unused, because responses must return in order and one slow response blocks the rest. That head-of-line blocking is what HTTP/2 multiplexing was built to solve.

Idempotent requests may be safely retried on a connection the server closes. POST may not, without an idempotency key.

Sending requests by hand

curl -v https://api.example.com/v1/orders
curl -i -X POST https://api.example.com/v1/orders \
  -H 'Content-Type: application/json' \
  -d '{"sku":"HU-100","qty":2}'
curl -sI https://example.com                  # headers only, HEAD request
curl -s -o /dev/null -w '%{http_code} %{time_total}\n' https://example.com
curl -s --http1.1 -D - https://example.com -o /dev/null   # dump headers
curl --data-urlencode 'q=hack university' https://example.com/search
curl -F file=@report.pdf -F title=Q3 https://example.com/upload
curl -L https://example.com                   # follow redirects
curl -k https://localhost:8443                # skip cert verification, dev only
# raw HTTP over a plaintext port
printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' \
  | nc example.com 80

# raw HTTP over TLS
printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' \
  | openssl s_client -quiet -connect example.com:443 -servername example.com
Useful curl flagDoes
-iinclude response headers in the output
-IHEAD only
-v / --trace-ascii -handshake and header trace
-Lfollow Location redirects
-Hadd or override a request header
-d / --data-binaryrequest body, implies POST
-Xoverride the method
--compressedsend Accept-Encoding and decode the reply
--resolve host:port:iptest one origin without touching DNS
-wprint timing and metadata after the transfer