Redirecting users is a routine task — after a form submission, after login, when content moves. WordPress provides two functions for this: wp_redirect() and the safer wp_safe_redirect(). Knowing when to use each one matters.
Problem: How do you redirect users to another URL in WordPress without calling header() directly?
Solution: Use wp_redirect() for any URL or wp_safe_redirect() to restrict redirects to the same site — always call exit() immediately after to stop further script execution.
wp_redirect() sends any URL. wp_safe_redirect() restricts the destination to the same site (or a whitelist of allowed hosts), which prevents open redirect attacks:
// Redirect to an external URL (use sparingly)
wp_redirect( 'https://example.com', 302 );
exit;
// Redirect within the same site — safe by default
wp_safe_redirect( home_url( '/thank-you/' ), 302 );
exit;
// Permanent redirect (tells search engines the URL has moved)
wp_redirect( home_url( '/new-page/' ), 301 );
exit;
A common pattern — redirect non-logged-in users away from a protected page:
add_action( 'template_redirect', 'redirect_guests_from_dashboard' );
function redirect_guests_from_dashboard() {
if ( is_page( 'dashboard' ) && ! is_user_logged_in() ) {
wp_safe_redirect( wp_login_url( get_permalink() ) );
exit;
}
}
To allow additional external hosts with wp_safe_redirect():
add_filter( 'allowed_redirect_hosts', function( $hosts ) {
$hosts[] = 'app.example.com';
return $hosts;
} );
NOTE: Always call exit immediately after wp_redirect() or wp_safe_redirect(). Without it, PHP continues executing the current script even though the redirect header has been sent. Use template_redirect (not init) for page-level redirects to avoid interfering with AJAX and REST API requests.