PHP ob_list_handlers() Function: Everything You Need to Know
As a PHP developer, you may need to get a list of the registered output handlers. The ob_list_handlers() function is a built-in function in PHP that allows you
The ob_list_handlers() function returns an array containing the names of every output buffer handler that is currently active, ordered from the outermost buffer to the innermost. Output buffering lets PHP collect generated output in memory instead of sending it straight to the browser; a handler is the optional callback you attach to a buffer with ob_start() to transform that output before it is flushed. This page covers the syntax, return value, how PHP names each handler, and when reaching for ob_list_handlers() actually helps.
Syntax
ob_list_handlers(): arrayThe function takes no arguments and returns an array of strings. When no output buffer is active, it returns an empty array.
What the Handler Names Look Like
The strings you get back are not the buffer's contents — they are labels that identify each handler. The label depends on how the buffer was opened:
| How the buffer was started | Name in the array |
|---|---|
ob_start() with no callback | "default output handler" |
ob_start('ob_gzhandler') (built-in) | "ob_gzhandler" |
ob_start('my_function') (named callback) | "my_function" |
ob_start(fn($b) => $b) (closure) | "Closure::__invoke" |
Because anonymous functions all report as "Closure::__invoke", you cannot tell two different closures apart from this array — name your handler functions if you need to identify them later.
Basic Usage
Call ob_list_handlers() and loop over the result. When nothing is buffered the array is empty, so guard for that case:
<?php
$handlers = ob_list_handlers();
if (empty($handlers)) {
echo "No output handlers are active.\n";
} else {
foreach ($handlers as $handler) {
echo $handler . "\n";
}
}With no buffer started, this prints:
No output handlers are active.Inspecting Nested Handlers
Output buffers stack: each ob_start() opens a new buffer on top of the previous one. ob_list_handlers() reflects that whole stack, so it is handy for seeing exactly what is layered together.
<?php
function uppercase_handler(string $buffer): string
{
return strtoupper($buffer);
}
ob_start(); // default buffer, no callback
ob_start('uppercase_handler'); // named callback
ob_start(function ($buffer) { // anonymous callback
return trim($buffer);
});
print_r(ob_list_handlers());Output:
Array
(
[0] => default output handler
[1] => uppercase_handler
[2] => Closure::__invoke
)The order matches the order the buffers were opened: index 0 is the outermost (first) buffer, and the last index is the innermost (most recently started) one.
When Would I Use This?
ob_list_handlers() is a diagnostic tool, not something you call in normal request handling. Reach for it when you need to:
- Debug "headers already sent" or unexpected output by confirming which buffering layers are in play.
- Avoid double-compression — check for
"ob_gzhandler"before adding your own gzip handler, since thezlib.output_compressionINI setting may already register one. - Verify framework or middleware behavior, since many frameworks open their own buffers and you may not know how deep the stack is.
To count active buffers instead of naming them, ob_get_level() returns the depth directly:
<?php
ob_start();
ob_start('ob_gzhandler');
echo count(ob_list_handlers()), "\n"; // 2
echo ob_get_level(), "\n"; // 2Output:
2
2Common Gotchas
- Empty array is normal. A return of
[]simply means no buffer is open — it is not an error. - One name per buffer. A buffer started without a callback still appears, as
"default output handler"; the name reflects the handler, not whether a buffer exists. - Names are not callable. The strings are labels only. You cannot pass
"Closure::__invoke"back toob_start()to recreate the same handler.
Related Functions
ob_start()— open a new output buffer and optionally attach a handler.ob_get_level()— get the nesting level of output buffering.ob_get_contents()— read the current buffer's contents.ob_end_flush()/ob_end_clean()— close the topmost buffer.- PHP Output Control — overview of the output buffering family.
Conclusion
ob_list_handlers() gives you a quick, read-only snapshot of the output-buffer stack, naming each active handler from outermost to innermost. It is most valuable while debugging buffering issues or before registering a handler (such as gzip) that might already be present. Pair it with ob_get_level() when you only need the count.