When visiting a website, the website will cache in your browser. This cache can be controlled by configuring your Cache-Control HTTP headers for your website This is done by adding mod_expires in the .htaccess file of your server.

If you don't set your Cache-Control for the HTTP headers, then, you will have a longer wait times when visiting your website. Each time your website is accessed without Cache-Control, your website has to make a request to the server for each image, javascript file, CSS file, and so forth to load.

Browser caching is good because it allows your web resources to be stored in the browser for faster page load time. This makes your site faster to surf on the web. To remove the cache from your browser, your browser cache needs to be cleared. For information on clearing your browser cache, please see our article on How to clear your browser's cache. The following sections will explain the basics of setting up the Apache Module mod_expires in your .htaccess.

Basic code for setting expire dates for cache

In order to add browser caching to your website, you will need to set the date for when the cache expires. This cache code is placed in the .htaccess found in your public_html folder. You will need to edit your .htaccess file. Add the following code to the file and save it.

ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresDefault "access plus 2 days"

Now your site will set the time each for each resource that was added to the .htaccess to expire. In the previous code example, the jpg, jpeg, gif, png will expire in a year and pdf, javascript and flash files will expire in a month. More explanation o these settings will come later in this article. Next we will look at using the <ifmodule> for adding Cache-Control with mod_expires.

Code for mod_expires in an <ifmodule>

Using mod_expires in an <ifmodule> allows image types and other file types to be set in an array. This matches the file types to the specific expire time. This streamlines the htaccess code. In the code below, the file types are listed in a row like jpg|jpeg|png|gif|js|css|swf|ico|woff|mp3. Below is an example of the code to use.

<ifmodule mod_expires.c>
<Filesmatch "\.(jpg|jpeg|png|gif|js|css|swf|ico|woff|mp3)$">
    ExpiresActive on
    ExpiresDefault "access plus 2 days"
</Filesmatch>
</ifmodule>

This sets the cache to expire to the same duration for each of the file types. To specify the specific times for each individual file type, you will want to use the previous code example. The following will explain the Directive types that are used for Cache-Control.

Directive types

There are three directive types; ExpiresActive, ExpiresByType, and ExpiresDefault. The following table explains the difference between them.

Caching directives
ExpiresActive Directive Enables the Expires headers for the website.
ExpiresByType Directive This defines the age of the cache header and the type of file to cache.
ExpiresDefault Directive This sets the age of the cache for all documents other than those specified in the ExpiresByType for the site.

Caching Directive bases

There are 3 base types the access, now, and modification type.

  • access
  • now (same as "access")
  • modification

Duration of cache time

The duration of cache time can be set to one of the following units of time.

  • years
  • months
  • weeks
  • days
  • hours
  • minutes
  • seconds

Basic syntax for ExpiresByType intervals

The following shows the basic syntax for the ExpiresByType. Each file type can be set to specific times to expire the cache.

ExpiresByType text/html "access plus 2 days 12 hours"
ExpiresByType image/png "access plus 6 months 3 days"

Recommended Expire date ranges

You do not want to set your expire times for your cache to unrealistic settings. If you keep the cache to a maximum of a year and a minimum of a month, you should have your browser caching working optimized for your site.

  • Set your images to a long expire time like "access plus 1 year". Images take more time to load and are updated less frequently than other files.
  • Make your CSS, HTML, and Javascript expire at a minimum of a month like "access plus 1 month". CSS, HTML and JavaScript's typically are updated more when developing a site than the sites images.
  • Keep your cache expire date at most a year.
Did you find this article helpful?

We value your feedback!

Why was this article not helpful? (Check all that apply)
The article is too difficult or too technical to follow.
There is a step or detail missing from the instructions.
The information is incorrect or out-of-date.
It does not resolve the question/problem I have.
How did you find this article?
Please tell us how we can improve this article:
Email Address
Name

new! - Enter your name and email address above and we will post your feedback in the comments on this page!

Related Questions

