Short answer: WordPress’s logout URL is
/wp-login.php?action=logout
, but hitting it directly shows an “Are you sure you want to log out?” interstitial because WordPress requires a nonce on logout to prevent CSRF attacks. The clean way to build a logout link is
wp_logout_url()
– a built-in function that returns the URL with a valid nonce attached. For a logout item in a menu, drop a Custom Link into Appearance > Menus and pass the output of
wp_logout_url()
through a small filter, or install a plugin like Nav Menu Roles that adds the logic for you.
That covers the immediate “how do I log a user out” question. The rest of this guide covers why the bare URL is not enough, the right way to build one, three patterns for adding logout to a menu, how to redirect after logout, the block-editor equivalent, and the common mistakes that produce broken logout links.
Why the bare URL is not enough#
You can find the raw URL by inspecting the admin bar’s logout link or constructing it by hand:
https://example.com/wp-login.php?action=logout
Hit it directly and WordPress shows an interstitial page that says “Are you sure you want to log out?” with a “log out” link to click through.
This is intentional, not a bug. WordPress requires a nonce – a single-use token that ties the request to your current session – before it will actually destroy the session. Without one, anyone with a link could log a user out by tricking them into clicking it (cross-site request forgery / CSRF). The interstitial is the fallback WordPress shows when a nonce is missing, so the user has to consciously click again to confirm.
A complete logout URL looks like this:
https://example.com/wp-login.php?action=logout&_wpnonce=a1b2c3d4e5
The
_wpnonce
value is regenerated every 12-24 hours per session, so you cannot hardcode it. You have to ask WordPress to build it for you – which is what
wp_logout_url()
does.
The wp_logout_url() function#
wp_logout_url()
is a built-in WordPress function that returns a complete logout URL with a valid nonce for the current user.
Basic call:
echo wp_logout_url();
This outputs something like
https://example.com/wp-login.php?action=logout&_wpnonce=a1b2c3d4e5
.
Optional first argument – where to redirect after logout:
echo wp_logout_url( home_url() );
The user is logged out and then redirected to your site’s home page. Without the argument, they land on the WordPress login screen with a “You are now logged out” message.
You can call
wp_logout_url()
from anywhere that runs during a WordPress request – theme template files, a shortcode callback, a code snippet plugin, a custom block, a menu walker. The function is part of WordPress core and is available on every site.
Adding a logout link to a menu#
This is the most common reason people look up the logout URL – they want a “Log out” item in their site’s navigation menu or header. WordPress’s Appearance > Menus screen accepts custom links, but a hardcoded
/wp-login.php?action=logout
URL produces the interstitial because there is no nonce attached. Three patterns work around this.
Pattern 1: Nav Menu Roles plugin (easiest)#
Install the Nav Menu Roles plugin from the WordPress repository. It does two useful things:
- Adds role-based visibility to menu items (show “Log out” only to logged-in users; show “Log in” only to logged-out users).
- Recognizes a few special menu URLs, including
#logout, and rewrites them to a properwp_logout_url()at render time.
To use it:
- Appearance > Menus.
- Add a Custom Link.
- Set URL to
#logout. Set Link Text to “Log out”. - Save.
- In the menu item’s options (expand the row), tick Logged In Users under “Display Mode” so the item only appears for authenticated visitors.
The plugin replaces
#logout
with a proper logout URL plus nonce when the menu renders. You also get a matching
#login
for the inverse case.
This is the path for non-developers – no theme edits, no code snippets, handles the nonce correctly.
Pattern 2: Custom Link + wp_nav_menu_objects filter (no plugin)#
If you do not want another plugin, you can do the same thing with a small snippet in your theme’s
functions.php
or a code snippet plugin:
add_filter( 'wp_nav_menu_objects', function( $items ) {
foreach ( $items as $item ) {
if ( $item->url === '#logout' ) {
$item->url = wp_logout_url( home_url() );
}
}
return $items;
});
Now any Custom Link in any menu with URL
#logout
is rewritten to a valid logout URL on render. Add as many as you want, in any menu. The redirect target (here
home_url()
) is up to you.
To also hide the item for logged-out users:
add_filter( 'wp_nav_menu_objects', function( $items ) {
foreach ( $items as $key => $item ) {
if ( $item->url === '#logout' ) {
if ( ! is_user_logged_in() ) {
unset( $items[ $key ] );
continue;
}
$item->url = wp_logout_url( home_url() );
}
}
return $items;
});
Pattern 3: Hardcoded URL with the interstitial (worst, but works)#
If you cannot run PHP and cannot install a plugin, you can still drop a Custom Link to
/wp-login.php?action=logout
directly. The user clicks it, sees the “Are you sure you want to log out?” page, clicks “log out”, and is signed out.
This is functional but ugly – two clicks instead of one and an unstyled WordPress page between them. Most sites avoid it.
Redirecting after logout#
There are two places to control where users land after logout:
The
wp_logout_url()
argument – per-link control:
echo wp_logout_url( home_url( '/goodbye' ) );
Each link can redirect somewhere different. Useful when a logout from the member area should land on
/members-goodbye
but a logout from the dashboard should land on
/
.
The
logout_redirect
filter – site-wide default:
add_filter( 'logout_redirect', function( $redirect_to, $requested_redirect_to, $user ) {
return home_url();
}, 10, 3 );
This fires after WordPress destroys the session, regardless of how the logout was triggered (URL, admin bar, plugin-driven). Useful for catching every logout path with one snippet.
Note: the
logout_redirect
filter only fires when WordPress’s own logout flow runs. It does not fire if a third-party plugin destroys the session some other way (e.g. via
wp_destroy_current_session()
followed by a custom redirect).
The block editor and FSE#
WordPress block themes and the Site Editor include a Login/out block (
wp:loginout
) that renders a Log in or Log out link automatically based on the user’s state. Drop it into any template (header, sidebar, footer) and it handles the URL, the nonce, the redirect, and the conditional display.
Attributes worth knowing:
- Display login as form – off by default. When on, the block renders an inline login form instead of a link. Logout still renders as a link.
- Redirect to current URL – the user lands back on the page they logged out from, instead of the WordPress login screen.
For a classic theme without FSE, the function-based path above (Pattern 1 or 2) is the equivalent.
How Hostney handles WordPress login and logout#
If you turn on SSO-only login in your WordPress install’s Security tab on Hostney, all
/wp-login.php
traffic is blocked at the nginx layer. Users get into wp-admin via a one-click SSO link from your Hostney control panel instead of typing a password into WordPress’s login form. This stops brute-force attacks against
/wp-login.php
entirely because the requests do not even reach WordPress.
The logout URL still works under SSO-only – WordPress’s logout POST is allowed through because it carries a valid nonce for an authenticated session. So
wp_logout_url()
and the menu patterns above behave the same way, whether or not SSO-only is enabled. The only difference is that after logout, the user lands on a “you are signed out” page instead of a re-login form, since the form would be unreachable anyway. If you also use Hostney’s Login telemetry (also on the Security tab), the logout itself does not show up in the per-IP telemetry log – that log tracks
wp-login.php
attempts, not session terminations.
Common mistakes#
- Hardcoding
/wp-login.php?action=logoutin a menu. The user sees the “Are you sure?” interstitial instead of being logged out cleanly. Usewp_logout_url()or a plugin that injects the nonce. - Assuming the nonce is permanent. Nonces expire every 12-24 hours. Caching the output of
wp_logout_url()in a static HTML file or a page cache means every visitor gets the same nonce, which is invalid for them – they will see the interstitial. Page caching plugins handle this correctly when the menu is rendered server-side; static-site generators that snapshot WordPress output do not. - Forgetting the role check on the menu item. A “Log out” link visible to logged-out visitors looks broken and tells search engine bots about a path they shouldn’t be hitting. Use the Nav Menu Roles plugin or a
is_user_logged_in()check. - Hardcoding the WordPress URL. On a Multisite network or any site with a non-default WordPress installation path,
wp-login.phpis not always at the site root. Always go throughwp_logout_url()orwp_login_url()– they callsite_url()internally and produce the right path. - Using the admin bar’s logout link as the only path. The admin bar is hidden for Subscriber-level users by default and entirely hidden on the front end of some themes. Subscribers and members on themes without an admin bar have no way to log out unless you provide one in the menu.
Frequently asked questions#
Does logging out destroy the session everywhere?#
By default, no. WordPress sessions are stored per-device – logging out on a laptop does not log you out on a phone. If you want to invalidate every session for a user, use the Log out everywhere else button on the user’s profile screen, or call
wp_destroy_other_sessions()
for the current user and
WP_Session_Tokens::get_instance($user_id)->destroy_all()
for any user.
Does logout invalidate application passwords?#
No. Application passwords are independent of session tokens – they authenticate API requests directly. Logging out a user does not affect any of their application passwords. To revoke them, the user goes to Users > Profile and revokes them one at a time, or you call
WP_Application_Passwords::delete_all_application_passwords($user_id)
.
How is logout different from a session simply expiring?#
Logout explicitly destroys the session token in
wp_usermeta
and clears the auth cookies. Session expiry just lets the cookie’s timestamp pass; the token remains in
wp_usermeta
until WordPress cleans it up on next login. Both produce the same “you are no longer logged in” state from the user’s perspective.
What is the difference between wp_logout() and the logout URL?#
wp_logout()
is the PHP function that actually destroys the session. The logout URL is the public-facing endpoint that calls
wp_logout()
when the nonce checks pass. If you are writing custom code that should log a user out (a plugin’s “delete my account” flow, an automatic logout on session timeout), call
wp_logout()
directly – you do not need the URL or the nonce.
Can I add a logout button to a shortcode?#
Yes:
add_shortcode( 'logout_link', function( $atts ) {
if ( ! is_user_logged_in() ) {
return '';
}
$atts = shortcode_atts( array( 'text' => 'Log out', 'redirect' => home_url() ), $atts );
return '<a href="' . esc_url( wp_logout_url( $atts['redirect'] ) ) . '">' . esc_html( $atts['text'] ) . '</a>';
});
Use it as
[logout_link]
or
[logout_link text="Sign out" redirect="/goodbye"]
in any post or page.
Summary#
The WordPress logout URL is
/wp-login.php?action=logout
, but the nonce requirement means you almost never use it directly. The right tools are:
-
wp_logout_url()for any custom code that needs a logout link. - Nav Menu Roles plugin (or a small
wp_nav_menu_objectsfilter) for menu integration. - The block editor’s Login/out block for FSE themes.
- The
logout_redirectfilter for site-wide post-logout behavior.
Most “broken” logout setups come from skipping the nonce – either by hardcoding the bare URL or by caching
wp_logout_url()
output past its expiry window. Use a function call, render the menu server-side, and the nonce takes care of itself.
If you are auditing your site’s auth surface more broadly, WordPress user roles and user management covers who has access to what, how to customize the WordPress dashboard covers what they see after they log in, and how to add and manage menus in WordPress covers the menu mechanics this guide builds on. Together they cover the full “logged in, doing something, logged out” path.