What is the difference between HTTP status code 200 (cache) vs status code 304?
Asked Answered
A

5

230

I'm using the Google "Page Speed" plug-in for Firefox to access my web site.

Some of the components on my page is indicated as HTTP status:

200 200 (cache) 304

By Google's "Page Speed".

What I'm confused about is the difference between 200 (cache) and 304.

I've refreshed the page multiple times (but have not cleared my cache) and it always seems that my favicon.ico and a few images are status=200 (cache) while some other images are http status 304.

I don't understand why the difference.

UPDATE:

Using Google "Page Speed", I receive a "200 (cache)" for http://example.com/favicon.ico as well as http://cdn.example.com/js/ga.js

But, I receive a http status "304" for http://cdn.example.com/js/combined.min.js

I don't understand why I have two JavaScript files located in the same directory /js/, one returning a http status 304 and the other returning a 200 (cache) status code.

Acis answered 3/11, 2009 at 3:34 Comment(0)
B
240

The items with code "200 (cache)" were fulfilled directly from your browser cache, meaning that the original requests for the items were returned with headers indicating that the browser could cache them (e.g. future-dated Expires or Cache-Control: max-age headers), and that at the time you triggered the new request, those cached objects were still stored in local cache and had not yet expired.

304s, on the other hand, are the response of the server after the browser has checked if a file was modified since the last version it had cached (the answer being "no").

For most optimal web performance, you're best off setting a far-future Expires: or Cache-Control: max-age header for all assets, and then when an asset needs to be changed, changing the actual filename of the asset or appending a version string to requests for that asset. This eliminates the need for any request to be made unless the asset has definitely changed from the version in cache (no need for that 304 response). Google has more details on correct use of long-term caching.

Brandi answered 3/11, 2009 at 3:41 Comment(11)
So what's better to have from a speed perspective ... "200 (cache)" or "304" http status messages?Acis
200 cache. Some good notes about this here: developer.yahoo.com/performance/rules.html#expires . You want as long an expiration time as possible on your assets, but have to balance this with the fact that you lose a certain amount of control this way. One thing you can do is set long-lasting expirations on files, and then when needed increment an asset version number for those files. For example you can include style.css?v1 and increment in the <link> element to style.css?v2 when there are changes.Brandi
I've updated my original post to show my live site and the JavaScript in question. Please see my updated original post.Acis
Exactly. Firebug is reporting that it pulled a 200 OK response from the local cache. In other words, Firebug actually did a request/response cycle half an hour ago, and has cached the result: the result was a 200 OK, and the result still is a 200 OK, only now the result is coming from the cache rather than from the server.Challis
Justice, so why is Firebug report that for the ga.js is pulled from the local cache (status = 200 cache) while the combined.min.js is reporting a 304 http status. What's strange is that both files are of the same file type (JavaScript) and reside in the same server directory. You would think both would be either 200 or 304, and not differentAcis
here are the different firefox refresh methods www-jo.se/f.pfleger/firefox-reloadWilkes
Interestingly, Firebug ALWAYS shows requests that result in 304 (Not Modified) take 1 ms. But "200 OK (Cached)" requests always take 10-25 ms. There is no way the server request (304) could be faster than the cache fetch, which doesn't even ping the server. It must be a Firebug bug.Plantation
The max-age and age headers combined can also result in 200 (cache) results if age is less than max-age. The one exception is when the user clicks the browser refresh button, in which case a 304 header is sent.Slovak
HTML5 Boilerplate recommends against using the query string method of cache-busting - it's better to change the href, url, and src references to each file to include a 'fingerprint' (either a hash of the file or a simple incremented number), and then tell the server to strip off that fingerprint and just serve style.css or whatever. If you can't do that on the server, have your build system rename the actual files with the fingerprint.Sexennial
@Acis - I know this is years after the fact, but nobody else has answered your last question: why would two files, served from the same folder, result in different outcomes when refreshing? I think the answer is that it depends on how you are loading those resources. I'm pretty sure (if anyone can confirm, that would be great) that the second JS file is being loaded from a different "scope". That is, the refresh only triggers a conditional reload on files DIRECTLY on the initial page. If you're downloading files via other mechanism (e.g. iframe) the conditional refresh won't be triggered.Rasla
@Slovak confused. Do you mean if user clicks on refresh then it triggers/enforces a revalidation—leading to 304? OK. Then doing what leads to a 200? What other way is there that can trigger a request that doesn't require revalidation?Mellisa
S
72

200 (cache) means Firefox is simply using the locally cached version. This is the fastest because no request to the Web server is made.

