PHP flush() Function: Send Output to the Browser Immediately
Learn how PHP flush() sends buffered output to the browser immediately, how it differs from ob_flush(), and when to use it in long-running scripts.
By default, PHP collects the text your script prints (with echo, print, etc.) and sends it to the browser in chunks — often only once the script ends. The built-in flush() function lets you push whatever has already been produced right now, so the user sees partial output before the page is fully generated. This page explains what flush() does, how it differs from ob_flush(), the buffers that sit between your script and the browser, and when reaching for it actually helps.
What the flush() Function Does
flush(): voidflush() asks PHP to hand off any output it is holding to the layer below it — the SAPI and the web server. It takes no arguments and returns nothing. A common use is a long-running script that should show progress (a log line, a counter) instead of leaving the user staring at a blank page until everything finishes.
Two important limits:
flush()does not affect PHP's own output buffering layer (the one started withob_start()). If output buffering is active, the text is still trapped in PHP's buffer andflush()has nothing to send. You must release that layer first withob_flush()orob_end_flush().flush()cannot override buffering done by the web server or proxy (Apachemod_deflate, Nginxproxy_buffering, FastCGI, gzip). Those may still hold the data until they decide to send it.
A Basic Example
When no PHP output buffering is enabled, flush() alone is enough to push current output:
<?php
echo "Starting a slow task...\n";
flush(); // send the line above to the browser now
sleep(2); // pretend we are doing real work
echo "Done!\n";
?>Without the flush() call, the user would typically see both lines appear together after 2 seconds. With it, "Starting a slow task..." can arrive immediately.
flush() vs ob_flush()
This is the distinction that trips people up. PHP can stack two separate buffers, and each *flush function targets a different one:
| Function | Buffer it empties |
|---|---|
ob_flush() | PHP's output-control buffer (created by ob_start()) → moves data down to the SAPI buffer |
flush() | The SAPI / write buffer → moves data on toward the browser |
When output buffering is on, you need both, in order — ob_flush() first to release PHP's buffer, then flush() to push it onward:
<?php
ob_start(); // turn on PHP output buffering
echo "Buffered text\n";
ob_flush(); // PHP buffer -> SAPI buffer
flush(); // SAPI buffer -> browser
?>Reverse the order or skip ob_flush() and the text stays stuck inside PHP. If you want PHP to flush after every echo automatically, see ob_implicit_flush().
Why It Often "Doesn't Work"
Streaming output reliably is harder than calling one function, because several layers buffer independently:
- gzip / compression —
zlib.output_compressionand Apache'smod_deflatemust accumulate enough bytes before sending. Disable compression for the response you want to stream. - Web server / proxy buffering — Nginx (
proxy_buffering on), FastCGI, and load balancers commonly re-buffer the response. - Browser rendering — some browsers wait for a minimum number of bytes before painting; padding the output can force an earlier paint.
Because of these, flush() is best treated as a hint, not a guarantee. For modern streaming needs (server-sent events, chunked APIs) configure the server explicitly rather than relying on flush() alone.
Related Output Functions
ob_flush()— flush PHP's output-control buffer.ob_end_flush()— flush and turn off output buffering.ob_get_flush()— return the buffer contents and flush it.- PHP Output Control — overview of how the buffering layers fit together.
fflush()— flush buffered writes to an open file (not the browser).
Conclusion
flush() forces PHP to send output it has already produced toward the browser instead of waiting for the script to end. Remember that it only touches the SAPI/write buffer: with ob_start() active you must call ob_flush() first, and even then the web server or compression layer can delay delivery. Used with that understanding, flush() is a handy way to stream progress from long-running scripts.