.htaccess – gzip and cache your site for faster loading and bandwidth saving

Please read Improving web site performance with Apache .htaccess for an updated version of this article.

Last week I changed my hosting provider from Site5 to NearlyFreeSpeech.NET.
Despite the fact that the first one is faster than the second, NFSN is a lot more cheaper (I only pay for what I really use).

So in order to speed up my site and save bandwidth (the more I use the more I pay) I use .htaccess file to gzip my text based files and optimize cache HTTP headers.
Although this site is powered by WordPress which has some really great plugins to optimize PHP output I wanted a more generic solution which can be applied to all PHP web applications.

I also try to follow as much as I can the rules for high performance web sites so don’t be surprised if some Expires header seems too long (far future Expires header rule requires at least 172801 seconds).

Turn on compression

mod_gzip is an external extension module for Apache that allows you to quickly and easily compress your files before you send them to the client. This speeds up your site like crazy!

If your hosting provider has mod_gzip module enabled, the best way to compress your content is to add the following lines to your .htaccess file:

<ifModule mod_gzip.c>
  mod_gzip_on Yes
  mod_gzip_dechunk Yes
  mod_gzip_item_include file .(html?|txt|css|js|php|pl)$
  mod_gzip_item_include handler ^cgi-script$
  mod_gzip_item_include mime ^text/.*
  mod_gzip_item_include mime ^application/x-javascript.*
  mod_gzip_item_exclude mime ^image/.*
  mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*

unfortunately my provider doesn’t have this module enabled. If you have the same problem, you can add the following line instead:

php_value output_handler ob_gzhandler

this makes PHP to compress your PHP files (be cautious, this is very CPU intensive).

To compress other static content you can use Ali Farhadi’s JSmart Compressor which compress CSS and JavaScript files.

Setup JSmart

Note: This section is outdated. JSmart Compressor has been renamed and updated as SmartOptimizer.

  • Assuming your application resides in your web root, simply place the JSmart files into /jsmart.
  • Edit /jsmart/config.php if you like, though the default settings should work fine. The mine looks like:
//JSmart Configuration File

//Show error messages if any error occurs (true or false)
define('JSMART_DEBUG_ENABLED', false);

//Encoding of your js and css files. (utf-8 or iso-8859-1)
define('JSMART_CHARSET', 'utf-8');

//Base dir for javascript files
define('JSMART_JS_DIR', '../');

//Base dir for css files
define('JSMART_CSS_DIR', '../');

//Change it to false only for debugging purposes
define('JSMART_CACHE_ENABLED', true);

//JSmart cache dir
define('JSMART_CACHE_DIR', 'cache/');
  • Create and chmod 777 /jsmart/cache
  • Add the following lines into your .htaccess in your web root:
<ifModule mod_rewrite.c>
  RewriteEngine on
  RewriteRule ^(.*.(js|css))$ jsmart/load.php?file=$1

Add future Expires and Cache-Control headers

A first-time visitor to your page will make several HTTP requests to download all your sites files, but using the Expires and Cache-Control headers you make those files cacheable. This avoids unnecessary HTTP requests on subsequent page views.

To set your Expires headers add these lines to your .htaccess:

<ifModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 1 seconds"
  ExpiresByType text/html "access plus 1 seconds"
  ExpiresByType image/gif "access plus 2592000 seconds"
  ExpiresByType image/jpeg "access plus 2592000 seconds"
  ExpiresByType image/png "access plus 2592000 seconds"
  ExpiresByType text/css "access plus 604800 seconds"
  ExpiresByType text/javascript "access plus 216000 seconds"
  ExpiresByType application/x-javascript "access plus 216000 seconds"

and to set Cache-Control headers add:

<ifModule mod_headers.c>
  <filesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|swf)$">
    Header set Cache-Control "max-age=2592000, public"
  <filesMatch "\.(css)$">
    Header set Cache-Control "max-age=604800, public"
  <filesMatch "\.(js)$">
    Header set Cache-Control "max-age=216000, private"
  <filesMatch "\.(xml|txt)$">
    Header set Cache-Control "max-age=216000, public, must-revalidate"
  <filesMatch "\.(html|htm|php)$">
    Header set Cache-Control "max-age=1, private, must-revalidate"

