The HTTP 304 not modified status code indicates a communication problem between a user’s browser and a website’s server. If you or your users come across this status code on your site, it can block access to your content entirely.
Since it can be on the server-side or the client-side, figuring out the source of the problem can take a little work. Fortunately, there are several foolproof techniques for troubleshooting it.
In this post, we’ll discuss HTTP status codes and explain what the HTTP 304 status code is. Then we’ll walk you through six methods you (or your visitors) can use to fix it.
Let’s get started!
An Introduction to HTTP Status Codes
To understand HTTP 304, it helps to first understand status codes. Put simply, every time you make a request to your browser – such as by accessing a particular website – an HTTP status code is sent between your browser and the server in order to exchange information.
There are more than 40 different status codes that can be involved in that communication. However, there are only a handful you’ll likely come across directly. When you do encounter a status code, it usually means that something has gone wrong.
HTTP status codes fall into one of five categories, numbered between the 100s and 500s. Each series indicates a different type of problem. For example, error codes that fall into the 400s, such as the “404 Not Found” error and the ”401 error”, typically mean that there was an issue with the request and the website or page in question was unreachable.
On the other hand, codes in the 300s – such as the HTTP 304 status code we’ll focus on in this post – are redirection codes. They make it clear that the information being requested was either temporarily or permanently substituted with another resource.
When you encounter one of these status codes, it means that further action must be taken.
What is The HTTP 304 Status Code?
HTTP 304, also sometimes known as “304 Not Modified”, is a code that communicates to your browser that: “The requested resource has not been modified since the last time you accessed it.”
The Internet Engineering Task Force (IETF) defines the 304 Not Modified as:
The 304 (Not Modified) status code indicates that a conditional GET or HEAD request has been received and would have resulted in a 200 (OK) response if it were not for the fact that the condition evaluated to false. In other words, there is no need for the server to transfer a representation of the target resource because the request indicates that the client, which made the request conditional, already has a valid representation; the server is therefore redirecting the client to make use of that stored representation as if it were the payload of a 200 (OK) response.
Essentially, your (or your visitor’s) browser is being told by the server that the resources stored (cached) in the browser haven’t been modified since the latest time you visited that page.
In turn, your browser retrieves a saved version of the web page from the cache. The purpose of this is to improve page speed and delivery, by preventing your browser from having to repeatedly download the same information.
Check Out Our Video Guide to the 304 Not Modified Status Code and All 3xx Redirects
Understanding HTTP 304 Requests
When your browser stores a resource in the cache, it keeps what’s called the ‘Last-Modified header’ information that was sent from the server. If a browser receives a request for a web page it has a saved copy of, but it doesn’t know whether it has the latest version, it sends a ‘conditional validation’ request to the server.
The browser communicates to the server the ‘Last-Modified’ date and time for the copy of the resource it has, via the ‘If-Modified-Since’ or ‘If-None-Match’ header. The server inspects these headers and also looks at the ETag value. The latter is a unique identifier used to specify the version of a particular resource.
If the values for these files are the same, the server sends the HTTP 304 Not Modified response header and the browser uses the cached copy of the resource.
If the browser copy is outdated, meaning that the file has been modified since the last request, it sends an HTTP 200 code and a new copy is used.
Unfortunately, there are a few issues that might cause an HTTP 304 response when it’s not supposed to occur. The most common causes include:
- Server configuration or Domain Name Server (DNS) issues
- A cached resource that is infected or corrupted (i.e., malware or viruses affecting the browser)
The 304 status code can be due to a problem on either the server-side or the client-side, so it might take some troubleshooting in order to diagnose and resolve it.
The HTTP 304 status code can block access to all of your content which means understanding how to fix it is crucial 🚨 This guide has 6 methods to get things back up and running ASAP ✨Click to Tweet
How to Fix an HTTP 304 Status Code (6 Potential Methods)
The methods you can use to resolve an HTTP 304 status code vary from simple to fairly technical. Search engines are responsible for indexing and caching websites, so this issue can usually be traced back to the browser being used to access the site.
Of course, there’s only so much you can do to fix the browsers of people who are trying to access your site.
However, understanding what may be causing the issue for visitors can be helpful, either when trying to find a solution on your end or assisting them directly.
With that in mind, let’s take a look at six methods you can use to try and fix an HTTP 304 status code!
1. Clear the Browser’s Cache Data
First up, cleaning your browser data to clear the cache might help with accessing the desired URL. This includes deleting all of the browsing data, cookies, and cache information.
The instructions for executing this process will vary depending on the browser you’re using. If you’re unsure how to do it on your device, feel free to refer to our guide on clearing the cache for all major browsers.
2. Run a Malware Scan
Corrupted browsers that have been infected with a virus or malware may be another culprit. Therefore, it’s a good idea to run a malware scan on your system. Doing so can help identify and remove any issues that might be interrupting or interfering with the header request, including problematic extensions.
If you’re using the Windows version of Chrome, you can run the Malware Scanner and Cleanup Tool that comes built-in.
To do this, first make sure you’re running the latest version of Chrome by opening up a new tab and clicking on the menu icon, followed by About Chrome:
If your browser isn’t updated to the current version, you can resolve that in the same place. Then, open a new Chrome tab and enter “chrome://settings/cleanup” into the URL bar.
Hit Enter, and then next to Find and remove harmful software click on the Find button:
The scanner will begin running, then report back with the results.
Unfortunately, some other browsers such as Firefox and Edge, as well as the macOS and Linux OSs, do not come with their own versions of this built-in tool. Instead, you’ll have to run a malware scan using the antivirus software on your computer.
3. Disable Your Browser’s Extensions
Your browser’s extensions may also become infected and interfere with requests and server communication. That’s why you may also want to disable them. You can do this by opening Chrome’s menu and going to Settings > Extensions:
On the Extensions page, you can disable each one by clicking on the corresponding toggle switch.
You can also delete unused or outdated extensions via the Remove button:
Again, this process will vary slightly depending on your browser. The goal is to remove or disable each extension manually and then check to see if that resolves the HTTP 304 issue.
Then, you can try turning them back on one by one.
4. Flush the DNS and Reset the TCP/IP
If the problem hasn’t been resolved at this point, there could be an issue with the DNS settings. For example, using an outdated IP address might cause an HTTP 304 status code.
Therefore, another approach to try is flushing the DNS and resetting the TCP/IP.
With Chrome, you can flush the browser DNS by entering “chrome://net-internals/#dns” into a new tab.
Hit Enter, and then click on the Clear host cache button:
You can also flush the DNS and reset the TCP/IP in your OS. If you need detailed guidance, you can refer to our tutorial on How to Flush DNS Cache (Windows, Mac, Chrome).
5. Try Using the Google Public DNS
Another potential cause is an incorrect DNS address. Therefore, it’s worth using the Google Public DNS to see if that resolves the problem.
On Windows, you can do this by pressing the Win + R keys. In the Run window that appears, type “ncpa.cpl” into the command box, and then hit Ok.
In the Network Connections window that opens next, locate the network connection you’re using and right-click on it. Next, select Properties:
From there, double-click on Internet Protocol Version 4:
Select the option to “Use the following DNS server addresses”, then enter the value “8.8.8.8” under Preferred and “8.8.4.4” under Alternate:
When you’re done, click on Ok. Then restart your system, and try accessing the website again.
To change your DNS server settings using macOS, you would go to Apple > System Preferences > Network:
In the window that opens, select your connection, then click on Advanced followed by the DNS tab:
Click the + icon next to the IPv4 or IPv6 addresses, to replace the existing addresses with the Google Public IPs.
For further instructions or for guidance on using Google Public DNS on a Linux or another OS, check out Google’s own DNS guide.
6. Check Your Server Configuration Files for Incorrect Redirect Instructions
An HTTP 304 Not Modified status code can occur due to both server- and client-related problems. If none of the methods we’ve covered so far have corrected the issue, your server configuration files may be at fault. For example, it’s possible that there are incorrect redirect instructions present.
The process for checking your server configuration files depends on whether you’re using Nginx or Apache.
At Kinsta, we use the Nginx web server. So if you’re a Kinsta user, you won’t have access to the .htaccess file that Apache users do.
However, you can still perform similar functions. For example, after logging in to MyKinsta, you can check the Analytics > Response section of the dashboard for a breakdown of response codes and redirects:
You can also check the error logs. If you have a specific question or request about editing the configuration files, your best bet is to reach out to our support team.
If your server is running on Apache, then you’ll want to look for the .htaccess file in the root directory of your site. You can do this by logging into the File Manager for your hosting account, and navigating to the public_html folder.
Once you open that file, look for a mod_cache module section. It should look something like this:
LoadModule cache_module modules/mod_cache.so
<IfModule mod_cache.c>
LoadModule cache_disk_module modules/mod_cache_disk.so
<IfModule mod_cache_disk.c>
CacheRoot "c:/cacheroot"
CacheEnable disk "/"
CacheDirLevels 5
CacheDirLength 3
</IfModule>
# When acting as a proxy, don't cache the list of security updates
CacheDisable "http://security.update.server/update-list/"
</IfModule>
We don’t recommend deleting anything, as that can cause severe damage. Instead, you can try temporarily commenting out the cache section by adding a “#” symbol at the beginning of each line.
After you save your changes, check to see if this resolved the HTTP 304 status code.
Don’t let an HTTP 304 status code stand in the way of your site ❌ Find all the troubleshooting tricks you need in this in-depth guideClick to Tweet
Summary
300s redirection codes are used to improve page speed and performance. Unfortunately, when a server or browser isn’t properly configured, communication between the two can get interrupted and result in an HTTP 304 not modified status code. There are six methods you can use to fix it, specifically:
- Clearing your browser’s cache data.
- Running a malware scan.
- Disabling your browser extensions.
- Flushing the DNS and resetting the TCI/IP.
- Trying the Google Public DNS.
- Checking your server configuration files for incorrect redirect instructions.
HTTP response status code 304 Not Modified is returned by the server to indicate a successful HTTP request, yet there is no need to send the data associated with the relevant resource. Essentially, it is the same as a 200 OK status code with a specific header included. There is no message body for this response code.
Usage
The 304 Not Modified status code is sent by the server in a limited number of cases. It implies that the HTTP request is safe, such as a GET or HEAD HTTP request, and the server concludes that the resource has not been changed since it was last stored in the client’s cache. This is intended as a bandwidth-conserving function, as the server does not have to retransmit data that the client already has.
The server must generate one of the following HTTP headers in response to what was sent by the client:
- Cache-Control
- Content-Location
- Date
- ETag
- Expires
- Vary
Because the goal of the 304 Not Modified HTTP response is to minimize bandwidth, the server will not generate redundant or unused HTTP headers. Therefore, none of the above fields will be returned that were not included in the HTTP request, unless it is otherwise helpful for the cache-update process.
If the HTTP request was conditional, such as a conditional GET, and it included an appropriate directive, then the server may return 304 Not Modified status code. The relevant directives are If-None-Match and If-Modified-Since, and rely on a header such as ETag to evaluate the necessity to transmit the resource.
Example
In the example, the client requests a resource that is stored in the cache after it is received. The ETag transmitted by the server uniquely identifies the version sent by the server. Sometime later, a second HTTP request is made by the client to see if anything has changed. The client transmits the ETag that it had originally received, and the server recognizes that nothing has changed since the last transmission. Consequently, it returns the 304 Not Modified status code. Finally, the client makes a third HTTP request and by that time, a new version of the document is available. As such, a new copy is transmitted by the server with the newest ETag.
Note
Each time the server updates a resource, it generates a new ETag and maintains a history of the previous ones. This server-side version history, in conjunction with the client’s local cache, together are what make this bandwidth-conserving option possible. Alternatively, the server might return a Last-Modified date, and the client can use that instead of the ETag in If-Modified-Since, negating the need for the server to maintain a history of ETag values.
Initial request
GET /news.html HTTP/1.1
Host: www.example.re
Initial response
HTTP/1.1 200 OK
Etag: “1234 … 000"
Content-Type: text/html
Content-Length: 1250
<message body contains requested resource>
Second request
GET /news.html HTTP/1.1
Host: www.example.re
If-None-Match: “1234 … 000"
Second response
HTTP/1.1 304 Not Modified
Etag: “1234 … 000"
Third request
GET /news.html HTTP/1.1
Host: www.example.re
If-None-Match: “1234 … 000"
Third response
HTTP/1.1 200 OK
Etag: “1234 … 001"
Content-Type: text/html
Content-Length: 1600
<message body contains requested resource>
Code references
.NET
HttpStatusCode.NotModified
Rust
http::StatusCode::NOT_MODIFIED
Rails
:not_modified
Go
http.StatusNotModified
Symfony
Response::HTTP_NOT_MODIFIED
Python3.5+
http.HTTPStatus.NOT_MODIFIED
Java
java.net.HttpURLConnection.HTTP_NOT_MODIFIED
Apache HttpComponents Core
org.apache.hc.core5.http.HttpStatus.SC_NOT_MODIFIED
Angular
@angular/common/http/HttpStatusCode.NotModified
Takeaway
The 304 Not Modified status code indicates that the HTTP request was successful but because the client has the most recent version already cached locally, the server opts to conserve bandwidth and respond to say that there is no reason to retransmit the requested resource.
See also
- 200 OK
- If-Modified-Since
- If-None-Match
- RFC 7231
Last updated: August 2, 2023
The other night I was searching «Best Pasta Dish Recipes» on Google.
I clicked the first link and was stopped by the dreaded error code.
I’m willing to bet something similar has happened to you, at one point or another.
When that happens, it’s not just my brain experiencing technical difficulties.
These error codes are HTTP status codes. If you receive an error code, something went wrong when your browser requested the information from a web server. An HTTP status code is sent every time you go to a new web page. However, you’ll only see them if something isn’t right.
For marketers, it’s important to discover and fix these issues so your website visitors don’t have a negative experience.
Below, let’s review what an HTTP 304 not modified status code is, and what’s causing it.
An HTTP 304 not modified status code means that the website you’re requesting hasn’t been updated since the last time you accessed it. Typically, your browser will save (or cache) web pages so it doesn’t have to repeatedly download the same information. This is an attempt to speed up page delivery. However, if this happens to your site, visitors could be prevented from accessing your web pages.
When you click on a web page or URL, your browser requests access to it from a web server. If it has not been modified since the last time you accessed it, the web server will send back a 304 not modified status code, which lets your browser know to use a cached version of the web page.
Usually, you’ll only see this error code if you’re on a search engine because search engines index and cache websites.
If your browser receives this code, it’ll try to show you a saved version of the page. But sometimes it might prevent you from accessing the URL because it’s outdated.
As a marketer, you could lose out on traffic and leads if visitors are prevented from seeing your site.
So, what causes a 304 not modified code?
Causes of an HTTP 304 Not Modified Status Code
If a user sees a 304 not modified status code on your site, there isn’t much you can do. This is because the problem is most likely on their side of the screen.
Users could receive a 304 not modified status code for a variety of reasons:
1. You have a virus.
If you have a virus or malware on your computer, it most likely has corrupted your browser. This could impact your browser’s ability to communicate with web servers and cache web pages.
2. You’ve recently installed or uninstalled software.
Sometimes when you install or uninstall software on your computer, the registry could become corrupt. Again, this impacts your browser.
3. An application has corrupted files.
If there are corrupted files related to your internet browser, it will impact its ability to save web pages and update information.
How to Fix a 304 Not Modified Status Code
Although marketers can’t do much if a user sees a 304 not modified status code, users can try a few things to get the web page to show up on their browser.
1. Clear browsing data.
Clearing your browsing data will make sure your cache is cleared so it can try to access the URL you’re requesting.
To clear your browsing data, go to your History and then click «Clear browsing data.» In Chrome, it looks like this:
Once you click that, make sure you check off all three options. Then, you’ll want to change the time frame to «All Time.» It should look like this:
2. Run cleaners to get rid of viruses and malware.
A 304 not modified code could be happening because your browser is corrupted with a virus or malware. Run a check to make sure that isn’t the issue and clean up your computer.
3. Disable extensions.
There could be something wrong with your extensions. For example, they could be corrupt, which impacts your browser’s ability to receive information. Disable your extensions to see if this is the issue.
If these things don’t work, fixing a 304 not modified can be a more technical process. You might consider asking a web developer or someone in IT to take a look.
If you receive an HTTP 304 not modified error code, it’s because the URL you requested has outdated information. To fix it, you’ll want to double-check that the error isn’t on your side — the client’s — but instead on the server-side.
Any ideas why on some links that I try to access using HttpWebRequest I am getting «The remote server returned an error: (304) Not Modified.» in the code?
The code I’m using is from Jeff’s post here (the page seems to have disappeared, see an archive copy at the Wayback Machine).
Note the concept of the code is a simple proxy server, so I’m pointing my browser at this locally running piece of code, which gets my browsers request, and then proxies it on by creating a new HttpWebRequest, as you’ll see in the code. It works great for most sites/links, but for some this error comes up. You will see one key bit in the code is where it seems to copy the http header settings from the browser request to it’s request out to the site, and it copies in the header attributes. Not sure if the issue is something to do with how it mimics this aspect of the request and then what happens as the result comes back?
case "If-Modified-Since":
request.IfModifiedSince = DateTime.Parse(listenerContext.Request.Headers[key]);
break;
I get the issue for example from http://en.wikipedia.org/wiki/Main_Page
PS. UPDATE HERE
Still can’t work this out. Basically I can identify 1 link which has an issue, and it seems to work fine, 2nd time it gets the error, 3rd time OK, 4th time gets the error, 5th time OK etc. As if there is some state not getting cleared or something in the code. I’ve tried to clean up the code a bit using «using» type statements etc.
Here’s the code. If anyone can spot why every 2nd time I browse to a link like http://newsimg.bbc.co.uk/css/screen/1_0_16/nol/v4/story.css (starting at the 2nd time, not the first) via this proxy code I get the error I’d love to hear.
class Program
{
static void Main(string[] args)
{
Proxy p = new Proxy(8080);
Thread proxythread = new Thread(new ThreadStart(p.Start));
proxythread.Start();
Console.WriteLine("Proxy Started. Press Any Key To Stop...");
Console.ReadKey();
p.Stop();
}
}
public class Proxy
{
private HttpListener _listener;
private int _port;
public Proxy(int port)
{
int defaultport = 8080;
// Setup Thread Pool
System.Threading.ThreadPool.SetMaxThreads(50, 1000);
System.Threading.ThreadPool.SetMinThreads(50, 50);
// Sanitize Port Number
if (port < 1024 || port > 65535)
port = defaultport;
// Create HttpListener Prefix
string prefix = string.Format("http://*:{0}/", port);
_port = port;
// Create HttpListener
_listener = new HttpListener();
_listener.Prefixes.Add(prefix);
}
public void Start()
{
_listener.Start();
while (true)
{
HttpListenerContext request = null;
try
{
request = _listener.GetContext();
// Statistics (by Greg)
int availThreads = -1;
int compPortThreads = -1;
ThreadPool.GetAvailableThreads(out availThreads, out compPortThreads);
log("INFO", request.Request.Url.ToString(), "START - [" + availThreads + "]");
ThreadPool.QueueUserWorkItem(ProcessRequest, request);
}
catch (HttpListenerException ex)
{
log("ERROR", "NA", "INFO: HttpListenerException - " + ex.Message);
break;
}
catch (InvalidOperationException ex)
{
log("ERROR", "NA", "INFO: InvalidOperationException - " + ex.Message);
break;
}
}
}
public void Stop()
{
_listener.Stop();
}
private void log(string sev, string uri, string message)
{
Console.Out.WriteLine(Process.GetCurrentProcess().Id + " - " + sev + " (" + uri + "): " + message);
}
private void ProcessRequest(object _listenerContext)
{
#region local variables
HttpWebRequest psRequest; // Request to send to remote web server
HttpWebResponse psResponse; // Response from remote web server
List<byte> requestBody = new List<byte>(); // Byte array to hold the request's body
List<byte> responseBody = new List<byte>(); // Byte array to hold the response's body
byte[] buffer;
string uri = "";
#endregion
var listenerContext = (HttpListenerContext)_listenerContext;
uri = listenerContext.Request.Url.ToString().Replace(string.Format(":{0}", _port), "");
// Create Interent Request
HttpWebRequest internetRequest = (HttpWebRequest)WebRequest.Create(uri);
#region Build Request Up
internetRequest.Method = listenerContext.Request.HttpMethod;
internetRequest.ProtocolVersion = listenerContext.Request.ProtocolVersion;
internetRequest.UserAgent = listenerContext.Request.UserAgent;
foreach (string key in listenerContext.Request.Headers.AllKeys)
{
try
{
switch (key)
{
case "Proxy-Connection":
case "Connection":
internetRequest.KeepAlive = (listenerContext.Request.Headers[key].ToLower() == "keep-alive") ? true : false;
break;
case "Content-Length":
internetRequest.ContentLength = listenerContext.Request.ContentLength64;
break;
case "Content-Type":
internetRequest.ContentType = listenerContext.Request.ContentType;
break;
case "Accept":
internetRequest.Accept = listenerContext.Request.Headers[key];
break;
case "Host":
break;
case "Referer":
internetRequest.Referer = listenerContext.Request.Headers[key];
break;
case "If-Modified-Since":
internetRequest.IfModifiedSince = DateTime.Parse(listenerContext.Request.Headers[key]);
break;
default:
internetRequest.Headers.Add(key, listenerContext.Request.Headers[key]);
break;
}
}
catch (Exception ex)
{
Console.WriteLine("Error settup up psRequest object. Error = " + ex.Message + "\n" + ex.StackTrace);
}
}
#endregion
#region Copy content into request
buffer = new byte[1024];
using (Stream instream = listenerContext.Request.InputStream)
{
int incount = instream.Read(buffer, 0, buffer.Length);
while (incount > 0)
{
internetRequest.GetRequestStream().Write(buffer, 0, incount);
incount = instream.Read(buffer, 0, buffer.Length);
}
}
#endregion
// Get Internet Response
HttpWebResponse internetResponse = null;
try
{
using (internetResponse = (HttpWebResponse)internetRequest.GetResponse())
{
#region Configure Local Response Header Keys
foreach (string key in internetResponse.Headers.Keys)
{
try
{
switch (key)
{
case "Transfer-Encoding":
listenerContext.Response.SendChunked = (internetResponse.Headers[key].ToLower() == "chunked") ? true : false;
break;
case "Content-Length":
listenerContext.Response.ContentLength64 = internetResponse.ContentLength;
break;
case "Content-Type":
listenerContext.Response.ContentType = internetResponse.Headers[key];
break;
case "Keep-Alive":
listenerContext.Response.KeepAlive = true;
break;
default:
listenerContext.Response.Headers.Add(key, internetResponse.Headers[key]);
break;
}
}
catch (Exception ex)
{
log("ERROR", uri, "Error settup up listenerContext.Response objects. Error = " + ex.Message + "\n" + ex.StackTrace);
}
}
#endregion
try
{
// Transfer the body data from Internet Response to Internal Response
buffer = new byte[1024];
using (Stream inputStream = internetResponse.GetResponseStream())
{
int outcount = inputStream.Read(buffer, 0, buffer.Length);
while (outcount > 0)
{
listenerContext.Response.OutputStream.Write(buffer, 0, outcount);
outcount = inputStream.Read(buffer, 0, buffer.Length);
}
}
}
catch (Exception ex)
{
log("ERROR", uri, "Could not obtain response from URI: " + ex.Message);
}
finally
{
listenerContext.Response.OutputStream.Close();
}
}
}
catch (Exception ex)
{
//if (ex is InvalidOperationException ||
// ex is ProtocolViolationException ||
// ex is WebException)
//{
// log(uri, "Could not successfully get response: " + ex.GetType() + " - " + ex.Message);
// listenerContext.Response.Close();
// return;
//}
//else { throw; }
log("ERROR", uri, "Could not successfully get response: " + ex.GetType() + " - " + ex.Message);
listenerContext.Response.Close();
}
}
}
And here is an example of what I see — first hit is good, 2nd has error…
Proxy Started. Press Any Key To Stop...
2080 - INFO (http://newsimg.bbc.co.uk:8080/css/screen/1_0_16/nol/v4/story.css): START - [50]
2080 - INFO (http://newsimg.bbc.co.uk:8080/css/screen/1_0_16/nol/v4/story.css): START - [50]
2080 - ERROR (http://newsimg.bbc.co.uk/css/screen/1_0_16/nol/v4/story.css): Could not successfully get response: System.Net.WebException - The remote server returned an error: (304) Not Modified.
Dec 7, 2017 10:00:01 AM |
304 Not Modified: What It Is and How to Fix It
A close look at what a 304 Not Modified response code is, including troubleshooting tips to help you resolve this error in your own application.
A 304 Not Modified message is an HTTP response status code
indicating that the requested resource has not been modified since the previous transmission, so there is no need to retransmit the requested resource to the client. In effect, a 304 Not Modified
response code acts as an implicit redirection to a cached version of the requested resource.
Often it can be challenging to distinguish between all the possible HTTP response codes and determine the exact cause of errors like the 304 Not Modified
code. There are dozens of possible HTTP status codes used to represent the complex relationship between the client, a web application, a web server, and the multitude of third-party web services that may be in use, so determining the cause of a particular status code can be challenging. In this article we’ll examine the 304 Not Modified
code by looking at a few troubleshooting tips, along with some potential fixes for common problems that might be causing this issue within your own web applications, so let’s get to it!
The Problem is Server-Side
All HTTP response status codes that are in the 3xx
category are considered redirection messages
. Such codes indicate to the user agent (i.e. your web browser) that an additional action is required in order to complete the request and access the desired resource. Unlike client error responses
found in the 4xx
codes, like the 403 Forbidden Error
we looked at recently, which could occur due to either a client- or server-side issue, a 304 Not Modified
code generally indicates an issue on the actual web server hosting your application.
Having said that, the appearance of a 304 Not Modified
is typically not an issue that requires much user intervention on your part. This is because a 304
code is a response when the original user agent request occurred using a safe
method. Any HTTP method that doesn’t alter the state of the server is considered safe
. Thus, any request method that only requires the server to response with a read-only operation would be safe
. The most common of these safe
HTTP methods is GET
, but others include HEAD
and OPTIONS
.
If the user agent request included either of the special headers If-None-Match
or If-Modified-Since
then the server will check the cached version of the resource against the requested version. If the version matches then that cached version can be returned, rather than regenerating a new copy. The If-None-Match
header indicates that the ETag
response header should be verified, which contains a specific resource version. On the other hand, the If-Modified-Since
with a specific last modified date with which to compare the last modified date of the resource.
Since the 304 Not Modified
indicates that something has gone wrong within the server
of your application, we can largely disregard the client
side of things. If you’re trying to diagnose an issue with your own application, you can immediately ignore most client-side code and components, such as HTML, cascading style sheets (CSS), client-side JavaScript, and so forth. This doesn’t apply solely to web sites, either. Many smart phone apps that have a modern looking user interface are actually powered by a normal web application behind the scenes; one that is simply hidden from the user. If you’re using such an application and a 304 Not Modified
occurs, the issue isn’t going to be related to the app installed on your phone or local testing device. Instead, it will be something on the server-side, which is performing most of the logic and processing behind the scenes, outside the purview of the local interface presented to the user.
If your application is generating unexpected 304 Not Modified
response codes there are a number of steps you can take to diagnose the problem.
Start With a Thorough Application Backup
As with anything, it’s better to have played it safe at the start than to screw something up and come to regret it later on down the road. As such, it is critical that you perform a full backup of your application, database, and so forth, before attempting any fixes or changes to the system. Even better, if you have the capability, create a complete copy of the application onto a secondary staging
server that isn’t «live,» or isn’t otherwise active and available to the public. This will give you a clean testing ground with which to test all potential fixes to resolve the issue, without threatening the security or sanctity of your live application.
Diagnosing a 304 Not Modified Response Code
A 304 Not Modified
response code indicates that the requested resource has not been modified since the previous transmission. This typically means there is no need to retransmit the requested resource to the client, and a cached version can be used, instead. However, it’s possible that the server is improperly configured, which is causing it to incorrectly respond with a 304 Not Modified
code, instead of the standard and expected 200 OK
code of a normal, functional request. Thus, a large part of diagnosing the issue will be going through the process of double-checking what resources/URLs are generating 304 Not Modified
response codes and determining if these codes are appropriate or not.
If your application is responding with 304 Not Modified
codes that it should not be issuing, this is an issue that many other visitors may be experiencing as well, dramatically hindering your application’s ability to service users. We’ll go over some troubleshooting tips and tricks to help you try to resolve this issue. If nothing here works, don’t forget that Google is your friend. Try searching for specific terms related to your issue, such as the name of your application’s CMS or web server software, along with 304 Not Modified
. Chances are you’ll find others who have experienced this issue and have found a solution.
Troubleshooting on the Server-Side
Here are some additional tips to help you troubleshoot what might be causing the 304 Not Modified
to appear on the server-side of things:
Confirm Your Server Configuration
Your application is likely running on a server that is using one of the two most popular web server softwares, Apache
or nginx
. At the time of publication, both of these web servers make up over 84%
of the world’s web server software! Thus, one of the first steps you can take to determine what might be causing these 304 Not Modified
response codes is to check the configuration files for your web server software for unintentional redirect instructions.
To determine which web server your application is using you’ll want to look for a key file. If your web server is Apache then look for an .htaccess
file within the root directory of your website file system. For example, if your application is on a shared host you’ll likely have a username associated with the hosting account. In such a case, the application root directory is typically found at the path of /home/<username>/public_html/
, so the .htaccess
file would be at /home/<username>/public_html/.htaccess
. That said, if you have access to the system Apache configuration file then you should open the /etc/apache2/httpd.conf
or /etc/apache2/apache2.conf
file instead.
The most likely culprit for producing unexpected 304
codes in Apache is the mod_cache
module. Thus, within the configuration file you have open look for a section that checks for the mod_cache.c
file. Here’s an example from the official documentation:
LoadModule cache_module modules/mod_cache.so
<IfModule mod_cache.c>
LoadModule cache_disk_module modules/mod_cache_disk.so
<IfModule mod_cache_disk.c>
CacheRoot "c:/cacheroot"
CacheEnable disk "/"
CacheDirLevels 5
CacheDirLength 3
</IfModule>
# When acting as a proxy, don't cache the list of security updates
CacheDisable "http://security.update.server/update-list/"
</IfModule>
Since you don’t want to cause irreversible damage, don’t delete anything, but instead just temporarily comment out the caching section by adding #
characters at the start of every line to be commented out. Save the modified configuration file then restart the Apache web server to see if this fixed the problem.
On the other hand, if your server is running on nginx
, you’ll need to look for a completely different configuration file. By default this file is named nginx.conf
and is located in one of a few common directories: /usr/local/nginx/conf
, /etc/nginx
, or /usr/local/etc/nginx
. By default, nginx
actually comes with built-in caching, so it is not uncommon for static resources to be cached and for a 304 Not Modified
response code to be sent when refreshing a page or what not. Thus, troubleshooting for unexpected caching can be a bit more challenging then with Apache.
The main thing you should look for within the nginx.conf
file is the expires
directive, which can be used within a block directive
(i.e. a name set of directives) to define when requested files from within that server should expire (that is, when the cached versions should be refreshed from the server). For example, here the expires
configuration maps a handful of content types to differing expiration timestamps:
map $sent_http_content_type $expires {
default off;
text/html 24h;
text/css 24h;
application/javascript max;
~image/ max;
}
server {
listen 80;
listen 443 ssl;
server_name www.example.com;
expires $expires;
}
If you find an expires
directive in your own configuration, try temporarily commenting it out by preceding it with #
characters. Save the changed file then restart the server and test if the issue was resolved.
Look Through the Logs
Nearly every web application will keep some form of server-side logs. Application logs
are typically the history of what the application did, such as which pages were requested, which servers it connected to, which database results it provides, and so forth. Server logs
are related to the actual hardware that is running the application, and will often provide details about the health and status of all connected services, or even just the server itself. Google «logs [PLATFORM_NAME]» if you’re using a CMS, or «logs [PROGRAMMING_LANGUAGE]» and «logs [OPERATING_SYSTEM]» if you’re running a custom application, to get more information on finding the logs in question.
Debug Your Application Code
If all else fails, it may be that a problem in some custom code within your application is causing the issue. Try to diagnose where the issue may be coming from through manually debugging your application, along with parsing through application and server logs. Ideally, make a copy of the entire application to a local development machine and perform a step-by-step debug process, which will allow you to recreate the exact scenario in which the 304 Not Modified
occurred and view the application code at the moment something goes wrong.
No matter what the cause, the appearance of a 304 Not Modified
within your own web application is a strong indication that you may need an error management tool to help you automatically detect such errors in the future. The best of these tools can even alert you and your team immediately when an error occurs. Airbrake’s error monitoring software provides real-time error monitoring and automatic exception reporting for all your development projects. Airbrake’s state of the art web dashboard ensures you receive round-the-clock status updates on your application’s health and error rates. No matter what you’re working on, Airbrake easily integrates with all the most popular languages and frameworks. Plus, Airbrake makes it easy to customize exception parameters, while giving you complete control of the active error filter system, so you only gather the errors that matter most.
Check out Airbrake’s error monitoring software today and see for yourself why so many of the world’s best engineering teams use Airbrake to revolutionize their exception handling practices!