Skip Navigation

PHP, Gzip and htaccess

There is a perfectly good chance that at the present time, your site is sending pages in an uncompressed form to users. That is perfectly normal - in fact it is pretty much standard - but there is a better way to send your data. Some browsers (not all, but some) can accept "gz-encoded" data, which means the data is compressed.

PHP includes functions for sending pages in a "gz-encoded" form. However, this can be a pain to add to large files. There is a much easier way to add gzip functionality to your site than editing every page on it.

To achieve this effect, we are going to be using one of the most powerful, yet least used, of the features of htaccess. In an htaccess file, we can include the following lines:

  1. php_value auto_prepend_file /full/path/to/begin_gzip.php
  2. php_value auto_append_file /full/path/to/end_gzip.php

The auto_prepend_file and auto_append_file commands are excellent in the right hands. They allow you to include files in all php scripts, without actually needing to use the include() function or the require() function. That makes it very very easy to handle includes, and even easier to add in new functionality to a site without actually needing to touch the PHP itself.

In this instance, we are using two files. The first line is the equivalent of adding include("begin_gzip.php") at the start of each PHP file. The second is the equivalent of adding include("end_gzip.php") at the end of each PHP file.

In the files themselves, we need to add in the functionality to control output buffering, and tell PHP to compress the data, if the user can receive it. A user-agent (like a browser) sends a header to a server indicating if it can receive "gz-encoded" data. If it can't, the server won't send back "gz-encoded" data - so there is no risk here that users may be unable to view your site. All that can happen is that the majority of users will see your site a bit quicker, and your bandwidth bills should drop.

Note: Please be aware that if your site is already using output buffering, the following scripts may not have the desired effect. In addition, output buffering with gz encoding is not available in versions of PHP previous to 4.0.5.

The first file, begin_gzip.php, needs to contain the following, which tells the PHP parser to begin output buffering, and that output will be gz encoded.

  1. <?php
  2. ob_start("ob_gzhandler");
  3. ?>

The second file, end_gzip.php, needs to contain the following. This will tell the PHP parser to send the contents of the buffer to the user.

  1. <?php
  2. ob_flush();
  3. ?>

Last, you need to include the two lines at the beginning of this tutorial to your htaccess file, remembering to change the path to the PHP files as required. If you do not yet have an htaccess file, open a blank document in a text editor, paste the two lines above into it, and save it. You need to upload it to your web server, and rename it to ".htaccess" (htaccess is the extension, and there must be no file name).

And there you go - your PHP based pages should now be sending data in a compressed format to those users that can handle it, and without any editting to your current site whatsoever.

34 comments

Konrad Roziewski
Poland #1: July 4, 2004
I've used auto_prepend_file with output buffering in one of my projects last year to transform XML into HTML. It worked quite well with Apache 2.0 and PHP 4.3. But sometimes when you tried to load a PHP page from another directory (without auto_prepend_file) Apache bahaved like it was trying to prepend that file nonetheless.

Now I can see it happening again with my current project -- httpd complains it couldn't find and prepend a file from distant, unrelated project directory. I'm going to throw away those auto_prepends.

As far as I can tell it is a bug in Apache and thus related with auto_prepend, not output buffering.
I have tried every way I can to add gzip to my site; I am running php 4.5.0, my host tells me gzip should work fine, but every time i try to implement it i get an error 500 message - anybody have the faintest idea why??
A 500 Internal Server error can be caused by several things. If PHP is running as a CGI module, it may be PHP generating the error. More likely it is a mistake in your .htaccess file though. If your server does not allow one or more of the commands you are using, such as "auto_prepend_file" or "auto_append_file", that will generate an error. If you can grab a copy of the error logs for your server, and track down the error in there, you may find more information. Otherwise, try and fix it through a process of elimination - try it with normal includes rather than "auto_prepend_file" and "auto_append_file", and so on, until you find where the error is.
kosherjava
United States #4: September 13, 2004
Wouldn't adding the following to htaccess be a better approach?

php_flag zlib.output_compression On
php_value zlib.output_compression_level 5
With ob_gzhandler if a script took 5 seconds to run (db calls etc) the buffering would wait till the whole page was generated and only than would it compress and send the output to the browser /user-agent, leading to what would seem to the user to be a nice amount of latency
the approach using zlib would allow straming as soon as even part of the output was ready.
Yes, that is also a fine way to add gzipping to a php-based site. However, the reason I've outlined the approach I have is because the output buffering, when done this way, allows for more functionality. You can manipulate the buffer once a page has run, adding things like highlighting, correction of common coding bugs, caching, etc.
Thanks kosherjava, the load time is like half now. Verry impressive
Good stuff! Thanks Dave, I can now save tons off my bandwidth bill :)
Eagle
United States #8: July 14, 2005
I have added below codes at the beginning of web files, it worked fine for me, to serve php, html, css, js, etc (PHP handler parsed) files (gzip) compressed and faster:

&lt;?php ob_start ("ob_gzhandler");
header("Content-type: text/css; charset: UTF-8");
?&gt;