Now all your files must have the right headers and be cacheable except the CSS and JavaScript files processed by JSmart. This is because JSmart overrides the cache headers when gzipping these files.

To fix this you have to edit /jsmart/load.php file and change the block code

  if (isset($headers['If-Modified-Since']) && $headers['If-Modified-Since'] == $mtimestr)
    header_exit('304 Not Modified');

  header("Last-Modified: " . $mtimestr);
  header("Cache-Control: must-revalidate", false);
} else header_nocache();


  if (isset($headers['If-Modified-Since']) && $headers['If-Modified-Since'] == $mtimestr)
    header_exit('304 Not Modified');

  if ($file_type=='js') {
    header("Expires: " . gmdate("D, d M Y H:i:s", $mtime + 216000) . " GMT");
    header("Cache-Control: max-age=216000, private, must-revalidate", true);
  } else {
    header("Expires: " . gmdate("D, d M Y H:i:s", $mtime + 604800) . " GMT");
    header("Cache-Control: max-age=604800, public, must-revalidate", true);
} else header_nocache();

Turn off ETags

By removing the ETag header, you disable caches and browsers from being able to validate files, so they are forced to rely on your Cache-Control and Expires header.
Entity tags (ETags) are a mechanism to check for a newer version of a cached file.

Add these lines to .htaccess:

<ifModule mod_headers.c>
  Header unset ETag
FileETag None

Remove Last-Modified header

If you remove the Last-Modified and ETag header, you will totally eliminate If-Modified-Since and If-None-Match requests and their 304 Not Modified responses, so a file will stay cached without checking for updates until the Expires header indicates new content is available!

Add these lines to .htaccess:

<ifModule mod_headers.c>
  Header unset Last-Modified


With these settings you should have your site a lot faster and your file’s size greatly reduced.


Some descriptions are based on .htaccess (Hypertext Access) Articles from AskApache.
mod_gzip settings are taken from Highub – Web Development Blog.

Published by

Samuel Santos

