HTTP Headers to Build 10X APIs š„
#83: Break Into HTTP Headers (15 Minutes)
Get my system design playbook for FREE on newsletter signup:
This post outlines the must-know HTTP headers.
Share this post & I'll send you some rewards for the referrals.
I created the block diagrams in this newsletter with Eraser.
Once upon a time, there lived a junior software engineer.
He worked for a tech company named Hooli.
Although extremely bright, he never got promoted.
So he was sad and frustrated.
Until one day, when he had the idea to apply for a job at a unicorn startup.
And worked hard on solving LeetCode.
But the interviewer asked him just about HTTP headers.
And he failed to answer, so the interview was over in 7 minutes.
So he studied web docs later to fill the knowledge gap.
Onward.
āBuilding a scalable authorization system: A step-by-step blueprintā Ebook by Cerbos - Sponsor
Authorization can make or break your applicationās security and scalability. From managing dynamic permissions to implementing fine-grained access controls, the challenges grow as your requirements and users scale.
This eBook will guide you through the 6 key requirements all authorization layers should include to avoid technical debt:
Architectural and design considerations for building a scalable and secure authorization layer.
20+ technologies, approaches, and standards to consider for your permission management systems.
Practical insights, based on 500+ interviews with engineers, architects, and IAM professionals.
Learn how to create an authorization solution that evolves with your business needs, while avoiding technical debt.
An HTTP request-response has 2 parts:
Header: tiny pieces of metadata
Body: actual content
A request means the client asks for something. While a response means the server sends back something.
An HTTP header consists of a name and a value. Although headers are invisible to the users, theyāre important in transferring information. Yet extra headers could consume bandwidth and affect performance. So itās necessary to use them correctly.
And the server sends a status code with each response. It tells the client whether its request succeeded, failed, or needs extra action.
HTTP Headers
He failed the interview, so you donāt have to.
Hereās a summary of what he learned:
1. General Headers
Both requests and responses include these headers.
Cache-Control
It controls the caching behavior of browsers and intermediary caches. For example, caching in proxy servers and CDN. Put simply, it helps to determine if the browser should serve data from its cache when the user revisits a site.
Here are some of its directives:
Cache-Control: max-age=3600, publicIt means cache the response in each infrastructure layer for 3600 seconds.
Cache-Control: no-storeIt means donāt cache the response anywhere.
Cache-Control: no-cacheIt means cache the response. But the browser must re-validate with the server before using it.
An incorrect configuration of this header might display stale data to the user. Also thereās a risk of storing private data. Besides forgetting to cache static resources, such as images or scripts, affects the performance badly.
Date
It indicates when the server sent the response. Itās used to calculate cache freshness and also debug clock issues.
Hereās an example:
Date: Sun, 22 Aug 2025 14:00:00 GMTIt means the server sent the response on 22 August 2025 at 14:00 GMT.
An incorrect configuration of this header will make the cache freshness calculation wrong. Also it'd make debugging harder.
Via
Itās added by proxy servers automatically. And helps to track and debug network routing paths. Put simply, it shows the intermediary servers such as proxies, load balancers, and CDN.
Hereās an example:
Via: 1.1 proxy1.example.com, 1.1 proxy2.example.comIt means the message passed through
proxy1andproxy2using HTTP/1.1.
So thereās no impact on users if this header is missing. But its absence can make debugging difficult when there are many proxies.
Letās keep going!
2. Request Headers
The client sends these headers to the server to give information about the client or the request.
Host
It contains the hostname and port number of the server receiving the request.
Yet it defaults to port 443 for HTTPS if the client specifies nothing. Itās helpful when the server handles different sites via virtual hosting on the same IP address.
Hereās an example:
Host: blog.example.comIt means the request is for the blog subdomain (virtual host) on the server.
The server might return the default site or a 400 error status code if this header is missing. Put simply, an incorrect header will prevent the request from reaching the correct site.
User-Agent
It informs the server about the clientās browser and operating system. Itās useful for analytics, compatibility workarounds, and content optimization (mobile vs desktop).
Hereās an example:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/114.0.0.0 Safari/537.36It means the request came from Google Chrome 114 on a 64-bit Windows 10 machine.
Some older browsers might receive incompatible content if this header is missing. Also a wrong header might serve incorrect data to the mobile client. Thus affecting performance badly.
Accept
It informs the server of the content format expected in the response. For example, JSON or HTML.
Hereās an example:
Accept: application/jsonIt means the client prefers a JSON response.
The server responds with its default format if this header is missing. And the client might fail to process the response. Besides the server responds with a 406 Not Acceptable error code if it doesnāt support the requested format.
Accept-Language
It informs the server of the human language expected in the response. Put simply, it tells the browserās language preference. For example, English or German.
Hereās an example:
Accept-Language: en-US, de;q=0.9It means the client prefers content in US English. And prefers German only if itās unavailable.
The server falls back to its default language if this header is missing or wrongly set. Thus affecting user experience.
Accept-Encoding
It informs the server of the compression algorithm expected in the response. For example, gzip or deflate. It helps to reduce the response size by compressing it, thus saving bandwidth.
Hereās an example:
Accept-Encoding: gzip, deflate, brIt means the client can handle responses compressed with gzip, deflate, or brotli (br).
The server sends an uncompressed response if this header is missing. Thus affecting performance badly. Also an incorrect header might create a response in the wrong compression format. And the client might fail to decode it.
Cookie
It lets the client send its cookies to the server. Think of a cookie as a piece of data stored on the browser. It helps to remember things like logins, preferences, or sessions.
Hereās an example:
Cookie: session_id=abc567; theme=darkIt means the client is sending its stored data, such as session ID and theme preference, to the server.
The server might start a new session if this header is missing. Thus affecting the user experience badly.
Referer
It contains the site URL that sent the client to the current page. Put simply, it shows where the request came from. And itās commonly used in analytics.
Hereās an example:
Referer: https://example.com/page1It means the request came from page1 on example.com
The site traffic analytics might become inaccurate if this header is missing.
Authorization
It lets the client send authentication credentials, such as tokens or API keys. Imagine authentication credentials as a password or token to prove who the client is. So the server can allow it to access specific resources.
Hereās an example:
Authorization: Bearer eyJhbKciOiJmIt means the client is using a Bearer token as proof of identity to access the server. Think of the Bearer token as a temporary digital key for access.
The server responds with a 401 Unauthorized error code if this header is missing or invalid. While server responds with a 403 Forbidden error code if the client has insufficient permission.
Range
It lets the client download specific byte ranges of a file. Itās useful for streaming media or resuming broken downloads.
Hereās an example:
Range: bytes=0-499It means the client is telling the server to send only the first 500 bytes of a file.
The server sends the entire file on each request if this header is missing. Thus wasting bandwidth.
If-Modified-Since
It tells the server to send the resource only if an update occurred on it after a specific period. Put simply, it lets the client make conditional GET requests.
Hereās an example:
If-Modified-Since: Tue, 11 Jun 2024 10:00:00 GMTIt means the client is asking the server to send the resource only if it has changed since 11 June 2024, 10 hours GMT.
The server sends a fresh copy every time if this header is missing. Thus wasting bandwidth. While the server responds with 304 Not Modified without a body if the resource hasnāt changed.
If-None-Match
It tells the server to send the resource only if the clientās ETag doesnāt match the serverās current ETag. Think of ETag as a unique resource version identifier for a resource. Put simply, it lets the client make conditional GET requests, but much more precisely.
Hereās an example:
If-None-Match: "abc123"It means the client is asking the server to send the resource only if its current ETag differs from
āabc123ā.
The server sends a fresh copy every time if this header is missing. Thus wasting bandwidth and affecting performance.
X-Forwarded-For
The client doesn't add this header, but the proxy does.
It lets the server know the client's IP address even if the request passed through proxies or load balancers. Itās useful for analytics, logging, and rate limiting.
Hereās an example:
X-Forwarded-For: 203.0.113.21It means the request originally came from the client with IP address 203.0.113.21
While the server only sees the proxy or load balancerās IP address if the header is missing. Thus making rate limiting difficult and analytics less accurate.
X-Forwarded-Proto
The proxy or load balancer adds this header.
It tells the server the original protocol the client used before the request passed through proxies or load balancers. For example, HTTP or HTTPS.
It helps the server to generate correct absolute URLs that match the clientās protocol.
Hereās an example:
X-Forwarded-Proto: httpsIt means the original client used HTTPS.
The server might return insecure HTTP links to the client if this header is missing.
X-Forwarded-Port
The proxy or load balancer adds this header.
It tells the server the original port the client used before the request passed through proxies or load balancers. For example, port 80 for HTTP or 443 for HTTPS.
It helps the server generate correct absolute URLs for redirects.
Hereās an example:
X-Forwarded-Port: 443It means the original client used port 443 (default for HTTPS).
The server might return incorrect absolute links to the client if this header is missing.
Ready for the best part?
Subscribe to get simplified case studies delivered straight to your inbox:
3. Response Headers
The server sends these headers to give instructions to the client.
Location
Itās used by the server to redirect the client to a specific URL. For example, the server sends this header after a form submission to tell the browser where the new resource is.
Hereās an example:
Location: https://example.com/welcomeIt means the server is telling the client to redirect to example.com/welcome
The client might get redirected to a broken URL if this header is wrong. While the client will stay on the same URL if this header is missing.
Set-Cookie
It lets the server store cookies on the client. The client then includes it in future requests. Imagine a cookie as a small piece of data stored on the client. It allows session management, personalization, and tracking.
Hereās an example:
Set-Cookie: session_id=abc123; Path=/; HttpOnlyIt means the server is telling the browser to store a session cookie for the entire site and block JavaScript from accessing it.
Each request might get treated as a new session if this header is missing. Also there might be security risks or broken logins if this header is wrong.
Access-Control-Allow-Origin
Itās the main header for cross-origin requests (CORS).
It tells the browser which sites are allowed access to a resource on a specific site. While the browser blocks the response if it's missing.
Imagine an e-commerce store that uses an external payment service. The store tries to fetch the payment confirmation from the payment service.
Yet browsers have the same-origin policy. It means JavaScript can only read responses from the same site unless the other site allows it. So without CORS, the browser blocks the response. (Even if the request went through successfully.)
With CORS enabled, the payment service responds with this header:
Access-Control-Allow-Origin: ecommerce-store.comIt means allow storeās JavaScript to read the payment confirmation.
And the e-commerce store displays the payment confirmation data. This approach prevents random sites from accessing sensitive data.
Think of this header with a real-world analogy:
Access-Control-Allow-Origin header = guest list for a party
Browser = security guard
Payment service = party host
E-commerce store = guest who wants to visit the party
If the payment service doesnāt have the e-commerce store on the guest list, the browser wonāt let it in to see the data.
Age
This header is added by a cache, such as the CDN or proxy.
It tells how many seconds the response has been in the cache since it was fetched from the origin server. Thus helping the browser decide if the cache is still fresh or needs revalidation.
Hereās an example:
Age: 120It means the cached copy is 120 seconds old.
Each time the cache serves a response, it calculates the age and includes it in the header. The cache freshness is then determined by comparing this header value with the cache-control header.
While the client might show stale data to the user if this header is missing.
Vary
The server sends different responses for the same URL based on request headers. For example, user-agent, accept-encoding, or accept-language. So there are different cache versions for the same URL.
This header tells the cache which request headers affect the serverās response. Thus ensuring cache to serve the right version of a resource to different clients.
Hereās an example:
Vary: User-AgentIt means the server might send different responses for desktop and mobile users.
The cache might serve the wrong version of a site if this header is missing. Thus breaking pages or showing wrong language.
Accept-Ranges
It tells the client whether the server supports partial requests. Itās useful for downloading parts of a large media file and for streaming media.
Hereās an example:
Accept-Ranges: bytesIt means the server supports partial requests in bytes.
The client assumes the server doesnāt support partial requests if this header is missing. Thus downloading the file in full.
Content-Range
It indicates which part of a resource is being sent in response to a partial request. This lets the client assemble the resource correctly from different parts.
Hereās an example:
Content-Range: bytes 0-499/1234It means this response contains bytes 0 through 499 of a resource that is 1234 bytes in total.
The client won't know the part it received if this header is missing. Thus it might fail to assemble the resource correctly.
Content-Security-Policy
It tells the browser which sources are allowed for scripts, styles, and images. Thus preventing cross-site scripting (XSS) attacks. Think of XSS as a situation where a hacker injects malicious JavaScript into a site to steal data.
Hereās an example:
A hacker could inject malicious JavaScript into the site through a form or comment box. Without this header, the browser runs the script and lets the hacker steal user data.
But with this header, the browser loads resources only from trusted sources. Thus blocking malicious scripts.
Content-Security-Policy: default-src 'self'; script-src 'self'It means the site only allows content and scripts to load from its own domain.
The browser checks every resource against these rules and blocks anything not on the allowed list.
Strict-Transport-Security
It tells the browser to always use HTTPS for this domain for a specific period.
Hereās an example:
Strict-Transport-Security: max-age=31536000; includeSubDomainsIt means the browser uses HTTPS only for this site and its subdomains for the next 1 year.
First-time visitors to a site might get downgraded to insecure HTTP if this header is missing. Thus making them vulnerable to man-in-the-middle attacks.
So include this header with the maximum age for security.
4. Payload Headers
These headers describe the content body of a request or response.
Letās dive in!
Content-Type
It indicates the format of the message body, so the receiver knows how to process it.
Hereās an example:
Content-Type: application/jsonIt means that the body of the message is in JSON format.
The client might fail to interpret the content if this header is wrong or missing.
Content-Disposition
It tells the browser how to handle the response body. For example, whether to display it inline or download it as a file.
Content-Disposition: attachment; filename="report.pdf"It means the browser prompts the user to download the file.
The browser might just show the file inline if this header is missing. Thus affecting user experience.
Content-Length
It tells the receiver how big the body is. For example, when uploading or downloading a file.
Hereās an example:
Content-Length: 348It means the message body is 348 bytes long.
This helps the client show accurate progress bars for uploads or downloads.
The receiver might fail to understand where the body ends if this header is missing. Thus misinterpreting the message.
Content-Encoding
It tells the client which compression algorithm was applied to the response body. So the client can decode it correctly.
Hereās an example:
Content-Encoding: gzipIt means the body got compressed with gzip.
The client might fail to decode the content and show an error if this header is wrong.
Content-Language
It tells the client the human language of the response body. Itās useful in multilingual sites to interpret the content correctly.
Hereās an example:
Content-Language: en-USIt means the response is for US English users.
The client might try to guess the language if this header is missing. Thus causing accessibility or localization issues.
Last-Modified
It tells the client the date and time when the resource was last changed on the server. This helps to determine if the cached copy is still fresh.
Hereās an example:
Last-Modified: Tue, 11 Jun 2024 10:00:00 GMTIt means the resource was last changed on 11 June 2024 at 10:00 GMT.
The client wouldnāt be able to make conditional requests if this header is missing. Thus wasting bandwidth.
ETag
Entity Tag (ETag) is a response header. Think of it as a unique version identifier, like a hash or fingerprint, for a resource.




































