How do I make a redirect in PHP?

3,360,619

Solution 1

Summary of existing answers plus my own two cents:

1. Basic answer

You can use the header() function to send a new HTTP header, but this must be sent to the browser before any HTML or text (so before the <!DOCTYPE ...> declaration, for example).

header('Location: '.$newURL);

2. Important details

die() or exit()

header("Location: https://example.com/myOtherPage.php");
die();

Why you should use die() or exit(): The Daily WTF

Absolute or relative URL

Since June 2014 both absolute and relative URLs can be used. See RFC 7231 which had replaced the old RFC 2616, where only absolute URLs were allowed.

Status Codes

PHP's "Location"-header still uses the HTTP 302-redirect code, this is a "temporary" redirect and may not be the one you should use. You should consider either 301 (permanent redirect) or 303 (other).

Note: W3C mentions that the 303-header is incompatible with "many pre-HTTP/1.1 user agents. Currently used browsers are all HTTP/1.1 user agents. This is not true for many other user agents like spiders and robots.

3. Documentation

HTTP Headers and the header() function in PHP

4. Alternatives

You may use the alternative method of http_redirect($url); which needs the PECL package pecl to be installed.

5. Helper Functions

This function doesn't incorporate the 303 status code:

function Redirect($url, $permanent = false)
{
    header('Location: ' . $url, true, $permanent ? 301 : 302);

    exit();
}

Redirect('https://example.com/', false);

This is more flexible:

function redirect($url, $statusCode = 303)
{
   header('Location: ' . $url, true, $statusCode);
   die();
}

6. Workaround

As mentioned header() redirects only work before anything is written out. They usually fail if invoked inmidst HTML output. Then you might use a HTML header workaround (not very professional!) like:

 <meta http-equiv="refresh" content="0;url=finalpage.html">

Or a JavaScript redirect even.

window.location.replace("https://example.com/");

Solution 2

Use the header() function to send an HTTP Location header:

header('Location: '.$newURL);

Contrary to what some think, die() has nothing to do with redirection. Use it only if you want to redirect instead of normal execution.

File example.php:

<?php
    header('Location: static.html');
    $fh = fopen('/tmp/track.txt', 'a');
    fwrite($fh, $_SERVER['REMOTE_ADDR'] . ' ' . date('c') . "\n");
    fclose($fh);
?>

Result of three executions:

bart@hal9k:~> cat /tmp/track.txt
127.0.0.1 2009-04-21T09:50:02+02:00
127.0.0.1 2009-04-21T09:50:05+02:00
127.0.0.1 2009-04-21T09:50:08+02:00

Resuming — obligatory die()/exit() is some urban legend that has nothing to do with actual PHP. It has nothing to do with client "respecting" the Location: header. Sending a header does not stop PHP execution, regardless of the client used.

Solution 3

function Redirect($url, $permanent = false)
{
    if (headers_sent() === false)
    {
        header('Location: ' . $url, true, ($permanent === true) ? 301 : 302);
    }

    exit();
}

Redirect('http://www.google.com/', false);

Don't forget to die() / exit() !

Solution 4

Output JavaScript from PHP using echo, which will do the job.

echo '<script type="text/javascript">
           window.location = "http://www.google.com/"
      </script>';

You can't really do it in PHP unless you buffer the page output and then later check for redirect condition. That might be too much of a hassle. Remember that headers are the first thing that is sent from the page. Most of the redirect is usually required later in the page. For that you have to buffer all the output of the page and check for redirect condition later. At that point you can either redirect page user header() or simply echo the buffered output.

For more about buffering (advantages)

What is output buffering?

Solution 5

1. Without header

here you will not face any problem

 <?php echo "<script>location.href='target-page.php';</script>"; ?>

2. Using header function with exit()

<?php 
     header('Location: target-page.php');
     exit();
?>

but if you use header function then some times you will get "warning like header already send" to resolve that do not echo or print before sending headers or you can simply use die() or exit() after header function.

3. Using header function with ob_start() and ob_end_flush()

<?php
ob_start(); //this should be first line of your page
header('Location: target-page.php');
ob_end_flush(); //this should be last line of your page
?>
Share:
3,360,619
Sam
Author by

Sam

I'm an A+ Certified, Net+ Certified technician that is interested in programming because it's just so much better. ;]

Updated on January 04, 2022