Here are a few questions related to this article that our customers have asked:
Ooops! It looks like there are no questions about this page.
Would you like to ask a question about this page? If so, click the button below!
Ask a Question
2014-07-23 9:59 pm
I added the Basic expire code from this tutorial to my htaccess file and the GTMetrix Report is still saying "F" fail on that issue...so it must not be seeing it. Is the code changed to adding expire dates to the headers ? I do add this code to the htaccess file and that the only thing to do ? or is there another step ?
Staff
11,150 Points
2014-07-24 10:35 am
Hello PaulAlford,

Thank you for your question. We are happy to help, but will need some additional information. What is the exact issue and suggestion GTMetrix is giving you an "F" for?

It should begin as soon as you add the .htaccess rule. If you are using a CMS, such as Wordpress, Joomla, or Drupal, it's possible an existing rule in the .htaccess file is interfering with the rule you are adding.

If this is the case, you would instead go to the specific setting/plugin in the CMS, and set it there.

If you have any further questions, feel free to post them below.
Thank you,

-John-Paul
n/a Points
2014-08-01 3:47 pm

What is it? Set-Cookie: PHPSESSID=kvtgebg048oc30mvuqnkeiviq2; path=/

Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: max-age=604800, must-revalidate
Pragma: no-cache

 

Why the date Expires in past? The server answer with the included script of jcart on a site artchern.com gives such answer lust date, having cleaned this script the server answer at once becomes true and Expires: shows date for a week forward. Any instructions in accesse, httpd don't give the decision. In the script there are no direct instructions Cache-control (no cache) on a caching ban. well or they are written by any hidden formulas? or it is meant that the POST method programmatically forbids a caching? In what area to look for? Thanks.

Staff
9,968 Points
2014-08-01 4:36 pm
Hello Mike, and thanks for your comment.

The Set-Cookie: PHPSESSID part is simply PHP setting a cookie for the session of a user.

I'm not sure why your Expires header would be showing a date in the past, what is the code you currently have in your .htaccess file for turning on expires headers? That is not normal behavior, so it seems like it's either something with your code or your server that is causing this.

- Jacob
n/a Points
2014-08-03 2:29 am

Hello JacoblMH! Thanks for the answer.In my .htaccess file  currently this:AddType application/x-httpd-php .php .htm .html

Options +FollowSymLinks

RewriteEngine On

RewriteCond %{HTTP_HOST} ^www.artchern.com$ [NC]

RewriteRule ^(.*)$ http://artchern.com/$1 [R=301,L]

 

RewriteRule ^news_([a-z_0-9]+).html$ news.html?id_news=$1 [L]

<IfModule mod_expires.c>

ExpiresActive On

ExpiresDefault "access 7 days"

ExpiresByType image/jpeg "access plus 7 day"

ExpiresByType image/jpg "access plus 7 day"

ExpiresByType image/png "access plus 6 months"

ExpiresByType image/gif "access plus 6 months"

ExpiresByType image/x-icon "access plus 6 months"

ExpiresByType application/javascript "access plus 6 months"

ExpiresByType text/css "access plus 6 months"

ExpiresByType text/javascript "access plus 6 months"

ExpiresByType text/js "access plus 6 months"

 

</IfModule>and in the file httpd.conf   contains this: 

RewriteEngine on

RewriteRule ^/(.*\.)v[0-9.]+\.(css|js|gif|png|jpg)$ /$1$2 [L,E=VERSIONED_FILE:1]

Header add "Cache-Control" "max-age=604800" env=VERSIONED_FILE

<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf|xml|txt|html|htm)$">

Header set Cache-Control "max-age=604800, public"

 

</FilesMatch>

 I wrote above that on a site there is a script "jcart"

  and if absolutely to clean this script "jcart" then the answer of the server

 

   will be correct with the necessary date forward.ThanksMike

Staff
10,141 Points
2014-08-04 10:57 am
When viewing your headers, everything looks fine to me and I'm not seeing any dates in the past. It does appear that you may have some server side caching issues that you may want to speak with your server admin about. Unfortunately, I was unable to replicate the issue you are seeing at all.
n/a Points
2014-08-26 6:07 am

