Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

PHP’s header('Location: ...') redirect works only if PHP sends it before any response body output. Put the redirect before HTML, whitespace, debug output, warnings, or output from included files, then call exit. If it still fails, check where output began and inspect the HTTP response.

Why PHP’s Location header fails

HTTP response headers must be sent before the response body. If PHP has already emitted output, it can no longer add a redirect header. Output can be visible HTML or an echo, but it can also be an otherwise easy-to-miss blank line, whitespace outside PHP tags, output from an included file, a warning or notice, or a startup error. The PHP manual for header() explains that the function must run before actual output.

A Location: header normally results in a 302 redirect, unless status 201 or another 3xx status has already been set. Calling header() does not stop the script, so a redirect branch should end with exit.

Put the redirect before output

Handle the redirect at the start of the response, before rendering a template or sending other content:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<?php
if ($authenticated === false) {
    header('Location: /login.php', true, 302);
    exit;
}

Check the main script and every file it loads with require or include. An included file can emit output just as the main script can.

Find where output started

Use headers_sent() to check whether the response headers have already been sent. It can also report the file and line where output began:

<?php
if (headers_sent($file, $line)) {
    error_log("Headers already sent in {$file}:{$line}");
} else {
    header('Location: /login.php', true, 302);
    exit;
}

According to the PHP manual for headers_sent(), the function can return the originating filename and line. If the filename is empty, output may have begun before the script source ran, for example because of a startup error.

Check the response and fix hidden output

Inspect the response in browser developer tools or with an HTTP client. A server-side redirect should return a redirect status and a Location header. If there is no Location header, the redirect may not have run, or output or an error may have prevented it. If the header is present but the browser does not navigate, investigate the URL, client, proxy, or redirect policy; client behavior depends on the deployment.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Look for these common sources of premature output:

  • Remove a UTF-8 byte-order mark (BOM), leading spaces, or blank lines before <?php.
  • In files containing only PHP, omit the closing ?> tag to avoid accidentally emitting trailing whitespace.
  • Move echo, print, var_dump(), template rendering, and other body output until after headers are set.
  • Fix warnings, notices, or startup errors rather than displaying them before the redirect.
  • Inspect included files for output that occurs before the redirect branch.

Choose the redirect status for the request

The default behavior of Location: is a 302 unless status 201 or another 3xx status has already been set. Choose an explicit status when the redirect needs different HTTP semantics:

Status Typical use Request method behavior
302 Temporary general redirect Does not promise method preservation; client behavior can vary.
303 Often used for POST-redirect-GET after processing a form submission Directs the client to retrieve the destination rather than repeat the submitted request.
307 or 308 Temporary or permanent redirect when the original method should be preserved Client should repeat the request using the same method.

The choice depends on what the application expects the client to do. Verify the status and Location value in the actual response.

Example: redirect after a form submission

Process and validate the submission before sending any body output. Then redirect to the result page and stop execution:

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Validate and save data here.
    header('Location: /success.php', true, 303);
    exit;
}
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When output buffering helps—and when it does not

ob_start() can hold body output in a buffer so headers can still be sent before the buffer is flushed. PHP also provides the output_buffering configuration directive. Buffering can consume memory and complicate control flow; it can also hide the source of accidental output, so it is not a substitute for fixing output order.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

This example shows buffering mechanics. ob_end_clean() discards the buffered body before the redirect:

<?php
ob_start();
// Code that may generate body output.
header('Location: /next.php', true, 302);
ob_end_clean();
exit;

See the PHP documentation for ob_start() and the output control configuration directives. For most failures, the durable fix is to find unintended output and send the redirect before constructing the response body.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.