Java developer, Open Source hacker, Web technologist, JUG Leader.

  • http://www.askapache.com AskApache

    Excellent article! Very nice, you’ll need the faster speed these tips provide when I start sending traffic your way. You might also like: Hacking wp-cache for ultimate speed.



  • http://www.samaxes.com/ Samuel Santos

    Thanks. I’m waiting for it :)

  • Pingback: PHP Weekly Reader - April 27th 2008 : phpaddiction()

  • Pingback: Skylog » Blog Archive » links for 2008-05-06()

  • http://www.heimtierheim.com Alex

    i search this tool and this works fine.

    use htaccess for rewriting the urls. it’s better for the security and static files look like nicer

  • http://www.miniclip-games.net George

    Thanks for the great article…. I was using mod_expires and gzip only. I just added the eTag, mod_headers stuff to my htaccess … hope it gives my sites a boost in speed.

    Thanks again.
    Stumbled it !

  • http://www.palsmart.net/ Kelvin

    Undeniable, a must read & practice for all webmaster!
    Thanks for the tips!

  • http://gregbrown.co.nz Greg Brown

    Nice article – my only question is should you be gzipping your jpg/png/gif files? They’re already compressed so I’d have thought gzipping wouldn’t noticeably reduce the file size, and just create unnecessary processor overhead.

  • http://www.samaxes.com/ Samuel Santos

    Yes Greg, you are right. jpg/png/gif files shouldn’t be gzipped.

    The mod_gzip configuration has been updated. Thanks!

  • http://www.clubperruno.com Nidia

    What a G R E A T tip!!!
    My site is now very very fast!!

  • Pingback: .htaccess - gzip and cache your site for faster loading and bandwidth saving « Sandeep Verma()

  • Pingback: Ultimate .htaccess file Examples()

  • fakhru

    Nice article it help me a lot to speed up my site
    thanks a lot

  • William

    Thank you, I was about to dump WordPress and my host to do speed issues, but thanks to these tips, my site now runs faster than before!

  • http://sms-in.ru/ -= Cara =-

    Thank you very much for tips and tricks!

  • http://pagesofinterest.net/blog/ Mike

    Thank you for this overview of different methods.

    I was especially happy with Smart Optimizer, thank you so much for mentioning it!

    I saved 36% in total :)

  • http://www.webwhitenoise.com/ JAB_au

    Thanks for the guide, I was using PHP GZip method on my site (WWN) before this, the .htaccess method was something I didn’t know.


  • KnyghtMare

    If your host is up-to-date you won’t have mod_gzip becaues it was renamed/morphed into mod_deflate

  • http://www.samaxes.com/ Samuel Santos

    mod_gzip still exists as an external extension module and mod_deflate only comes bundle with Apache since the version 2.
    Unfortunately for me, my host still uses Apache 1.3.

  • Pingback: A to Z of WordPress .htaccess Hacks | Nometech.com()

  • Pingback: 从A到Z 26条 WordPress .htaccess 技巧 at 站趣-分享建站的乐趣()

  • Pingback: WordPress .htaccess Hacks | Web Design()

  • Pingback: Free To Feel » Cake Tips from my App()

  • Pingback: Blogging Tips: SOB's Top 7 Tweaks To A Faster Wordpress Blog()

  • Pingback: Things to do after a series of upgrade in wordpress | :: HawkEYE Expression ::()

  • http://jingkung.net sunsuron

    The line:php_value output_handler ob_gzhandlerwill not work when Suhosin is installed in the server.

  • http://spiamediagroup.com Steve Yakoban

    Great Tut! It was news to me and it definitely works. I’m a regular here now.

  • Pingback: 10 Ways to Use .htaccess to Speed Up WordPress | WPShout.com()

  • Pingback: The htaccess Rules You Must Have On Your Blog | Blog Optimization Guide | Zemalf()

  • Pingback: Quality Management and Webpage Load Speed | Sydney Freelance Business Consultant & Trainer()

  • Pingback: Configuring cache expiration headers with .htaccess (Apache) — omglog()

  • http://intheb.com Abhishek Dilliwal

    Thank You for that great article :)…

  • http://www.pestahosting.com hosting murah

    woww thanka tips…

  • http://RichardBaldock.com Richard

    Hi, Great stuff. How can you tell if the Mod_Gzip is enabled on your server?

    • http://www.samaxes.com/ Samuel Santos

      No, it’s not. Unfortunately my hosting provider supports neither mod_gzip nor mod_deflate.

  • Pingback: 做了个万像摄影的网站 | 农妇、山泉,有点田()

  • http://www.overcloud9.com Moumita Paul

    I just can’t thank you enough.My site http://www.overcloud9.com was rated D by Yslow and Google webmasters showed loading time of 12.5 seconds!with your simple htaccess modification codes,now Yslow rates it at 70%.

  • http://www.jocuri.freefun.ro Jocuri

    Nice tips, Thanks a lot!

  • http://RichardBaldock.com Richard

    Hi, My hosting provider confirmed that the Gzip mod is available, so I placed your script at the top of .htaccess files. YSlow (Yahoo’s website performance add-in for Firefox) still reports though that a whole bunch of .css & .js files could be compressed for improved perfomance. So it appears the code is not working. I have tried this on static HTML sites and WordPress sites with the same result?
    Do you have any idea/s why this may not be working ?

  • Pingback: Blog-Ladezeiten Optimieren – Teil 1 - Blog, Ladezeiten, gzip, Kompression, mod_deflate, Test - Plerzelwupps Erfahrungen()

  • http://RichardBaldock.com Richard

    Thanks, My server is Apache 2.2.13 so I tried using this as you suggested.
    (on both WP & static HTML sites)

    SetOutputFilter DEFLATE

    The result though is still the same. YSlow reports that .js & .css files are not compressed.?

    • http://www.samaxes.com/ Samuel Santos

      I suggest you to contact your hosting provider and ask them which module are they using to compress files.

  • Guy

    i also added your code to my htacsess but i do not have any change
    my host server support deflate and gzip
    when i try to gzip the index file i get error page
    my host does not support or give me explanation why
    do you have any suggestions?

    • http://www.samaxes.com/ Samuel Santos

      Hello Guy,
      You have to ask your hosting provider which Apache module are they using to gzip files.

  • Guy

    hi thanks for your answer i asked them here is the question and their answer
    Q: hi
    1.which Apache module are you using to gzip files?

    2.why i do not see Content-Encoding: gzip
    in the
    Response Headers – http://www.espressotech.co.il/index.html

    Date: Fri, 08 Jan 2010 17:25:45 GMT
    Server: Microsoft-IIS/5.0
    Last-Modified: Fri, 08 Jan 2010 10:59:18 GMT
    Accept-Ranges: bytes
    Content-Length: 16841
    Content-Type: text/html

    200 OK

    [Jan 8, 2010 9:48:34 AM]
    A: Hi

    We do not have any special setup for apache module, apache running as was explained in your early tickets, using standard coding and all php functions applied are located in link below:

    You may looking for some special coding or advanced setting that is not supported running in our shared hosting service, keep in mind that shared hosting service may limit to standard setup to keep service running optimal for all uses.

    Best Regards
    Support team

    also the server release is
    Apache Release 1.03

    please advise me what i can do in order to enable gzip under these conditions?

    • http://www.samaxes.com/ Samuel Santos

      The link http://bsd2.hostdone.com/info.php shows that they are using Apache 1.3.41.
      This version does not come bundled with any gzip module.

  • Guy

    does it mean that this server cannot support gzip?
    in the same link http://bsd2.hostdone.com/info.php it says
    HTTP_ACCEPT_ENCODING gzip, deflate
    what does it mean?

    • http://www.samaxes.com/ Samuel Santos

      That’s a header sent by the browser request telling the server that it supports gzipped data.

  • Pingback: Speed up a wordpress website « My Blog()

  • Pingback: 提高网页加载速度的几点优化建议 | 网络赚钱方法-小熊建站博客()

  • d

    dont you mean 755, you should never 777 its a huge security risk

    • http://www.samaxes.com/ Samuel Santos

      You can use any mode you find best as long as JSmart has write access to that folder.

  • Pingback: kaka212's Blog » Blog Archive » Các bài viết tối ưu Cache HTTP Headers()

  • Pingback: Gzip it for speed | HOSTERWARE UK()

  • Pingback: Quick Cache – Pump it up! | HOSTERWARE UK()

  • Pingback: 10 Things To Do For Every New Site()

  • Pingback: Tăng tốc blog của bạn bằng .htaccess | Hutek.info()

  • http://www.TheBicyclingGuitarist.net/ The Bicycling Guitarist

    Thanks for this page. Already my page speeds are much greater. I am very new at .htaccess stuff but am familiar with HTML and CSS. So far I haven’t been able to get smartoptimizer to compress the CSS files yet even though I followed its installation instructions carefully.

  • http://www.TheBicyclingGuitarist.net/ The Bicycling Guitarist

    Wow quick response! My host server runs the older Apache that has gzip but not deflate. As for the css, it apparently IS being compressed by gzip but for some reason the page speed tools in the Firebug add-on for the Firefox browser indicated that it wasn’t.

    So far as I know, I now have browser caching and gzipping enabled for all content on my web site. If you have a few minutes, maybe you could email me and I could send you exactly what is in my .htaccess file (cobbled together from yours and smartoptimizer’s code) and you could tell me if I did it right. If not, still cool. thanks again for a great page!

  • lovewp

    Please tell me where I can find .htaccess file . (What a stupid question, right ?)

    • http://www.samaxes.com/ Samuel Santos

      The file does not exist by default.
      You have to create it under your site root folder.

  • http://forum.bisik.net ichigoni

    for a wap site, when turn on the gzip, it seem like not much changes.

  • http://www.khabarnaak.com khabarnaak

    its really helpful .. use the same technique on my website .. and its loading speed is now really improved .. ..

    Thanks to author

  • http://www.papersoup.org Brixter

    I am looking for the WordPress plugin WP Super Cache and I was wondering if there’s a version that you can install on your custom php content management system?

    • http://www.samaxes.com/ Samuel Santos

      Hi Brixter,
      I’m not sure I get your question right.
      I don’t own any custom CMS.

  • http://www.papersoup.org Brixter

    @ Samuel Santos, Sorry if I did not make myself clear. Hmmm what I mean is that does the WP Super Cache is only available in WordPress? Does it have any other version for other CMS or platforms? I’ve been looking @ Google for a while and can’t seem to find answer. I can only see WordPress out there.

    • http://www.samaxes.com/ Samuel Santos

      Not that I know of.
      You should probably ask Donncha, which is the author of WordPress Super Cache plugin, just to make sure.

  • http://www.papersoup.org Brixter

    @ Samuel thanks for the link, but sadly there’s no other version other then WordPress. Your htaccess tutorial doesn’t work with my server but works locally. I guess I have to find a cache library in php classes and see if I can cache my template files.

  • Pingback: Affiliate & Webmaster Blog()

  • http://lacyg.info LacyG | Software Developer in Cluj

    Thank you! I’ve always used different plugins for WP to enable gzip and caching, and now had a hard time setting it up on a custom system.

    Thank you again!

  • http://www.wpinsite.com Jason

    Fantastic post, though quiet old, still hope the techniques work.

  • Nik Clair-Williams

    Thanks! This is an awesome tutorial…saw instant results in speed after adjusting my .htaccess file. Went from a 78 to 85 in my Yslow score and even more in other areas.

  • Pingback: Tăng tốc blog của bạn bằng .htaccess | Thế Giới Net - Tin Tức IT - Thủ Thuật - Tin Học - Blogger - WordPress - Make Money Online()

  • Pingback: Tăng tốc blog của bạn bằng .htaccess | Wordpress | VN222.COM()

  • Pingback: Seo Css to Optimize caching | Seoxgoogle()

  • Pingback: Seo Css to Minimize the Payload Size and the Rtt | Seoxgoogle()

  • Pingback: Seo Css to Minimize the Payload Size and the Rtt()

  • http://webylife.com Nikunj

    I have tried everything but the Yslow still show Add Expires headers i dont what went wrong

  • http://www.lineshjose.com lineshjose

    very helpful post. :)

  • http://www.computer-nach-wunsch.de/ Peter

    Thank you! Nice article! My site is now faster than ever bevor! Great article!

  • http://websilon.net creation site ardeche

    Thanks a lot, it is what i was exactly looking for. Regards.

  • http://fixabathroom.com.au Mick

    Hi Sam,
    Cheers for your efforts.
    I’ve noticed that etags does not need the

    Header unset ETag

    All that is needed is

    FileETag None

  • Pingback: apache üzerinden statik dosyaları sunmak | /home/haqen()

  • Pingback: PHP Cache Control for browser to only cache part of page | SeekPHP.com()

  • http://haijerome.wordpress.com/ Jerome Dennis D

    Thanks a lot brother :-)

    great piece of information to speed up any site.

  • Pingback: Website performance: Asset Management | My Blog()

  • http://thecustomizewindows.com Abhishek Ghosh

    Excellent article.

    Kindly edit (for the new users) :

    &lt;ifModule mod_gzip.c&gt;

    to :

    <ifModule mod_gzip.c>

    And like that.

    (probably something is changing &lt; and &gt; to url friendly chars.).

    It is what I am viewing : http://thecustomizewindows.com/suggest-7.png

    • http://www.samaxes.com/ Samuel Santos

      Hi Abhishek,

      I moved to a new hosting provider during the weekend and somewhere in the process some characters have been messed up.

      It should be fixed now.

  • Pingback: Cache, htaccess - accélérer WordPress? - Formation Création Internet Montpellier Nimes()

  • Pingback: 10 Ways to Use .htaccess to Speed Up WordPress()

  • http://flight-case-shop.ch Flightcase

    Dank You!!!

    This code speeds up my side really extremely

  • Pingback: Techbeast.net - Wordpress Optimisations()

  • Pingback: SEO durch Verbesserung der Webseiten-Geschwindigkeit - Ozzwood()

  • http://www.gauravtips.in Gaurav Mishra

    Thank you very much!! Great article

  • http://www.baliberty.com miss alice

    Huy guys,
    I can’t find the “” /jsmart/load.php file” in my directory
    in order
    “To fix this you have to edit /jsmart/load.php file and change the block code”.

    I have only :
    Smartoptimiser directory
    > cache directory (empty)
    > config.php
    > index.php
    > minifiers directory
    > css.php
    > js.php

    Would you have any idea ?

  • http://joomlabasic.com Che Linh Nguyen

    i used
    ExpiresActive On
    ExpiresDefault “access plus 1 seconds”
    ExpiresByType text/html “access plus 1 seconds”
    ExpiresByType image/gif “access plus 2592000 seconds”
    ExpiresByType image/jpeg “access plus 2592000 seconds”
    ExpiresByType image/png “access plus 2592000 seconds”
    ExpiresByType text/css “access plus 604800 seconds”
    ExpiresByType text/javascript “access plus 216000 seconds”
    ExpiresByType application/x-javascript “access plus 216000 seconds”
    . But it response 500 error

    • http://www.samaxes.com/ Samuel Santos

      Make sure you wrap those lines inside a <ifModule mod_expires.c> element.
      That way the mod_expires module will only be used when supported by the server.

  • http://manggale.com jasa pembuatan website murah

    I’ve been using W3 Total Cache, does it still require the above code on my website htaccess?

    • http://www.samaxes.com/ Samuel Santos

      I don’t use W3 Total Cache myself.
      You need to open your website’s .htaccess file, check which modules have been enabled by the plugin, and add those that are missing.

  • http://www.jdfoxmicro.com/ Jeffrey Fox


    I think you have some incorrect information about ETags and Last-Modified. You said that disabling these will prevent the clients’ browsers from hitting your web server with conditional request (If-Modified-Since and If-None-Match) until after the cache period has expired.

    However, web browsers will not hit your server with a conditional request during the cache period anyway; if a user clicks on a link to (or within) your site, the browser will see the cache is still current (from your Cache-Control tag), and load the content from its cache. It will not contact your server, and it will not consider the ETag or Last-Modified at all. In other words, removing these tags is not necessary to prevent the browser from sending a request during the cache period.

    After the cache period (or if the user hits F5), the browser will use the ETag and/or Last-Modified to send a conditional request; if the server sees from those tags that the resource is unchanged, it will send back a 304. If you disable ETag or Last-Modified headers, then the browser will always have to download the whole resource again, because it will have no information to share with the server about what version it has in its cache. So, you will certainly see no 304s in your logs, but what you don’t realize is you increase bandwidth.

    Bottom line: leave the ETag or Last-Modified there. Then, when the cache period is expired, the browsers will contact your web server, but if the resource has not been updated, your server will only have to respond with a few bytes (304), rather than send the resource again.

  • john

    can i use 2 .htaccess different coding files in public html folder
    if not then kindly put conditon if my site is offline then

    RewriteEngine on
    #RewriteBase /
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^.$ – [NC,L]
    RewriteRule .
    index.php [L]


    RewriteEngine on
    #RewriteBase /
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^.$ – [NC,L]
    RewriteRule .
    index.php [L]
    AddHandler application/x-httpd-php4 .php .php4 .php3