304 means Firefox is sending a "If-Modified-Since" conditional request to the Web server. If the file has not been updated since the date sent by the browser, the Web server returns a 304 response which essentially tells Firefox to use its cached version. It is not as fast as 200 (cache) because the request is still sent to the Web server, but the server doesn't have to send the contents of the file.

To your last question, I don't know why the two JavaScript files in the same directory are returning different results.

Saturable answered 3/8, 2010 at 21:28 Comment(0)
B
19

This threw me for a long time too. The first thing I'd verify is that you're not reloading the page by clicking the refresh button, that will always issue a conditional request for resources and will return 304s for many of the page elements. Instead go up to the url bar select the page and hit enter as if you had just typed in the same URL again, that will give you a better indicator of what's being cached properly. This article does a great job explaining the difference between conditional and unconditional requests and how the refresh button affects them: http://blogs.msdn.com/b/ieinternals/archive/2010/07/08/technical-information-about-conditional-http-requests-and-the-refresh-button.aspx

Beef answered 30/8, 2013 at 21:22 Comment(2)
I can't even describe how much time I spent trying to figure out 304 status of requests to CDN. Although you answer a bit different question, you deserve a bounty :-)Isochronous
You are right: the difference in the codes is related to the fact that you are reloading or not the same page. If I reload a page, I see in the browser's network monitor a 304 code. But, if I access another URL, which uses these same files, I see in the browser's network monitor a 200 (from cache) code.In my case, the other URL was just a query string appended to the original URL (the page was essentially the same).Brookweed
E
9

HTTP 304 is "not modified". Your web server is basically telling the browser "this file hasn't changed since the last time you requested it." Whereas an HTTP 200 is telling the browser "here is a successful response" - which should be returned when it's either the first time your browser is accessing the file or the first time a modified copy is being accessed.

For more info on status codes check out http://en.wikipedia.org/wiki/List_of_HTTP_status_codes.

Erythromycin answered 3/11, 2009 at 3:41 Comment(5)
That's my understanding as well ... which is why I stated in my original post that I've refreshed my page multiple times and am still getting the "200 (cache)" for the same favicon.ico and particular JavaScript includes I have. Very strangeAcis
200 actually doesn't mean cached, it just means OK. Chances are that your server configuration doesn't explicitly tell the browser to cache your ico and js files, which would make it return a status code of 200.Erythromycin
That's not the case b/c on some of my JavaScript, I receive a 304 and other JavaScript I get a "200 (cache)". All JavaScript resides within the same web server directory example.com/js/Acis
I should add that 200 (cache) just means it's locally cached and not actually making a request to the server, which is going to be faster than going to the server and getting a 304 response.Erythromycin
I've updated my original post to show my live site and the JavaScript in question. Please see my updated original post.Acis
T
3

For your last question, why ? I'll try to explain with what I know

A brief explanation of those three status codes in layman's terms.

  • 200 - success (browser requests and get file from server)

If caching is enabled in the server

  • 200 (from memory cache) - file found in browser, so browser is not going request from server
  • 304 - browser request a file but it is rejected by server (ie, if the content is not modified since the last time it's requested)

For some files browser is deciding to request from server and for some it's deciding to read from stored (cached) files. Why is this ? Every files has an expiry date, so

If a file is not expired then the browser will use from cache (200 cache).

If file is expired, browser requests server for a file. Server check file in both places (browser and server). If same file found, server refuses the request. As per protocol browser uses existing file.

look at this nginx configuration

location / {
    add_header Cache-Control must-revalidate;
    expires     60;
    etag on;

    ...
}

Here the expiry is set to 60 seconds, so all static files are cached for 60 seconds. So if u request a file again within 60 seconds browser will read from memory (200 memory). If u request after 60 seconds browser will request server (304).

I assumed that the file is not changed after 60 seconds, in that case you would get 200 (ie, updated file will be fetched from server).

So, if the servers are configured with different expiring and caching headers (policies), the status may differ.

In your case you are using cdn, the main purpose of cdn is high availability and fast delivery. Therefore they use multiple servers. Even though it seems like files are in same directory, cdn might use multiple servers to provide u content, if those servers have different configurations. Then these status can change. Hope it helps.

Added on 20/04/2023

For 304 to work we have to add If-Modified-Since header to the http request, if not server cannot check whether the content is modified or not.

Toweling answered 20/3, 2018 at 12:45 Comment(1)
The 304 - Not Modified isn't a "rejection" by the server. It is the server declaring to the client "for the version you are asking for, I know it is not modified, you don't really need the file". Technically, 304 is one of the "redirection" response codes. Its telling the client "get it from your own cache".Diffusive

© 2022 - 2024 — McMap. All rights reserved.