Headers to prevent 304/If-modified-since/HEAD requests

You can't really control what headers user agents decide to send to you. If the file in question is in the browser's cache and it decides it need to check for a new version then it will. According to this article, these are the situations browsers will request using If-Modified-Since:

  • The cached entry has no expiration date and the content is being accessed for the first time in a browser session
  • The cached entry has an expiration date but it has expired
  • The user has requested a page update by clicking the Refresh button or pressing F5

So if you are reloading the page to test your caching, it won't work since the browser will re-request the images. Try clicking a link then another link back to the first page. If your users are regularly reloading pages then you may need to rethink your site/app structure to prevent that.

One thing that may help is adding "public" to the cache control header, i.e. Cache-Control: public, max-age=31536000. I also learned recently that an expiry date of more than one year is invalid. Since your expiry date is exactly one year, perhaps lowering that by a few days or weeks would ensure the file stays in browser caches and is not discarded.


What you want is the immutable keyword in your Cache-Control line. Example for php:

header('Cache-Control: public, max-age=80000, immutable');

Source: https://code.facebook.com/posts/557147474482256/this-browser-tweak-saved-60-of-requests-to-facebook/


I had the same issue, and the Requests are definitely hitting the server for it to respond with the 304 status - I'm sending the 304 via some C# and for sure it hits the server..

I only had Cache-Control: private set. No max-age and no Expires It operated as expected; hit the server with the If-Modified-Since where I test the value compared to what I expect and deliver 304 w/empty response body - else 200 & full the response body.

Setting Expires header had the desired results, 200 - (from cache) on client & no HTTP requests hit the server.

But.. I found that setting BOTH max-age= & Expires can cause browsers to not send If-Modified-Since header AND not to cache at all if the values don't match.

Something to be aware of if you have caching issues & used the different headers in combination.