HTTP headers control how browsers, servers, caches, and APIs handle a request or response. This practical HTTP headers reference explains the headers most often involved in caching, security, content types, CORS, redirects, cookies, and compression, then provides a repeatable workflow for debugging them in browser DevTools and from the command line.
Overview
A header problem is often a configuration problem rather than an application-code problem. The response may contain the right body, but an incorrect or missing header can make a browser serve an old asset, block a script, download a page as a file, reject a cross-origin request, or send a cookie without the protection you expected.
Start by separating request headers from response headers. Request headers describe what the client is asking for, such as an accepted media type or an authorization token. Response headers describe how the server handled that request and how the client should process the result. Most production debugging begins with the response headers shown in the browser's Network panel.
Use this compact reference as a starting point:
| Header or group | Primary purpose | What to inspect |
|---|---|---|
Cache-Control | Controls caching and revalidation | Directives such as no-store, no-cache, max-age, and public |
Content-Type | Identifies the response media type | Correct MIME type and, where relevant, character encoding |
Content-Security-Policy | Restricts which resources a page may load or execute | Directive sources, report-only testing, and blocked-resource messages |
Strict-Transport-Security | Instructs browsers to use HTTPS for a host | Scope, duration, and whether the policy is appropriate for the deployment |
Access-Control-Allow-Origin and related CORS headers | Controls browser access across origins | Allowed origin, methods, headers, credentials, and preflight responses |
Location | Provides the destination for a redirect | Target URL, redirect status, and redirect chain |
Set-Cookie | Asks the browser to store a cookie | Secure, HttpOnly, SameSite, scope, and expiration |
Content-Encoding | Describes response compression | Whether the encoding matches what the client can decode |
Headers are not independent. For example, a long-lived cache policy works well for a versioned JavaScript filename, but it can preserve an old unversioned file. A strict content policy may be useful, but it can also expose an incomplete list of script, font, image, or API sources. Always evaluate a header in the context of the resource and its deployment path.
Checklist by scenario
Stale CSS, JavaScript, or image assets
- Open the resource in DevTools and inspect the response
Cache-Control,ETag, andLast-Modifiedvalues when present. - Check the requested URL, including its query string and filename. A changed build may still use the same URL.
- Confirm that the server, CDN, reverse proxy, and browser are not applying conflicting cache behavior.
- For immutable, versioned assets, use a cache policy intended for long reuse. For HTML or frequently changing responses, choose a policy that allows timely revalidation.
- After changing configuration, test a fresh request and a repeat request. A configuration change does not necessarily remove an already stored response from every cache.
Blocked scripts, styles, fonts, or frames
- Read the browser console message first; it commonly identifies the CSP directive that blocked the resource.
- Inspect
Content-Security-Policyfor directives such asscript-src,style-src,img-src,font-src,connect-src, andframe-ancestors. - Check whether the resource is inline, loaded from another origin, or dependent on a connection such as fetch, WebSocket, or an API request.
- Use a report-only policy while reviewing intended changes when your testing process supports it. Do not weaken a policy broadly just to silence one console message.
Incorrect downloads or garbled responses
- Verify
Content-Type. An HTML document, JSON response, image, stylesheet, and JavaScript module should be labeled according to what the endpoint actually returns. - Check
Content-Dispositionwhen a response should download rather than render, or should render rather than download. - Inspect
Content-Encodingand ensure an intermediary has not compressed an already encoded or incompatible response incorrectly. - Confirm that an error page is not being returned with a success status and an unexpected content type.
CORS errors and failed API calls
- Compare the request's
Originvalue withAccess-Control-Allow-Origin. The allowed value must match the intended origin rather than merely allowing an unrelated site. - For non-simple requests, inspect the preflight
OPTIONSresponse. CheckAccess-Control-Allow-MethodsandAccess-Control-Allow-Headers. - If cookies or other credentials are required, review
Access-Control-Allow-Credentialsand the cookie'sSameSitebehavior together. - Remember that CORS is enforced by browsers. A command-line request may receive a response even when browser JavaScript cannot read it.
Insecure or missing cookies
- Inspect every relevant
Set-Cookieresponse, not only the login response. - Use
Securefor cookies that should travel only over HTTPS andHttpOnlyfor cookies that should not be available to client-side scripts. - Set
SameSitedeliberately based on the application's navigation and cross-site request needs. - Review
Domain,Path, expiration, and deletion behavior. A cookie that cannot be removed because its scope differs from the original can cause confusing session issues.
Unexpected redirects or HTTPS behavior
- Record the complete redirect chain and the status code at each step. Check every
Locationvalue for the intended host, scheme, path, and query string. - Check for redirect loops caused by disagreement between a proxy and the application about whether the original request used HTTPS.
- Review
Strict-Transport-Securityonly after HTTPS is correctly deployed for the intended host scope. A browser can continue enforcing a policy after the response that introduced it is no longer visible.
How to debug HTTP headers
Use two views: the browser's actual request and a reproducible command-line request. In browser DevTools, open Network, reload the page, select the failing request, and review Headers. Compare the request URL, status, request headers, response headers, timing, redirect chain, and any console warning. Disable the browser cache only as a diagnostic step; it can hide the behavior real users experience.
From a terminal, begin with a header-only request:
curl -I https://example.com/assets/app.css
For redirects, follow the chain while retaining header output:
curl -I -L https://example.com/old-path
To test a particular request context, add the relevant request headers explicitly:
curl -i \
-H 'Origin: https://app.example.com' \
-H 'Accept: application/json' \
https://api.example.com/data
Compare results from the origin, hosting platform, CDN, and public URL when possible. Differences often reveal a proxy rule, environment-specific configuration, or a cached intermediary response. Avoid placing real access tokens, session cookies, or private user data in shared debugging tools or public issue reports.
What to double-check
- Response status: A correct header on a failed response does not make the request successful. Check the status before interpreting the body.
- Header duplication: Multiple layers can add the same header. Determine whether the browser receives one effective value or conflicting values.
- Environment differences: Compare local, preview, and production configuration. Framework defaults may differ from hosting or proxy defaults.
- Origin boundaries: Write down the page origin, API origin, asset origin, and redirect destination. Small differences in scheme, host, or port can change browser behavior.
- Policy scope: A header applied globally may affect APIs, error pages, static files, and administrative routes differently. Apply rules at the narrowest useful scope.
- Standards and browser behavior: Recheck the relevant specification, framework documentation, and browser documentation when changing a security policy or relying on a newer directive.
Common mistakes
A frequent caching mistake is using a blanket no-store policy everywhere. It can solve one sensitive-response problem while preventing useful caching for static resources. Another is setting a long lifetime for an HTML entry point whose asset references change on every release.
Security headers also require precision. A permissive content policy, an overly broad CORS rule, or a cookie without a deliberate scope may appear to fix an immediate error while expanding the application's exposure. Test changes against real browser flows, including login, logout, uploads, embedded content, API calls, and error handling.
Finally, do not diagnose only from server configuration. A CDN, load balancer, service worker, framework middleware, or browser cache may alter the result. The header received by the browser is the most useful evidence.
When to revisit
Keep this checklist with your release and incident workflow. Revisit header behavior before a production migration, domain or DNS change, CDN adoption, authentication redesign, major frontend release, or security review. It is also worth repeating when a hosting platform, reverse proxy, framework, or browser support baseline changes.
For a practical review, choose one representative page, one static asset, one API request, one redirect, and one authenticated flow. Capture their request and response headers in preview and production, then record any intentional differences. Turn confirmed fixes into automated checks where possible: verify content types, redirect destinations, cache directives, required security headers, and CORS behavior in deployment tests.
When the next header problem appears, avoid changing several policies at once. Reproduce the request, identify the layer that supplied the unexpected value, make the smallest safe change, and test both the failing scenario and the neighboring scenarios that the header can affect.