Header("Location") on PHP

A classic PHP puzzle. This code looks like it should redirect to index.php, since 1 == 1 is always true:

if (1 == 1) { header("Location: index.php"); }
header("Location: http://www.google.com");

Yet the browser ends up on Google. The explanation is simple and it is one of the most common PHP redirect bugs: header() does not stop script execution. It only queues a raw HTTP response header, and the script keeps running to the end. Here both header() calls execute, the response carries two Location headers, and the last one wins — so off to Google you go.

And to correct my own 2008 guess: this is not a “client side command”. Headers are pure server-side HTTP; the browser simply obeys the last Location header it receives.

The fix: exit after the redirect

Treat header('Location: ...') and exit; as one atomic operation. If you want branching, be explicit about it:

if (1 == 1) {
    header("Location: index.php");
} else {
    header("Location: http://www.google.com");
}
exit;

This matters far beyond contrived examples. Any code placed after the redirect — database writes, emails, logging — still runs unless you stop the script. Most real-world “why did that insert happen twice” bugs trace back to a missing exit.

Headers must come before output

The other classic constraint: headers can only be sent before any body output. One stray character of HTML, whitespace after a closing ?> tag, or an echo, and you get the infamous Cannot modify header information – headers already sent warning. If you need to find where the output started, headers_sent($file, $line) tells you the exact file and line.

Other details worth knowing

  • header('Location: ...') sends a 302 Found status by default. For permanent moves pass the status explicitly: header('Location: ...', true, 301) — but be careful, browsers cache 301 redirects aggressively.
  • Relative Location values such as index.php are legal per the HTTP spec (RFC 9110). The old advice to always write absolute URLs is outdated.
  • Unless you are on a framework, there is no magic after header(): you own the exit;.
  • Modern frameworks give you a redirect helper that sets the status and Location header and returns a response object — return redirect('/index.php') in Laravel, $response->withStatus(302)->withHeader('Location', ...) in PSR-7 land. Use it and the exit problem disappears.

The full details live in the PHP manual page for header().

6 thoughts on “Header("Location") on PHP

  1. Pol DeNais says:

    Any ideas why the following line won’t work:

    header(‘Location: index.php? page=list-album’);

    but the following line does work as a test to see if Header works:

    header(‘location: index.html’)

    Reply
  2. worthposting says:

    use
    header(’Location: index.php?page=list-album’);

    without a space just before page

    Reply
  3. worthposting says:

    Maybe an invalid page Get variable somewhere redirects somewhere else.

    Reply
  4. worthposting says:

    Dont Forget that header(“Location: somewhere.html”); can only work when nothing else has been output to page.
    Place it above all.

    Error Suppression Can Hide the error message
    warning: Cannot modify header information – headers already sent by ….

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *