Redirect code generator
Type the old address and the new one, choose the status, and decide what happens to the visitor's query string and a trailing slash. Copy the version for your server.
This tool needs JavaScript. Everything it does runs in your browser — nothing you type is sent anywhere.
Every snippet here was run on a real Apache, nginx, PHP and Symfony server before this page was published. Nothing you type leaves your browser.
Which status to use
| Status | Meaning | Use it when |
|---|---|---|
| 301 | Moved permanently | A page has a new address for good. Search engines move the old address's standing to the new one. |
| 302 | Found, temporarily | The old address will come back: a sale page, a maintenance notice. |
| 307 | Temporary, method kept | As 302, for an address that receives form posts or API calls. |
| 308 | Permanent, method kept | As 301, for an address that receives form posts or API calls. |
A browser following a 301 or 302 may turn a POST into a GET, so a form submitted to the old address arrives at the new one empty. 307 and 308 forbid that. For an ordinary page nobody posts to, 301 is the answer.
The two choices this generator will not guess
The visitor's query string. A link to /old-page/?ref=newsletter
can arrive at the new page with ?ref=newsletter or without it. Passing
it on keeps campaign tracking working; dropping it is right when the old
parameters mean nothing to the new page. Apache and nginx can do either.
Symfony's built-in redirect cannot choose: it always passes the query
string on to a path on the same site and never to a full https://
address, and the generator says so rather than writing a route that does
the opposite of what you asked.
The trailing slash. /old-page and /old-page/ are different
addresses to a server. "Match with or without" redirects both, which is
almost always what you want after a migration, because old links exist in
both forms.
How to redirect a page in PHP
Send the Location header before anything else is output, then stop the
script:
<?php
header('Location: /new-page/', true, 301);
exit;
The third argument of header() is the status; leave it out and PHP
sends a 302, which tells search engines the move is temporary. The
exit matters: without it the rest of the old page still runs, and
anything it does, such as writing to a database, still happens. If PHP
says headers were already sent, something was output first: often a
blank line or a byte-order mark before the opening <?php.
Where each snippet goes
- .htaccess: the file in the folder the old address lives under, usually the site root, above any WordPress or framework block that would otherwise catch the request first.
- nginx: inside the
server { }block for the site, thennginx -tto check it andnginx -s reloadto apply it. - PHP: at the very top of the script the old address runs, or of the front controller if every request goes through one.
- Symfony: in
config/routes.yaml.php bin/console debug:routerlists it once it is loaded.