Found it at below site(s)
http://www.atikotek.5gigs.com/edu/webdv/websrvr/ap/hta/index.php
or, http://atikotek.100free.com/edu/webdv/websrvr/ap/hta/index.html
or, http://atikotek.maclenet.com/edu/webdv/websrvr/ap/hta/index.html
Joe
United Kingdom #9: August 29, 2005
Hi Joe. As kosherjava said above, you can do it that way as well. If all you want is outbut buffering, that will be fine. However, this technique is described this way because it allows you to manipulate the output buffer before it is sent.
Watch out, if you already have it turned on, on some pages (like with phpbb) you should turn it of there, otherwise you get errors.
JonL
United States #12: November 11, 2005
Thanks for the htaccess tip using auto_prepend, using benchmarks, it's actually showing as still faster than zlib output on my site. Great tip. :-)
If you get a 500 Internal Server Error while attempting to use PHP directives from .htaccess it often means your host is using phpsuxec or similar, in which case you usually create a php.ini in the directory and set directives the php.ini way - though you should usually ask your host first.
Thanks for this... It's helped cut down my loading time alot.
Thanks for this. It will help a lot, as my site currently is extremely slow due to 140 k js includes and they should benefit extremely well from compression
Stefan
Netherlands #16: June 13, 2006
Thanks alot for the tip, really helped speeding up my site alot. Also I personally didn't like the fact that my output would start rolling out when a 'piece' of it is ready (distorting the layout at the beginning). A nice side effect of your script is that a user will only get the site at once, and not in little pieces ;)
How bout pictures and graphics that are in my site picmonkey.com . Do these pictures get compressed also?
I did a quick test to see how many other popular websites are using gzip and was surprised to find most are not.

Only a handful of sites providing external scripts (like analytics code) are providing gzip when requested by browsers. Google and MyBlogLog do it. Site Meter, Webtrends and Performancing do not.

In fact, some sites claiming to teach how to make good websites have home pages that are **over 350k!**

If you're a WordPress / PHP / JavaScript user, or want to do this on a windows machine with IIS6, you might also like the write-up I did at VibeTalk:

http://www.vibetechnology.com/vt/2006/09/22/triple-website-performance-with-gzip/.

I inlcuded a table listing the results of about 10 big-name websites that may surprise you.

If anyone has questions on making this work, I'm happy to help!

-Joe
Office Outlook
United States #19: October 20, 2006
What browsers can not accept "gz-encoded" data. Whether it is possible to define supports a browser "gz-encoded" data or not?
Great tutorial...very good...

But how do i check if the pages are compressed?
You can also put this code at the top of any php script, before the html content, that you would like to send to the browser.

Don't worry about flushing the buffer as this is automatic in PHP in this circumstance.

Most browsers have a function to deflate compressed content using gzip, but if not, then it will simply load the page the regular way. Very reliable and good for those still on dialup.

if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler");

else ob_start();
Excellent information. I added the code above and the result is immediately noticeable. I should have been using this long ago. Thanks so much.
Very useful article and much appreciated.
Wow. I can't beleive more people aren't doing this... i'm definitely sold.

Thanks.
Mike
Portugal #25: May 12, 2007
So do I!
You are my guru!
Thank you very much!

I did follow your instruction to do that on http://WebKing.hk, but 1 silly question, how can I know that my site is gzip already?

Thank you!!
You can check if your site is now using gzip compress, and the compression ratio, using this online tool:
http://www.gidnetwork.com/tools/gzip-test.php

For those of us using Firefox, here's an extension that can show this:
https://addons.mozilla.org/en-US/firefox/addon/60
Is this method the same as or better than mod_gzip in an htaccess file?
Seem like your Caching script is super-set of this script.
Both great script anyway. :)
Thanks alot dave,
one of my clients was having trouble with their account taking up too much of the servers time and the server would suspend the account for 3 min. well their information needs to be accessed 24/7 so this cannot happen. well this worked very well and they havnt been suspened since i put that in. (it used to happen everyday at least once)

again, THANKS ALOT!
Thanks Dave! Some very good stuff!
Thanks for this :) especially for the htaccess part
mrpwnage
Athens, Greece #33: October 1, 2008
I'm using a Windows end-to-end 64-bit system. That means Apache, PHP & MySQL are all 64-bit binaries. That being said, I can't run (can i?) mod_gzip because there is no x64 version. And now my question: I don't want to have to add this to every single page on the site manually, isn't there a way that I could set it to use gzip compression globally on the entire site indiscriminately? Perhaps through the httpd.conf or php.ini?
Remember, first things first - if your problem is bandwith or simple want your pages to load faster, you definitely should use gzip...

...HOWEVER, if you have a site with an heavy load, and you're always running out of memory, than you don't want to use gzip.

The gzip process needs additional memory, so, compress your code instead (javascript, CSS, XHTML...).

It can be confusing to edit it after, but if you save two versions, one compressed and one regular, you've just make the day, and your server will say thanks! =)

Post Your Comment

· Comments with keywords instead of a name have their URLs removed.
· Your email address will not be displayed or shared.

Live Comment Preview

 United States #35: 1 minute ago