Networking16 min read

HTTP Request and Response Messages

An HTTP message is plain readable text with a strict shape. Once you can name the four parts and the blank line that separates them, reading a captured packet stops being guesswork.

Application layer · Web and HTTP
Built from

Every field, method and status code on this page is stated against RFC 9110 (HTTP semantics) and RFC 9112 (HTTP/1.1 message syntax), and every example message is written in the exact byte layout those documents specify.

How to use it

Read the vocabulary first. Study the two annotated messages until you can say what every line is doing, then cover them and work the numbered exercises. Do not open the solutions until you have written a real attempt.

Source note

Course slides commonly show HTTP/1.1 defined by RFC 2616. That document was replaced in 2014 and again in June 2022; the current split is RFC 9110 for semantics, 9111 for caching and 9112 for HTTP/1.1 syntax. The message format taught here did not change. Two things did move on, and this page flags them where they come up: Connection: keep-alive is a leftover of HTTP/1.0 habits because persistence is the default in 1.1, and Expires has largely been superseded by Cache-Control.

What HTTP actually moves#

A web page is not a file. It is a base HTML file plus the objects it refers to — images, stylesheets, scripts, fonts. Each object is separately addressable by a URL, and each is fetched by its own request. A page with ten images is eleven fetches, not one.

A URL splits into a host name and a path name:

www.example.edu /dept/photo.gif

The part before the first slash names the machine to connect to. The part after it names what to ask that machine for. The browser uses the first to open a connection and puts the second in the request.

Memory line

HTTP is the Web’s application-layer protocol, it runs over TCP, and the server listens on port 80. The client opens the TCP connection; the server never initiates one.

And one property that shapes everything else: HTTP is stateless. The server keeps no memory of what a client asked for previously. Every request is judged entirely on its own contents. That is a deliberate design choice — protocols that maintain state are complex, because the state has to be stored, and if either end crashes the two views of it have to be reconciled.

Vocabulary, before anything uses it#

TermWhat it means
ObjectA single addressable file that makes up part of a web page — an HTML file, an image, a script.
URLThe address of one object, made of a host name and a path name.
Request messageThe message a client sends to ask for something.
Response messageThe message a server sends back.
Request lineThe first line of a request: method, URL, HTTP version.
Status lineThe first line of a response: HTTP version, status code, status phrase.
Header lineA single Name: value line carrying information about the message.
Entity bodyThe payload of a message, after the blank line — the page itself, or submitted form data.
MethodThe verb of a request, saying what the client wants done: GET, POST, HEAD, PUT, DELETE.
Status codeThe three-digit number in a response saying how the request turned out.
StatelessKeeping no record between requests, so each request is interpreted on its own.
CRCarriage return, the byte written \r, part of the line terminator.
LFLine feed, the byte written \n, the other part of the line terminator.
CRLFThe two bytes together, which is how every line in an HTTP message ends.
MIME typeThe label saying what kind of data the body is, carried in Content-Type.
User agentThe client program making the request, usually a browser.

Fast symbol reference

What you seeSay it as
GETsend me this thing
POSThere is data, do something with it
HEADsend me the headers but not the thing
200here it is
301it lives somewhere else now, permanently
304the copy you already have is still good
404no such thing here
\r\nend of this line
\r\n\r\nend of the headers; the body starts now
Host:which site on this server I want
Content-Length:the body is exactly this many bytes

The request, line by line#

An HTTP request is ASCII text a person can read. Here is a complete one:

GET /index.html HTTP/1.1
Host: www.example.edu
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

Its shape is fixed, and it is the same shape every time:

  1. The request line — exactly one, always first, and always three fields separated by spaces: method, then URL (the path part), then HTTP version. In the example: GET, /index.html, HTTP/1.1.
  2. Header lines — zero or more, each of the form Name: value.
  3. A blank line — a carriage return and line feed with nothing before them. This is what tells the server the headers have ended.
  4. The entity body — empty on a GET, and carrying the submitted data on a POST.

What the individual headers in that example are doing:

HeaderWhat it is telling the server
HostWhich site is wanted. One server often hosts many sites on one IP address, so this is how it knows which. It is the one header HTTP/1.1 requires.
User-AgentWhat program is asking. Servers sometimes send different content to different clients.
AcceptWhat content types the client can handle.
Accept-LanguagePreferred languages, with q= weights giving relative preference.
Accept-EncodingCompressions the client can decode, so the server can send a smaller body.
ConnectionWhether the client wants the TCP connection left open after this exchange.
Do not confuse these

The blank line is not decoration. HTTP has no length field for the header section. The only thing marking where headers stop and the body starts is an empty line — the byte sequence \r\n\r\n. In a capture, that empty line is what you look for to find the boundary.