Hi,

We are having excel files in docroot which will be often updated.

Whenever we updated the content of the .xls file we are not seeing the modifed content  while accesing through the URL. No script or program we are using. We just putting the file in docroot and access through the URL.

I feel like its caching somewhere may be in proxy.

I used mod_header to stop cacheing with below entry in httpd.conf file but still we are not getting the updated content, it takes time to get the updated content. COuld someone help me to fix it.

<FilesMatch "\.(xls)$">FileETag None#<ifModule mod_headers.c>Header unset ETagHeader set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"Header set Pragma "no-cache"Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"#</ifModule></FilesMatch>

Staff
21,046 Points
2014-08-26 9:06 am
Hello Abdur,
It sounds as if you simply do not want the xls files to cache. Try using the code below as it should set th xls files to a non caching state.

<FilesMatch "\.(xls)$">
ExpiresActive On
ExpiresDefault A1
Header append Cache-Control must-revalidate
</FilesMatch>


Kindest Regards,
Scott M
n/a Points
2014-10-13 5:00 am

Hello scott,

 First of all thank you so much your suggestion as it really worked. Now only one problem remainsSorry to reply laste as i was struck ip some other work.

As you suggested i enabled the below in httpd.conf file.

<FilesMatch "\.(xls)$">ExpiresActive OnExpiresDefault A1Header append Cache-Control must-revalidate</FilesMatch>

I am telling you here what exactly happening.I last modifed a file name sample.xls on August monthI first accessed the file today before enabling the expire module.It gave me the proper file as this is the first time i am accessing. Then i modifed the file again today then accessed for 2nd time but it didnt show me the modified content because proxy serves the file from cache.From the above steps i replicated the issue, Then i enabled the expire and header module.After that i accessed the file again but i was getting the same old file even though i enabled the option.

I then tried accessing one more file which was ceated on august month first time after enabling the expire. [Difference between above and this one is , In the above case i accessed the file one time before activitating exipre module, but here in this case i accessed the file only after enabling]As usual it give the proper content. Then i modifed again and accessed, this time it worked, I can able to see the modified content.

With the above 2 testing i got the below conclusion.If we access an old last modified file for the first time, Heuristic expiration policies set a expire time by deafult.After that whatever i access how many time i accessed eventough modifying the file, it will always shows the old file from cache.Enabling the expire module also wont work till the expire time set by the Heuristic expiration policies expires. After it expired, a new exipre time wont be set by Heuristic expiration policies as we enabled the expire module.If no expire module enabled then again a new expire date is set by the Heuristic expiration policies.

In the 2nd testing, i didnt access the file before enabling the expire module hence there was no expire time set because of that its working fine eventhough many times we do modifying.

Your suggestion gave me solution for my current issue, Thank you so much for that.But i want to know how to solve the same for the old files also. because its a website where everyone access the file and all the files already accessed by the users. So we cannot go by the 2nd testing result like creating a new fileWe have to make this work for old files also.hence could you please tell us what we can do to serve the files not from the cache eventhough already expiration date set by Heuristic expiration policies.

To simplify my question This expire configuration works for the file which is not accessed and cached before in proxyWhat configuration we can do for the file which is already accesed and cached in the proxy and having a expiration date .

Staff
21,046 Points
2014-10-13 12:50 pm
Hello Rasheed,

Browsers should behave the same in this, but they may each act a bit differently. The way it should work, is browsers who have already cached the files will wait until the expiration date set in the headers before checking back. Each user can clear their own cache, but adding the exception for the specific file types will not cause those that have cached already to remove their cached versions.

Kindest Regards,
Scott M
n/a Points
2014-10-14 12:02 am

<p>Hello Scott,</p><p>So in my case the only soultion is we have to wait till the expire date which is there in the header to expire. After it expired only this expire configuration will work. Am i right ?</p><p>Eventhough clearing the cache in browser wont help ?</p><p>Because i cleared the cache and tested but its not working.</p><p>Please kindly help me in my understanding.</p>

