W3docs

PHP headers_sent() Function: Everything You Need to Know

As a PHP developer, you may need to check whether HTTP headers have already been sent to the client. The headers_sent() function is a built-in function in PHP

Every HTTP response is split into two parts: a block of headers (status code, Content-Type, cookies, redirects) followed by the response body. The catch is that headers must be sent before any body output. The moment PHP echoes a single byte of body, it flushes the headers and locks them — any later call to header(), setcookie(), or session_start() then triggers the infamous Cannot modify header information - headers already sent warning.

headers_sent() is the built-in that lets you ask, before you try to send a header, whether it is already too late. This guide covers its syntax, its by-reference parameters, what causes premature output, and how to fix it.

What headers_sent() Does

headers_sent() returns a boolean:

  • true — headers have already been sent (output started). Any further header() / setcookie() call will fail.
  • false — no output has started yet, so it is still safe to set headers.

Guarding header logic with headers_sent() lets you avoid the warning and degrade gracefully (for example, log the problem or fall back to a JavaScript redirect) instead of crashing the page.

Syntax

headers_sent(string &$filename = null, int &$line = null): bool

Both parameters are optional and passed by reference. When headers have been sent, PHP fills them with the location of the output that started it:

  • $filename — the name of the source file where output first began.
  • $line — the line number within that file.

This is what makes headers_sent() so useful for debugging: it points you straight at the culprit.

Basic Usage

Check the return value before sending a header:

<?php

if (!headers_sent()) {
    header('Location: /dashboard');
    exit;
}

echo 'Headers were already sent, cannot redirect via HTTP.';

If output has not started, the redirect header is sent. Otherwise the script avoids the fatal warning and prints a fallback message.

Finding Where Output Started

Pass the two reference variables to learn exactly what sent the headers — invaluable when a stray space or echo is buried in an included file:

<?php

if (headers_sent($file, $line)) {
    echo "Headers already sent in $file on line $line";
} else {
    setcookie('theme', 'dark');
    echo 'Cookie set successfully.';
}

If the condition is true, you get a message like Headers already sent in /var/www/header.php on line 12, telling you precisely where to look.

What Triggers "Headers Already Sent"

Anything that produces body output before your header call flushes the headers. Common causes:

  • Whitespace or a blank line before <?php — even one space or newline counts as output.
  • A newline after the closing ?> of an included file. (Best practice: omit the closing ?> in pure-PHP files entirely.)
  • echo, print, printf, or var_dump running before the header.
  • A UTF-8 file saved with a BOM (byte-order mark) — those invisible leading bytes are output.
  • PHP warnings/notices printed to the page (when display_errors is on) before headers.

Fixing It with Output Buffering

If you cannot reorder your code so all headers come first, wrap the script in an output buffer. ob_start() holds the body in memory instead of sending it immediately, so headers stay modifiable until the buffer is flushed:

<?php

ob_start();              // start buffering — nothing is sent yet

echo 'Some early output';

// Still safe: the echo above is held in the buffer, headers are not sent
setcookie('user', 'jane');
header('X-App-Version: 2.0');

ob_end_flush();          // now send headers, then the buffered body

Because output is buffered, headers_sent() would still return false after the echo, and the later setcookie() and header() calls succeed.

  • header() — send a raw HTTP header.
  • headers_list() — list headers queued or already sent.
  • setcookie() — set a cookie (sends a Set-Cookie header).
  • ob_start() — start output buffering to delay sending headers.
  • PHP Sessionssession_start() also sends headers and is a frequent trigger.

Conclusion

headers_sent() is a small but essential guard: call it before any header(), setcookie(), or session_start() to check whether output has already begun. When it returns true, the by-reference $filename and $line arguments pinpoint the offending output so you can fix it — or wrap your script in ob_start() to keep headers modifiable until you are ready to flush.

Practice

Practice
What can cause the 'headers already sent' warning in PHP?
What can cause the 'headers already sent' warning in PHP?
Was this page helpful?