Comments

  • Sam
    Sam over 2 years

    Is it possible to redirect a user to a different page through the use of PHP?

    Say the user goes to www.example.com/page.php and I want to redirect them to www.example.com/index.php, how would I do so without the use of a meta refresh? Is it possible?

    This could even protect my pages from unauthorized users.

    • Zack Marrapese
      Zack Marrapese about 15 years
      You can update the header in PHP: header
    • Strae
      Strae about 13 years
      @Sam: just as side node, do not implement any kind of protection from unauthorized users via redirect; this is not how things should be done ;)
    • Admin
      Admin almost 11 years
      @Strae What's wrong with protecting pages with redirect ? Then what's the best way ?
    • Strae
      Strae almost 11 years
      @PravindaAmarathunga redirect is one of the elements, but not the only one. Just be sure that protected elements doesnt get outputted at all for unauthorized users; Browser's redirect can be disabled client-side, for example: if the browser doesnt do the redirect and the original page get outputted as normal, what would the user see? CMS usually do the redirect and doesnt print out protected items, replacing the normal output with a courtesy message.
    • Strae
      Strae almost 11 years
      @PravindaAmarathunga check the link from markus's answer: thedailywtf.com/Articles/WellIntentioned-Destruction.aspx
    • P Whittaker
      P Whittaker over 2 years
      Problem solved - it should have been $options = array('http' => array('method'=>"GET", 'header' => array("Cookie: " . $_SERVER["HTTP_COOKIE"], "Authorization: Basic " . base64_encode("$username:$password")) ) );
  • Kuroki Kaze
    Kuroki Kaze about 15 years
    And don't forget output buffering or you'll end up with 'Headers already sent'.
  • Strae
    Strae about 15 years
    ... and dont forget th print out somthign like "you'll be redirected to $nepage in $n seconds, click $link here if redirect dont happen" Some broser, and some browser's settings, may fail that redirect.
  • Strae
    Strae about 15 years
    What's about give some output to the user before kill the script? You know, people love to know what is happenin...
  • rmeador
    rmeador about 15 years
    @DaNieL: this type of redirect won't take "$n seconds". It will be instant if it happens at all, and any conforming browser should handle it. I think you're thinking of the "meta refresh" redirects that people use when they don't know any better.
  • Andrew Moore
    Andrew Moore about 15 years
    @rmeador... For older browsers and speciality browsers. You should first do your Location header, if fails have a meta-redirect with the "you'll be redirected to page in x seconds" with a link in case the meta-redirect fails. That's the proper and fail-safe way of doing a redirect.
  • nickf
    nickf about 15 years
    @DaNieL: change it to die("Stop ignoring my headers!")
  • Szabolcs Dézsi
    Szabolcs Dézsi about 15 years
    die() or exit() is for clients who don't respect the "Location: ..." header
  • vartec
    vartec about 15 years
    Andrew: how can HTTP browser not respect Location:?
  • markus
    markus about 15 years
    does not incorporate the 303 status.
  • Alix Axel
    Alix Axel almost 15 years
    @Kuroki Kaze: You won't end up with 'Headers already sent' because of the headers_sent() check.
  • Chuck Le Butt
    Chuck Le Butt about 13 years
    Some problems with this answer: 303 may not be the "correct" status code. 301 may be desired for Google, for example. Secondly, header('Location: '.$newURL); must be before any HTML (or text) has been passed to the browser, or it will not work correctly.
  • Alix Axel
    Alix Axel about 11 years
    @clawr: No, exit() is to prevent the page from showing up the remaining content (think restricted pages). vartec is right, it has nothing to do with the HTTP Location header and you don't need to exit. I chose to include it in my answer because, for someone who doesn't know how to do a simple redirect, one might as well play safe rather than not implement a simple yet crucial step just so he is able to take advantage of advanced process control.
  • josh
    josh over 10 years
    but you need to do it before you've sent any other output to the browser. Awesome!! Been searching for minutes on why I kept receiving the headers already sent error. +1!!
  • MarioVilas
    MarioVilas about 10 years
    @vartec It doesn't have to be a browser, it could be a spider or a malicious user.
  • MarioVilas
    MarioVilas about 10 years
    Also, if the new URL is built by concatenating user input, some sanitization is in order. :)
  • robertodecurnex
    robertodecurnex almost 10 years
    The daily WTF story is a common one, sadly. Anyway, it's not the missing die what cause the problem but a bad design. Shutting the process violently is wrong in 99.9% of the cases. A common, cleaner solution (not my favourite anyways) is to throw a RedirectionException and catch it on you application entry point. After that you can have all your "after *" calls (logs/close connections/what ever)
  • Timo002
    Timo002 almost 10 years
    The http-equiv="Location" is not supported by all browsers. You should use refresh instead! <meta http-equiv="refresh" content="0;url=http://example.com/">
  • madumlao
    madumlao over 9 years
    Never issue a 301 unless you mean it. 301 means permanent, and permanent means permanent, meaning it will be cached by user agents, meaning long, caffeine-filled nights staring at application logs wondering if you're going insane because you swear some page should have been called or updated and you swear to God it works on your machine but not the client's. If you absolutely must call a 301, put a cache-control max-age on the resource. You don't have infinite wisdom and you shouldn't be acting like you do.
  • ars265
    ars265 over 9 years
    But is there a reason to use die over exit? exit seems cleaner and more appropriate.
  • Christopher Schultz
    Christopher Schultz about 9 years
    A note about PECL: PECL 2.x does not include http_redirect for some reason, so betting on http_redirect might be a mistake in the long-run.
  • Nick Humphrey
    Nick Humphrey about 9 years
    commenter @tgape in the WTF story says "exit()" should be used instead of "die()": <<If there is a die immediately after a header redirect, the code will always hit it, and your error logs will fill up with useless "errors">>
  • TheBlackBenzKid
    TheBlackBenzKid about 9 years
    I liked that simple explanation of die(); you gave - if you dont do it the user may see the complete page for a moment if you do use it; the user will be redirected and no temporary content glitch will show + 1
  • chharvey
    chharvey almost 9 years
    Javascript runs on the client which may or may not be what you're looking for.
  • Stathis Andronikos
    Stathis Andronikos about 8 years
    Simple and to the point answer! Great for a simple page redirection!
  • rhavendc
    rhavendc about 8 years
    I'm wondering why all these codes are working fine in my localhost but failing when the system is up in a hosting site.. hmm..
  • Avatar
    Avatar almost 8 years
    And that way you do not run into the common Cannot modify header information - headers already sent by error.
  • MauganRa
    MauganRa over 7 years
    @MarioVilas why is a spider or a malicious user a problem? If the intention is to lead a visitor away from a confidential part of the site, then the app's design is quite flawed already...
  • MauganRa
    MauganRa over 7 years
    More general, you have /stop your script completely/. die() is just one way to do that.
  • dpa
    dpa over 7 years
    6 solution is useful when need track redirects with client side tracking scripts, eg. google analytics.
  • Tanner Summers
    Tanner Summers over 7 years
    why do we need the exit() or die()?
  • kris
    kris over 7 years
    +1 for the Absolute URL information - that was causing my redirect to fail silently on chrome (well, actually I was missing "http://", but that pointed me in that direction).
  • Mahdi Jazini
    Mahdi Jazini over 7 years
    don't forget to add header("Cache-Control: no-cache"); before the line
  • EKanadily
    EKanadily over 7 years
    exit() should be used immediately after the header()
  • EKanadily
    EKanadily over 7 years
    exit() should be used immediately after the header() . also out buffering has been automatically on by default for some time now.
  • Bhaskar Pramanik
    Bhaskar Pramanik over 7 years
    @docesam .. agreed .. exit() should be immediately called after header() call. However I feel, if there is no more output to browser after this header() statement, exit() may not be necessary - Just my opinion
  • EKanadily
    EKanadily over 7 years
    yes but you have to explain that because someone could copy your line of code to his script and that can potentially cause long times of circling around himself figuring out what went wrong.
  • FrancescoMM
    FrancescoMM over 7 years
    But browsers that respect the header will leave the page and close the connection while your script is still executing. This is totally bad. PHP will go on with the script for some time (that's why your code executes) but may abort it randomly in the middle of execution, leaving stuff broken. Calling ignore_user_abort() will prevent this, but sincerely I it's not worth it. Just go on with your HTML writing stuff (though probably useless) but don't do stuff that writes on disk or database after a header('Location:'); Write to disk before the redirect if possible. [Also: url should be absolute.]
  • Patrick Hund
    Patrick Hund about 7 years
    There is already an answer that has 1085 that contains the info you provide, plus much more.
  • RozzA
    RozzA almost 7 years
    I combined the header solution & using the die( "echo here" ) command to echo out meta refresh tag & all of the valid js solutions, should have me a pretty compatible little redirector!
  • Istiaque Ahmed
    Istiaque Ahmed almost 7 years
    @hmd, what if javascript is disabled ?
  • Hammad Khan
    Hammad Khan almost 7 years
    @IstiaqueAhmed javascript is almost always enabled these days but if it it is disabled then you can use PHP buffer. This SO question answers that. If you are using PHP Buffering then you dont need this method I gueess.
  • DanAllen
    DanAllen over 6 years
    It is possible to have useful activity occur after the header is sent, activity that sends nothing to the browser, but logs the activity or finishes recording transactions. For this reason, the need for die/exit is depends on the script.
  • DanAllen
    DanAllen over 6 years
    I keep reading that sending a header in the midst of html streaming out will generate the "cannot modify header" error, but I have not seen that in awhile now. I have even cookies accepted by a browser after html has started running into it. I just setup up codepen with 150 lines of html interrupted by a header sent by php. I can't find any notice if a problem either in the php error log or Chrome inspector. codepen.io/danallenhtn/pen/ooGWgd
  • www139
    www139 over 6 years
    Could you explain the function of your code? Your answer was flagged because of its length and content.
  • Scriptman
    Scriptman over 6 years
    What is this? Please don't use links to your own website. And the second example uses javascript redirect, and not the PHP header() function.
  • aswzen
    aswzen over 6 years
    @BhaskarPramanik imagine you have to lock a door quickly, but then you have to pull/push/smash them again to make sure if it already locked or not..
  • Doktor J
    Doktor J about 6 years
    @DanAllen you may have output buffering on; since it's not actually outputting the data to the client as the code runs, it hits the header() call and tacks that on before flushing the buffer to the client.
  • MestreLion
    MestreLion almost 6 years
    @TannerSummers: so no more processing is done on PHP and no content is displayed to the user. The former is potentially harmful (deleting records, etc) and hard to debug
  • MestreLion
    MestreLion almost 6 years
    False, you can (and should) do it in PHP even without buffering: in a well-designed page all relevant PHP processing should take place before any HTML content is sent to the user. That way PHP redirects will work fine.
  • The Godfather
    The Godfather almost 6 years
    Since July 2014 relative URLs are allowed in Location header. See recent update in answer stackoverflow.com/a/25643550/1657819 (refer tools.ietf.org/html/rfc7231#section-7.1.2)
  • Ari Waisberg
    Ari Waisberg almost 6 years
    wtf??? the crawler can read php code??? I thought they read html and js... but if reads php means he is inside your server, that's not a crawler thats a virus and you have to worry a lot more than a "redirect"... I'm surprise none note this...
  • Peter Mortensen
    Peter Mortensen over 5 years
    Why (near the end of the second paragraph)? Do you mean &para instead (so the whole reads mypage.php?param1=val1&param2=val2))? (The HTML entity para) is "¶" - perhaps some external program did a conversion?).
  • DoctorDroid Haiti
    DoctorDroid Haiti about 5 years
    Work like a charm. I use <?php echo "<script>location.href='google.fr/';</script>"; ?> To test it , and it did what i wanted
  • Ehsan88
    Ehsan88 about 5 years
    I agree with @robertodecurnex. The problem with The Daily WTF story is that it uses redirection to prevent an unauthorized user from doing a deletion. That's an absolutely bad design. You should never rely on redirection to prevent anything.
  • Jason
    Jason about 5 years
    If you are doing this in a framework, then die() or exit() is probably the last thing you should do. Check how you should exit cleanly from the framework so that it has a chance to log things, clean up, close files etc. Of course a framework will probably already have a helper function or method to do a redirect, but I'm mentioning this as it is good to not get into the habit of just doing an exit() without thinking about the consequences in the application.
  • oldboy
    oldboy almost 5 years
    is there any way to redirect before the browser detects the HTTP protocol? the reason i need to redirect is because i cannot get enough SSL certificates for all of my domains. i'd use .htaccess to redirect, but i need a way to somehow pass on which domain redirected to the final domain?
  • oldboy
    oldboy almost 5 years
    is there any way to redirect before the browser detects the HTTP protocol? the reason i need to redirect is because i cannot get enough SSL certificates for all of my domains. i'd use .htaccess to redirect, but i need a way to somehow pass on which domain redirected to the final domain?
  • oldboy
    oldboy almost 5 years
    is there any way to redirect before the browser detects the HTTP protocol? the reason i need to redirect is because i cannot get enough SSL certificates for all of my domains. i'd use .htaccess to redirect, but i need a way to somehow pass on which domain redirected to the final domain?
  • cdsaenz
    cdsaenz about 4 years
    The javascript bit somehow was the only thing that was working in the final hosting of the site; I believe it's a matter of caching but with that I solved it right away.
  • Jsowa
    Jsowa about 4 years
    There are already plenty of solutions. Your solution has mixed HTML and PHP without PHP tags. Secondly you send header after printing html code, so it will not work. And name of example files are bad. You shouldn't named them A.php and B.php. I know that is only example, but still you should care about naming convention.
  • clockw0rk
    clockw0rk about 4 years
    javascript is not automatically activated, in fact this only holds true for modern browsers. also, the question was about php, not JS
  • miken32
    miken32 over 3 years
    Yeah this is an answer to a completely different question. You have no control over the client side, and it's dangerous to assume you do.
  • miken32
    miken32 over 3 years
    For the record, that article is nonsense. The problem there was design that used GET requests to effect a change on the server, which is a HUGE no-no.
  • MindRoasterMir
    MindRoasterMir over 3 years
    it works only as the first statement in code. If you have logic and redirect is based on that. use meta http-equiv refresh or window.open javascript than. (copied)
  • bdsl
    bdsl about 3 years
    It doesn't have to be the first statement in the code. It just has to before any output. Organise your code to do all logic before it starts printing output - then probably it should print the prepared output all in one go.