What's Inside an HTTP Response?
Every time your browser loads a page or your JavaScript calls fetch(), a server sends back an HTTP response. You see the result — a rendered page, some JSON data, an error message — but the response itself contains more structure than most developers consciously think about. Understanding that structure gives you a clearer mental model when debugging in DevTools or handling responses in code.
An HTTP response has three parts: a status line, headers, and an optional body.
Key Takeaways
- Every HTTP response consists of three parts: a status line (or
:statuspseudo-header in HTTP/2 and HTTP/3), headers, and an optional body. - Status codes are grouped by their first digit — 2xx for success, 3xx for redirection, 4xx for client errors, and 5xx for server errors.
- Response headers control caching, security, cookies, and content interpretation — they tell the browser how to handle the payload, not just what it is.
- Not all response headers are accessible to frontend JavaScript in cross-origin requests. Servers must use
Access-Control-Expose-Headersto allow access beyond the default safe set.
The Anatomy of an HTTP Response: Status, Headers, Body
The Status Line
In HTTP/1.1, the response starts with a single status line:
HTTP/1.1 200 OK
This line contains the protocol version, a three-digit status code, and a human-readable reason phrase. The reason phrase is informational only — the status code is what browsers and clients actually act on.
HTTP status codes are grouped by their first digit:
| Range | Meaning |
|---|---|
| 1xx | Informational (request received, processing continues) |
| 2xx | Success (200 OK, 201 Created, 204 No Content) |
| 3xx | Redirection (301 Moved Permanently, 304 Not Modified) |
| 4xx | Client error (400 Bad Request, 401 Unauthorized, 404 Not Found) |
| 5xx | Server error (500 Internal Server Error, 503 Service Unavailable) |
A note on HTTP/2 and HTTP/3: The textual status line above is specific to the HTTP/1.1 wire format. In HTTP/2 and HTTP/3, there is no status line. Instead, the status is conveyed via a :status pseudo-header (e.g., :status: 200). The semantics are identical — the status code means the same thing — but the representation differs. DevTools normalizes the representation, so you’ll still see the familiar status code regardless of protocol version.
HTTP Response Headers: What They Actually Do
Response headers are metadata. They tell the browser how to handle the response, not what the content is. Each header is a case-insensitive name followed by a colon and a value.
Here are the categories you’ll encounter most often:
Content metadata
Content-Type: application/json; charset=utf-8— tells the browser what format the body is in and how to decode it.Content-Length: 1024— the size of the body in bytes.
Caching
Cache-Control: max-age=3600, public— instructs the browser and CDNs how long to cache the response.ETag: "abc123"— a fingerprint of the resource, used for conditional requests. If the resource hasn’t changed, the server returns304 Not Modifiedinstead of the full body.
Security
Content-Security-Policy— restricts which sources the browser can load scripts, styles, and other resources from.Strict-Transport-Security— tells the browser to only connect over HTTPS for a specified duration.
Cookies
Set-Cookie: session=xyz; HttpOnly; Secure— instructs the browser to store a cookie. A single response can include multipleSet-Cookieheaders, one per cookie.
One important constraint: not all response headers are accessible to frontend JavaScript. By default, the Fetch API only exposes a small set of “safe” headers from cross-origin responses. Servers must explicitly list additional headers in Access-Control-Expose-Headers for your JavaScript to read them.
The Response Body
The body is the actual payload — HTML, JSON, an image, a file. Not every response has one. A 204 No Content or 304 Not Modified response intentionally omits the body. In these cases, the status code itself is the message.
The Content-Type header tells the browser how to interpret whatever arrives in the body.
Discover how at OpenReplay.com.
Less Common Features Worth Knowing
HTTP responses can also include informational responses like 103 Early Hints, which lets servers suggest resources to preload before the main response arrives. Trailers — headers sent after the body — exist in HTTP/1.1 (with chunked transfer encoding) and in HTTP/2 and HTTP/3 as trailing headers, but are rarely encountered in everyday frontend work. These are worth knowing about, but you won’t see them often in DevTools.
Conclusion
Think of an HTTP response as an envelope. The status code tells you whether the delivery succeeded. The headers are instructions on the outside — handle with care, refrigerate after opening, expires in 24 hours. The body is what’s inside. When something breaks, check the status code first, then the headers — they usually tell you exactly what went wrong and what to do next.
FAQs
Content-Length specifies the exact size of the response body in bytes. Transfer-Encoding, typically set to chunked, means the body is sent in pieces without a predetermined total size. In HTTP/1.1 a response uses one or the other. Chunked encoding is common for dynamically generated content where the server does not know the final size upfront.
For cross-origin requests, the Fetch API only exposes a limited set of CORS-safelisted response headers by default. These include Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, and Pragma. To access any other header from JavaScript, the server must include it in the Access-Control-Expose-Headers response header.
Use 204 No Content when the server successfully processes a request but has no body to return. This is common for DELETE operations or form submissions where the client does not need updated data in response. A 200 OK is more appropriate when you want to send a confirmation payload or updated resource back to the client.
Open DevTools with F12 or Ctrl+Shift+I, go to the Network tab, and click any request in the list. The Headers panel shows both request and response headers. You can also filter by request type and search for specific header names. The Response tab shows the raw body content returned by the server.
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.