W3docs

PHP ob_gzhandler() Function: Everything You Need to Know

As a PHP developer, you may need to compress your output to reduce bandwidth usage and improve the speed of your website. The ob_gzhandler() function is a

Compressing HTML, CSS, or JSON before it leaves the server reduces bandwidth and makes pages load faster. PHP's built-in ob_gzhandler() function is a ready-made way to do this from inside your script: you hand it to the output buffer, and it gzip-compresses everything your script echoes — but only when the browser says it can decompress it. This article covers its syntax, a complete example, how it negotiates with the client, the gotchas that bite people, and when you should reach for it versus letting the server handle compression.

What the ob_gzhandler() Function Does

ob_gzhandler() is a callback designed to be passed to ob_start(). You never call it directly — instead, the output buffering system calls it for you with the buffered content as its argument, and it returns the compressed (or, when compression isn't possible, unmodified) bytes.

Before compressing, it inspects the request's Accept-Encoding header and picks the best supported scheme:

  • If the client supports gzip, it compresses with gzip and sets Content-Encoding: gzip.
  • If the client supports only deflate, it uses deflate instead.
  • If the client supports neither, it returns the content untouched and ob_start() fails (returns false), so the response is sent uncompressed.

Because it sets the Content-Encoding and Vary response headers automatically, you must register it before any output is sent — see headers_sent() if you hit a "headers already sent" error.

Syntax

ob_start("ob_gzhandler");

ob_gzhandler() takes two parameters internally ($buffer and $mode), but you never supply them — the buffering engine does. You just register the string "ob_gzhandler" as the callback name.

A Complete Example

<?php

ob_start("ob_gzhandler");
echo "This will be compressed using gzip compression";
ob_end_flush();
?>

Here, ob_start() opens an output buffer with ob_gzhandler() as its handler, the echo writes into that buffer instead of straight to the client, and ob_end_flush() closes the buffer and sends its (now compressed) contents. From the visitor's point of view nothing changes — the browser transparently decompresses the response — but fewer bytes travel over the network.

Falling Back for Clients That Don't Support gzip

ob_start("ob_gzhandler") returns false when the client doesn't advertise gzip or deflate support. If you ignore that, no buffer is started and your later ob_end_flush() will warn. Check the return value and fall back to a plain buffer:

<?php
if (!ob_start("ob_gzhandler")) {
    ob_start(); // plain buffer, no compression
}
echo "Served either compressed or uncompressed, but always buffered.";
ob_end_flush();
?>

Setting the Compression Level

ob_start() doesn't accept a compression level — ob_gzhandler() uses zlib's default (controlled by the zlib.output_compression_level INI setting, default -1). To force a specific level from 1 (fastest, least compression) to 9 (slowest, smallest), skip ob_gzhandler() and use your own callback with gzencode():

<?php
ob_start(function ($buffer) {
    return gzencode($buffer, 9);
});
echo "Compressed at the maximum level.";
ob_end_flush();
?>

Note that this custom callback does not negotiate Accept-Encoding or set Content-Encoding: gzip for you — ob_gzhandler() does both automatically. If you roll your own, you must send those headers yourself, which is why ob_gzhandler() remains convenient for the common case.

ob_gzhandler() vs. zlib.output_compression

PHP offers a second, even simpler way to compress output: the zlib.output_compression INI directive. Set it to On (or a byte threshold) and PHP gzips the whole response with no code at all:

zlib.output_compression = On

The two approaches are mutually exclusive — enabling zlib.output_compression while also calling ob_start("ob_gzhandler") triggers a warning and double-compresses nothing useful. Prefer zlib.output_compression when you can edit php.ini or use ini_set(), and reserve ob_gzhandler() for cases where you need it inside a script you don't control the configuration for.

Common Gotchas

  • Don't nest gzip layers. Combining ob_gzhandler() with server-level compression (Nginx/Apache gzip) or with zlib.output_compression can produce corrupted, double-encoded responses.
  • Register it first. Any prior echo, whitespace before <?php, or BOM in the file sends headers early and breaks compression.
  • Not for binary that's already compressed. Gzipping JPEGs, PNGs, or ZIPs wastes CPU for almost no size win.
  • It needs the zlib extension. ob_gzhandler() requires PHP to be built with zlib (it almost always is, but worth knowing on minimal builds).

Conclusion

The ob_gzhandler() function provides a simple, self-contained way to gzip PHP output: register it as a callback to ob_start(), and it negotiates encoding and sets headers for you. In modern setups, however, server-level compression (Nginx, Apache) or a CDN handling gzip/brotli is usually preferred — it offloads CPU from PHP and compresses static assets too. Knowing ob_gzhandler() still matters for legacy codebases and scripts where you can't touch the server config. For the broader picture of working with buffers, see the PHP Output Control overview.

Practice

Practice
What is the purpose of the ob_gzhandler in PHP?
What is the purpose of the ob_gzhandler in PHP?
Was this page helpful?