The URL in the request line is only the path. The host name is not in it; it is in the Host header. Writing the full http://www.example.edu/index.html into the request line is a common slip.

Methods, and what each one means#

MethodVersionWhat it asks for
GET1.0 and 1.1Send me the object at this URL. Any data goes in the URL itself, after a ?.
POST1.0 and 1.1Here is data in the entity body; process it. Used for form submissions.
HEAD1.0 and 1.1Send the headers you would send for a GET, but leave the object out. Used for testing and debugging.
PUT1.1Upload the object in the entity body to the path in the URL.
DELETE1.1Delete the object at the path in the URL.
Do not confuse these

GET with a query string is not POST. Both can carry form input. A GET puts it in the URL, where it is visible in the address bar, in browser history and in server logs. A POST puts it in the entity body, where it is not. Neither is encrypted by itself — that is what HTTPS is for.

HEAD is not a smaller GET. It returns the same headers a GET would return, with no body at all. Its purpose is to ask about an object without transferring it.

The response, line by line#

The response has the same four-part shape, with a status line in place of the request line:

HTTP/1.1 200 OK
Date: Sun, 06 Sep 2026 14:22:07 GMT
Server: Apache/2.4.62
Last-Modified: Tue, 01 Sep 2026 09:14:33 GMT
ETag: "a3f-6317c2b1"
Content-Length: 2652
Content-Type: text/html; charset=UTF-8
Expires: Mon, 07 Sep 2026 14:22:07 GMT
Connection: keep-alive

<!DOCTYPE html> ... the page itself ...

The status line has three fields: the version, the status code, and the status phrase — here HTTP/1.1, 200, OK. The phrase is for humans; software reads the number.

HeaderWhat it is telling the client
DateWhen the server generated this response. Not when the object was created.
ServerWhat software produced it, the mirror image of User-Agent.
Last-ModifiedWhen the object itself last changed. This is the date a cache uses for a conditional request.
ETagAn opaque version tag for this exact copy of the object.
Content-LengthHow many bytes of body follow, so the client knows when it has all of it.
Content-TypeWhat kind of data the body is, and its character encoding.
ExpiresThe date and time after which this copy should be treated as stale.
ConnectionWhether the server is keeping the TCP connection open.
Do not confuse these

Date, Last-Modified and Expires are three different times. Date is now, from the server’s clock. Last-Modified is in the past — when the object changed. Expires is in the future — when the copy goes stale. A question asking for “the expiration date in the response” wants Expires, and a capture with no Expires header usually has Cache-Control: max-age= instead, which does the same job as a duration rather than a timestamp.

Status codes worth knowing#

The first digit is the class, and knowing the five classes lets you place a code you have never seen:

ClassMeaning
1xxInformational — still going.
2xxSuccess.
3xxRedirection — you need to do something else to get it.
4xxClient error — the request was wrong.
5xxServer error — the request was fine, the server failed.

The individual codes that come up most:

CodePhraseWhat happened
200OKThe request succeeded and the object is in this message.
301Moved PermanentlyThe object has a new address, given in the Location header.
304Not ModifiedThe cached copy is still current, so no body is sent.
400Bad RequestThe server could not understand the request message.
404Not FoundNo such object on this server.
505HTTP Version Not SupportedThe server does not support the version in the request line.
Memory line

The status code is always the second field of the first line of a server-to-client message. If a question asks “what is the status of the response?”, the answer is on line one and nowhere else.

Worked example#

The question

Given the request and response messages above, state the method, the host contacted, the connection status requested, the response status, the protocol version in the response, and the expiration date.

Step 1 — Take the two first lines and read left to right. The request line is GET /index.html HTTP/1.1, so the method is the first field. The status line is HTTP/1.1 200 OK, so the version is the first field there and the status is the second.

Method = GET  ·  Status = 200 OK  ·  Version = HTTP/1.1

Step 2 — For everything else, name the header first, then read its value. Do not scan for a value that looks right; find the field whose name matches the thing being asked about. The host came from Host, not from the request line. The connection status came from Connection. The expiration came from Expires, not from Date and not from Last-Modified.

Host = www.example.edu  ·  Connection = keep-alive

Expires = Mon, 07 Sep 2026 14:22:07 GMT

Step 3 — Say which message each answer came from. Three of these are in the request and three in the response. An answer that quotes the right value from the wrong message is wrong, and it is the easiest mark to lose on a capture question.

What a full-credit answer contains

The value, the header or line field it came from, and which of the two messages it was in. “GET” is a value; “the method is GET, from the first field of the request line” is an answer.

Practice#