Staff
10,141 Points
2014-10-14 8:45 am
Be sure to fully clear all temporary data in your browser. If any references to those files are left over, it will still attempt to deliver the old files.
n/a Points
2014-10-15 1:28 am

I deleted all the temporary files still i am getting the old files if the same file was accessed once before enabling the expire module.

If i havent access the file before enabling the expire module then everything works fine.

Additional information,In my case proxy server is serving the file from the cache

Staff
18,621 Points
2014-10-15 10:14 am
Hello Rasheed,

Sorry to hear that you're still having problems with the caching. If you're using a proxy server that has cached the files, there's nothing we can clear browser-side. You will need to have the proxy server files cleared. You will also need to check and see if the proxy server will abide by the expiration rules set by the website. Otherwise, the proxy server caching will need to be cleared on a regular basis.

Regards,
Arnel C.
n/a Points
2014-10-15 10:59 pm

Hello Arnel,

The configuration which is given by Scott is working. only thing is its not working for the file which is already cached once in the proxy earlier. If i wait till the already defined expiration date expired then after that everything works normal and the modification are relfecting as soon as we change from server end.

I understood that if the file cached in proxy then we need to clear from prxy end.

After client accepted to enable this Expire configuration i'll enalbe in the server and will ask the network team to clear the cache for this specific webserver from their end then everything will start works fine I hope.

Thank you all for helping me in resolving this issue. :)

Regards,

Rasheed.

n/a Points
2014-10-03 12:40 pm

Hi, 

I implemented following mod_expires in our httpd.conf file and run into some issue. 

LoadModule expires_module modules/mod_expires.so   --> Enabled mod_expires load module on httpd.conf file and added following.

<IfModule mod_expires.c>

 ExpiresActive on

<FilesMatch "\.(gif|jpe?g|ico|png|css|js)$">

  ExpiresDefault "access plus 2 weeks"

 </FilesMatch>

<FilesMatch "\.(docx?|pff|pdf|xlsx?|zip|tar|gz)$">

  ExpiresDefault "access plus 1 month"

 </FilesMatch>

</IfModule>

While testing, I noticed the jpg files that are published on NAS are being cached properly, example: Internet/FSE_MEDIA/stelprdb5359300.jpg but the files that are on theme directory (application ear file) are not being cached. FSE_WIDTheme/themes/html/FSE_WIDTheme/images/headercorner.gif

could someone assist on this. Thank You

- Prasana 

Staff
11,150 Points
2014-10-03 1:05 pm
Hello Prasana,

Thank you for your question. We are happy to help, but it is difficult to troubleshoot since there can be many causes.

I recommend reviewing your error logs (such as apache error logs) to narrow down the cause, since it can be anything stopping the theme directory from caching.

If you have any further questions, feel free to post them below.

Thank you,
John-Paul
n/a Points
2014-10-13 11:34 pm

Hi John,

Thanks for your response. I was busy with prouction issues and was not able to respond you at the earliest.

Regarding the theme files (that are Theme ear file) that are not being cached, I reviewed the apache error log and do not notice anything. I need your inputs on below:

1) Do you think we need to some cache configuration settings on theme customization(as my applicaiton runs on portal).  

2) We have external caching (Akamai caching), is't something that blocking my code for mod_expires (ExpireDefault directive type) that I listed earlier.

Please let me know your thoughts.

Thanks,

Prasana 

Staff
10,141 Points
2014-10-14 8:41 am
With an external caching server as you are describing, a user would be accessing that server when they access your site in which caching data may not be passed on to the user. To allow browser caching, you would need need to configure this on the external caching server.
n/a Points
2014-10-26 10:53 am

Thanks! This article is so helpful to me because I was having a problem with Wordpress caches, after following this article (of course did some modification with the expiry time) and the problem solved!

