The standard PHP redirect sends a Location response header and then stops the script:
<?php
header('Location: /new-page.php');
exit;
This normally returns a temporary 302 Found response. The browser then requests /new-page.php. Use an explicit status code when the move is permanent, follows a form submission, or must preserve the original request method and body.
The correct PHP redirect syntax
PHP does not move a file or redirect by displaying a special page. It sends an HTTP response before the response body begins:
HTTP/1.1 302 Found
Location: /login.php
The client decides whether to follow that Location value. It may be an absolute URL or a site-relative path such as /login.php. PHP’s syntax is:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
header(string $header, bool $replace = true, int $response_code = 0);
- The first argument is the header, normally
Location: .... - The second controls replacement of an existing header of the same type.
- The third explicitly sets the HTTP status.
Put the call before any HTML, echo, debugging output, included template output, warning, or accidental whitespace. A UTF-8 byte-order mark before <?php can also count as output. The PHP manual documents this requirement and the special handling of Location headers at php.net.
header() alone does not stop PHP execution. Always terminate the redirect branch with exit; (or die;) so later code cannot change state or expose a response that the browser will not see.
Choose the right redirect status
| Status | Meaning | Typical use | Method and body |
|---|---|---|---|
301 |
Permanently moved | Permanent page or URL migration | Some clients historically change non-GET requests to GET |
302 |
Found; temporary | Ordinary temporary browser navigation; PHP’s usual Location default |
Non-GET behavior can vary |
303 |
See Other | Post/Redirect/Get after a successful form or other operation | Follow-up request is GET |
307 |
Temporary Redirect | Temporary routing that must preserve an upload or API request | Preserves method and body |
308 |
Permanent Redirect | Permanent routing where method preservation matters | Preserves method and body |
Use 301 for a permanent ordinary page move, or 308 when a non-GET method must remain unchanged. Use 302 for a temporary ordinary navigation, 303 when an action should lead to a new page fetched with GET, and 307 when the destination must receive the same method and body. A 307 or 308 can repeat a non-idempotent operation, so do not select one casually. Definitions and method rules are summarized by MDN’s redirection guide and its HTTP status reference.
Explicit examples
<?php
// Temporary navigation
header('Location: /home.php', true, 302);
exit;
// Permanent ordinary page move
header('Location: /new-page.php', true, 301);
exit;
// Temporary redirect that preserves method and body
header('Location: https://api.example.com/process', true, 307);
exit;
Google recommends a permanent server-side redirect such as 301 or 308 when a URL has permanently moved and the new URL should replace the old one in search results; it does not guarantee a particular ranking outcome. See Google’s redirect guidance.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Redirect after a form submission
Use the Post/Redirect/Get pattern so refreshing the result page does not submit the form again:
Rank #2
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Validate input, save data, and set any session message.
header('Location: /thank-you.php', true, 303);
exit;
}
303 deliberately changes the follow-up request to GET. Choose 307 instead only when the destination must receive the original method and body again.
Redirect conditionally for login or application logic
<?php
session_start();
if (empty($_SESSION['user_id'])) {
header('Location: /login.php', true, 302);
exit;
}
// Protected code runs only for an authenticated session.
A browser user can be sent to a login page, but an API normally should return an appropriate 401 or 403 response instead of an HTML login redirect.
Safely preserving a return path
Never place an unchecked destination in Location. Keep the value local (or use an allowlist) to prevent an open redirect that can support phishing:
Recommended Free Tools
<?php
$next = $_GET['next'] ?? '/dashboard.php';
if (
!is_string($next) ||
$next === '' ||
$next[0] !== '/' ||
str_starts_with($next, '//')
) {
$next = '/dashboard.php';
}
header(
'/login.php?next=' . rawurlencode($next),
true,
302
);
exit;
For sensitive applications, an allowlist of known internal paths is stronger than accepting arbitrary local paths.
Add query parameters correctly
Encode each value, or let http_build_query() construct the query string:
<?php
$userId = 42;
header('/profile.php?id=' . rawurlencode((string) $userId), true, 302);
exit;
<?php
$query = http_build_query([
'status' => 'success',
'id' => 42,
]);
header('/result.php?' . $query, true, 303);
exit;
Do not concatenate raw user input into a header. Validate destinations, encode parameter values, use HTTPS for sensitive destinations, and never put credentials or access tokens in a redirect URL.
Redirect to another domain
<?php
header('Location: https://www.example.com/', true, 302);
exit;
External destinations should use an absolute HTTPS URL. If a user chooses the destination, map a short key to approved URLs rather than trusting a submitted URL:
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitches<?php
$allowed = [
'docs' => 'https://docs.example.com/',
'support' => 'https://support.example.com/',
];
$key = $_GET['site'] ?? '';
$destination = $allowed[$key] ?? '/';
header('Location: ' . $destination, true, 302);
exit;
filter_var($url, FILTER_VALIDATE_URL) checks syntax, not whether the host is trusted. Do not build redirects from an unvalidated Host header.
Fix “headers already sent”
The error Cannot modify header information - headers already sent means PHP began sending output before the redirect. Typical causes include:
- HTML,
echo,print, or debugging output beforeheader(). - Whitespace outside PHP tags or a UTF-8 BOM in an included file.
- A warning, notice, or template that emitted output.
- Redirect code placed after rendering has started.
Move the redirect decision earlier and remove the premature output:
Rank #4
<?php
if ($completed) {
header('Location: /done.php', true, 303);
exit;
}
echo 'Processing...';
For diagnostics, PHP can report whether headers have been sent and where output began:
<?php
if (headers_sent($file, $line)) {
error_log("Headers already sent in $file on line $line");
}
var_dump(headers_list());
Output buffering may defer output in some configurations, but it is not the dependable fix; find and remove the source of premature output.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Test the actual response
- Open browser developer tools, reload the original URL, and inspect the Network entry for its status and
Locationheader. - Inspect every hop with
curl:
curl -i https://example.com/old-page.php
curl -IL https://example.com/old-page.php
The response should show the expected status and location, for example:
HTTP/2 301
location: https://example.com/new-page.php
To inspect a POST response without automatically following it:
curl -i -X POST https://example.com/submit.php
Use curl -L when you want the final response after following redirects, not when you need to inspect each individual hop. Confirm that the destination returns the expected final status and that no unnecessary chain exists.
Prevent redirect loops and chains
Loops commonly arise when an old and new route point at each other, HTTP-to-HTTPS rules conflict, a login guard protects the login page, trailing-slash rules disagree with framework routes, or a reverse proxy causes PHP to misread the original scheme. A proxy that terminates TLS must be configured so the application can trust the correct forwarded scheme.
Run curl -IL and inspect every hop. Global canonical-host, HTTP-to-HTTPS, and large migration rules are usually safer as one server- or proxy-level rule rather than several application redirects.
PHP versus Apache or Nginx redirects
Use PHP when the destination depends on a session, role, database record, or form result. Use Apache, Nginx, a load balancer, or a CDN when a rule applies to every request and can run before PHP starts, such as HTTP-to-HTTPS, host canonicalization, or a static path migration.
Apache
Redirect 301 /old-page https://example.com/new-page
Nginx
server {
listen 80;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
MDN covers Apache Redirect/mod_rewrite and Nginx return/rewrite alternatives at its redirection guide. Nginx’s redirect and rewrite behavior is documented at nginx.org.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Common mistakes to avoid
- Omitting
exit;after a conditional redirect. - Calling
header()after output has begun. - Using
301for a temporary test, then being confused by cached behavior. - Using
302for a permanent migration. - Using
302or301when method preservation is required, instead of307or308. - Using a method-preserving redirect after an operation that must not be repeated.
- Trusting a user-supplied URL or raw query value.
- Creating redirect chains, loops, or a PHP rule for a site-wide server concern.
- Replacing an available HTTP redirect with JavaScript or a meta refresh. Those alternatives require the original page to load, may fail with JavaScript disabled, and provide weaker semantics for crawlers and clients.
Frequently Asked Questions
Can PHP redirect to another domain?
Yes. Send an absolute HTTPS URL in the Location header, and use an allowlist when the destination is selected by a user or request parameter.
Does header() stop PHP execution?
No. It sends the response header; add exit; immediately to stop the current script.
Can I redirect before ?
Yes. The redirect must be issued before any output, including the doctype, whitespace, warnings, or included template content.
Can I redirect to a URL without a .php extension?
Yes. The destination can be any valid relative path or absolute URL handled by your server or application.
Free tools Windows power users keep installed
One-click scans. No signup required.
Quick Recap
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.