Answer from the two messages above without scrolling back up more than you have to.

  1. What are the three fields of a request line, in order?
  2. What are the three fields of a status line, in order?
  3. What marks the end of the header lines? Give the byte sequence.
  4. A response arrives with the status line HTTP/1.1 404 Not Found. What class of code is that, and whose fault is the failure?
  5. Which header tells the server which website is wanted, and why is it required in HTTP/1.1?
  6. A request line reads POST /search HTTP/1.1. Where is the submitted data, and where would it have been with GET?
  7. Name the three date headers in the example response and say which direction in time each points.
  8. A response has Content-Length: 2652. What is that counting, and why does the client need it?
  9. What does “HTTP is stateless” mean, and give one reason a protocol designer might want that.

Solutions#

Best study method

If your answer is wrong, find the first line where your reasoning diverged, then redo the problem from that point. Copying the solution across teaches nothing.

  1. Method, URL, version. The method, then the URL (the path part only), then the HTTP version — separated by single spaces and terminated by CRLF.
  2. Version, status code, status phrase. The HTTP version, then the three-digit status code, then the status phrase. Note that the version comes first in a response and last in a request; that reversal is worth memorising.
  3. A blank line. An empty line — carriage return and line feed with nothing between them, so the byte sequence \r\n\r\n at the end of the last header. There is no header-length field; the blank line is the only marker.
  4. 4xx, a client error. It is a 4xx, which is the client-error class. The server understood the request and is reporting that what was asked for does not exist here — the fault lies with the request, not with the server.
  5. Host, because one server hosts many sites. The Host header. A single server with a single IP address commonly serves many different websites, and the path in the request line does not say which one is meant, so HTTP/1.1 makes Host mandatory.
  6. In the entity body; it would have been in the URL. With POST the data is in the entity body, after the blank line. With GET it would have been appended to the URL in the request line after a ?, where it is visible in the address bar and in server logs.
  7. Date now, Last-Modified past, Expires future. Date is when the response was generated, so it is now. Last-Modified is when the object last changed, so it points into the past. Expires is when the copy becomes stale, so it points into the future.
  8. Bytes of body, so the client knows when it is done. It counts the bytes of the entity body only, not the headers. The client needs it to know where this response ends — which matters especially on a persistent connection, where another response may follow immediately on the same TCP connection.
  9. No memory between requests. The server keeps no information about a client’s previous requests, so each request is interpreted entirely on its own contents. A designer wants that because storing state is complex: it must be kept somewhere, and if either end crashes the two sides can disagree about what the state is and have to reconcile.

Test-readiness checklist#

  • ☐  I can write out a complete HTTP request from memory, with all four parts in the right order.
  • ☐  I can name the three fields of a request line and the three of a status line, and not swap them.
  • ☐  I can point at the blank line in a capture and say what it separates.
  • ☐  I can name the five methods and say what each asks for.
  • ☐  I can place any status code by its first digit, and give 200, 301, 304, 400 and 404 exactly.
  • ☐  I can say which header carries the host name, and why HTTP/1.1 requires it.
  • ☐  I can tell Date, Last-Modified and Expires apart and say which way each points in time.
  • ☐  I can explain statelessness and give one reason it was chosen.
One last rule

On any question about a captured message, say which message the value came from and which field it was in. Right value, wrong message is the most common way to lose marks on packet-capture questions, and it costs nothing to prevent.

Frequently asked questions#

What are the four parts of an HTTP request message?

The request line, then zero or more header lines, then a blank line, then the entity body. The request line has three fields: method, URL and HTTP version. The blank line is what marks the end of the headers.

What is the difference between the request line and the status line?

The request line is the first line of a client message and reads method, URL, version. The status line is the first line of a server message and reads version, status code, status phrase. The version is last in one and first in the other, which is where the confusion usually starts.

Where does the browser put the host name in an HTTP request?

In the Host header, not in the request line. The request line carries only the path part of the URL. HTTP/1.1 requires the Host header because one server with one IP address commonly hosts many different websites.

What does a 304 Not Modified response mean?

It means the copy the client or cache already holds is still current, so the server has sent headers only and no body. It is the answer to a conditional request, and it saves transmitting an object that has not changed.

Which header gives the expiration date of an HTTP response?

The Expires header, which carries a date and time after which the copy should be treated as stale. Many modern servers use Cache-Control with a max-age in seconds instead, which expresses the same thing as a duration rather than a timestamp, so a capture may show one, the other, or both.

Suggest a change

Something here not clear? A topic you wish we covered? Tell us. We read every message, and a request is the fastest way to get a guide written.

Test yourself in the free Kestrel Exams app

Topic-selectable practice — offline, no ads, no account. A networking question bank is not built yet; every other subject is open.

Choose your subject →