The direct article to my problem wasn't helpful at all, this solution should be suggested there too! http://www.inmotionhosting.com/support/edu/wordpress/recommended-wordpress-plugins/clearing-cache-in-wordpress

n/a Points
2014-12-19 2:16 pm

Hi,

The GTmetrix report for my sites -- newly hosted on InMotion -- lists files which are not covered by the W3 total Cache WP plugin: all are links to outside servers (Facebook, ShareThis, couter, etc.)  Yet, all of these are static, never-changing.

How do I set these to have long expiration?  

Thanks!

JF 

Staff
18,621 Points
2014-12-20 8:40 am
Hello Josefus,

Thanks for the question. W3TC Caching plugin tries to set the expiry headers for files on a web page so that they don't have to be loaded repeatedly. This allows the viewer to see the webpage faster since the file is "cached" and they don't have to load a new copy of it. If those links are static and don't change, then you most likely don't have to worry about it. Also, it is possible that you're running into files on servers where the expiry header aren't supported. So, unfortunately, you won't be able to affect those files with the expiry header. I was looking around the WordPress Codex and found this discussion about Expiry Headers in W3TC. I hope this helps to explain the issue!

Please let us know if you have any further questions or comments.

Regards,
Arnel C.
n/a Points
2014-12-20 10:57 am

Thank you, Amel!Yes, I understand what W3TC does, and it has been very effective (my page loading dropped from about 700ms to 220ms after switching from another caching plugin), but my YSlow score still points to areas that need improvement.

In addition, InMotion Systems staff is telling me that my sites experience Resource Overage... and wanted me to lower my GTmetrix scores, and this is why I'm here with questions.Specifically, under Add Expires Headers (YSlow score: E-56), it says that the following links -- all static, all going to outside servers -- do not have expiration:

Add Expires headersThere are 4 static components without a far-future expiration date.    http://c.statcounter.com/t.php...    http://www.google-analytics.com/ga.js    http://wd-edge.sharethis.com/button/getAllAppDefault.esi...    http://wd-edge.sharethis.com/button/checkOAuth.esi

I believe that W3TC doesn't have any effect on these outside links...  So, I'm asking whether there are instructions (code) that I can place in the .htaccess file that will have an effect on links going to outside servers.Recently, InMotion staff was able to help me refine my .htaccess file on some other issues, I'm hoping that if you cannot do the same here you would inquire among your colleagues and come up with the code that can do this. Once I have the code structure, I can enter it very easily.

Thank you again!

JF

 

Staff
11,150 Points
2014-12-20 12:43 pm
Hello JF,

Thank you for contacting us. I spent some time researching this (and asking around the office) as was not able to find a good working solution.

The problem is that when you pull something from an external server/source, you are affected by their server performance and load time.

It may be possible to pull the resources periodically and store them on your server, but it is almost like a reverse cdn setup, and can cause other problems.

A better solution may be to host the scripts/resources you are pulling externally on the same server your website resides on. Then you have control over the files, and caching, etc.

Thank you,
John-Paul
n/a Points
2014-12-20 1:30 pm

Thank you, JohnPaul!

On your suggestion to  host those scripts/resources locally... if you take a close look at the specific items I included in my query, they come from StatCounter, googleAnalytics and ShareThis -- I don't believe you can relocate any of them. And, as you said, reverse CDN might introduce other problems.

I gather there might not be a good solution to this one... but if you find one at a later time, I'd love to hear about it.

Thanks again,

JF

Post a Comment

Name:
Email Address:
Phone Number:
Comment:
Submit

Please note: Your name and comment will be displayed, but we will not show your email address.

25 Questions & Comments

Post a comment

Back to first comment | top

Need more Help?

Search

Ask the Community!

Get help with your questions from our community of like-minded hosting users and InMotion Hosting Staff.

Current Customers

Chat: Click to Chat Now E-mail: support@InMotionHosting.com
Call: 888-321-HOST (4678) Ticket: Submit a Support Ticket

Not a Customer?

Get web hosting from a company that is here to help. Sign up today!