Last week, we learned that cross-origin resource sharing (CORS) is a mechanism based on HTTP headers. But what exactly are HTTP headers?
HTTP headers
Here's the definition of HTTP headers from the MDN Web Docs:
HTTP headers let the client and the server pass additional information with an HTTP request or response. An HTTP header consists of its case-insensitive name followed by a colon (
:
), then by its value. Whitespace before the value is ignored.
Inspecting HTTP headers
You can inspect HTTP headers using the Network panel in your browser's developer tools, such as the Network Monitor in Firefox DevTools and the Network panel in Chrome DevTools. Once you've chosen a request from the network request list, you'll see the network request details pane. This is where you'll find the HTTP headers for the request.

Request headers
I just entered the URL for this very website into my browser's address bar. The following are some of the request headers which my browser sent to the server where my website is hosted.
{
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Host": "barker.codes",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0"
}
Accept
The Accept
header indicates what content types my browser will accept. My browser is saying that it prefers:
- HTML/XHTML documents and AVIF/WebP images
- XML documents
- Any other content type
Notice that the text/html
, application/xhtml+xml
, image/avif
, and image/webp
content types don't have a ;q=
suffix. This means these content types have the default quality value of 1.0
. Meanwhile, the application/xml
content type has a quality value of 0.9
and the */*
content type has a quality value of 0.8
.
Accept-Encoding
The Accept-Encoding
header indicates what content encoding my browser will accept. This is usually a compression algorithm. My browser is saying that it will accept the gzip
, deflate
, and br
compression formats. Because none of them specifies a quality value, they're all equally weighted at 1.0
.
Host
The Host
header indicates the host (and port number) of the server where the request is being sent. My browser is saying it has sent the request to the host barker.codes
. Because the port number isn't specified, it will use the default port of 443
for HTTPS and 80
for HTTP. For example, try to visit https://barker.codes:443 and it should still work!
Sec-Fetch-*
The Sec-Fetch-*
headers provide additional information about the request context. My browser is saying that I initiated the request myself by entering the URL into my browser's address bar. This is in contrast to a CORS request, for example, where the user doen't make the request directly. See Sec-Fetch-Dest
, Sec-Fetch-Mode
, Sec-Fetch-Site
, and Sec-Fetch-User
.
User-Agent
The User-Agent
header contains details about the user agent, such as the user's browser and operating system. My browser is saying that I'm using Firefox on macOS.
Response headers
The following are some of the response headers which the server where my website is hosted sent back to my browser.
{
"Cache-Control": "public, max-age=0, must-revalidate",
"Content-Encoding": "br",
"Content-Length": 2890,
"Content-Type": "text/html; charset=UTF-8",
"ETag": "\"3590a6cc982a55b4cd3e99df1378b6f4-ssl-df\"",
"Strict-Transport-Security": "max-age=31536000",
"Vary": "Accept-Encoding"
}
Cache-Control
The Cache-Control
header controls caching in browsers and in shared caches such as content delivery networks (CDNs). Using the public
directive, the max-age
directive and the must-revalidate
directive, the server is essentially saying that the response can't be cached.
Content-Encoding
The Content-Encoding
header lists the content encodings that have been applied to the response body. The server is saying that the response was encoded using the Brotli compression algorithm. Remember the Accept-Encoding
request header? My browser said it would accept the Brotli algorithm!
Content-Length
The Content-Length
header indicates the size of the response body in bytes. The server is saying that the size of the response body was 2890 bytes after it was compressed using the Brotli compression algorithm.
Content-Type
The Content-Type
header indicates the content type of the response body before compression. The server is saying that this is an HTML response with UTF-8 character encoding. Remember the Accept
request header? My browser said it would accept (and actually prefer) HTML!
ETag
The ETag
header is an identifier for a specific version of a resource. It lets caches be more efficient and save bandwidth, as a web server does not need to resend a full response if the content was not changed.
The value above is likely a hash of the content, a hash of the last modification timestamp, or just a revision number
(MDN).
Strict-Transport-Security
The Strict-Transport-Security
header means that the site should only be accessed using HTTPS and that HTTP requests should be converted to HTTPS requests. Using the max-age=31536000
directive, the server is saying that the browser should remember this for 31,536,000 seconds (~1 year).
Vary
The Vary
header lists the request headers that could have influenced the creation of the response. The server is saying that the response could change based on the value of the Accept-Encoding
header. This is because the server will try to use an encoding that the browser said it will accept. This is called content negotiation.
Summary
There are many more HTTP headers not covered in this article. I encourage you to read about them in the MDN Web Docs. What I'd like you to take away from this article is that HTTP headers aren't “magic invisible things”. They're just a handful of key-value pairs which are sent and received with each request and response.