How to secure the WordPress login
Short answer: give every administrator a unique, long password and two-factor authentication, limit how many login attempts one address can make, and remove admin accounts nobody uses. WordPress core doesn’t limit login attempts by itself, so add a limit at your web server, CDN or with a plugin. Renaming the login URL alone isn’t protection.
Quick steps
- Clean up admin accounts. Remove unused administrators and give the rest the lowest role that works.
- Turn on two-factor login. Use a TOTP app with backup codes for every administrator and editor.
- Rate-limit wp-login.php. Limit attempts per IP address at the server, the CDN or with a plugin.
- Restrict or close extra doors. Block XML-RPC if unused and review application passwords.
- Log out stolen sessions. After any suspicion, change the secret keys so every session ends.
Why the login page is the front door
Bots try common and leaked passwords against /wp-login.php and /xmlrpc.php all day on almost every WordPress site. Most succeed not by cleverness but because a password was reused on another site that leaked. One stolen administrator password is enough to install a malicious plugin, so the login deserves several layers.
1. Clean up administrator accounts
List everyone with full control and remove or downgrade anyone who doesn’t need it. Content writers rarely need more than the Editor or Author role.
wp user list --role=administrator --fields=ID,user_login,user_email,user_registeredEach person gets their own account (no shared “admin” login) and a long, unique password from a password manager. If your site still has a user literally called admin, create a new administrator, move the content to it and delete the old one.
2. Turn on two-factor authentication
Two-factor login stops most stolen-password attacks, because the attacker also needs a code from the user’s phone. The free Two Factor plugin from the WordPress.org plugin directory supports authenticator apps (TOTP), email codes and backup codes. Install it, then each user turns it on under Users → Profile. Prefer an authenticator app over email codes, give users their backup codes, and require it for every administrator and editor. Many security suites offer the same feature if you already use one.
3. Limit login attempts
WordPress core doesn’t limit failed logins, so bots can try indefinitely. The best place to stop them is before PHP runs. On nginx, a rate limit on the login page lets real users through and slows bots down:
# in the http { } block
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=10r/m;
# in the server { } block, above your general PHP location
location = /wp-login.php {
limit_req zone=wplogin burst=5 nodelay;
limit_req_status 429;
# then the same fastcgi lines as in your location ~ \.php$ block, e.g.:
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php-fpm.sock;
}Test it on your own site; after a handful of fast requests you should see 429:
for i in $(seq 1 20); do curl -s -o /dev/null -w '%{http_code} ' -X POST https://yourdomain.com/wp-login.php; done; echoBehind Cloudflare, a rate-limiting rule for the path /wp-login.php does the same at the edge. On shared hosting without server access, a reputable “limit login attempts” plugin is the practical choice.
4. Allow the login only from known addresses (optional)
If everyone who logs in works from fixed IP addresses, you can close the login page to everyone else. On Apache 2.4, in .htaccess:
<Files "wp-login.php">
Require ip 203.0.113.10 198.51.100.0/24
</Files>Don’t block /wp-admin/admin-ajax.php: many themes and plugins use it for visitors. Skip this step if your team logs in from changing networks or if customers log in to a store; use 2FA and rate limiting instead.
5. Close the other doors
XML-RPC is an older remote API that also accepts passwords. If you don’t use the WordPress mobile app or Jetpack, block it as described in the WordPress hardening checklist. Application passwords let external tools use the REST API; review them under Users → Profile and revoke any you don’t recognise. If nothing uses them, turn the feature off with a small must-use plugin:
<?php
// wp-content/mu-plugins/no-app-passwords.php
add_filter( 'wp_is_application_passwords_available', '__return_false' );6. If you suspect a stolen password
Change the password, then replace the secret keys in wp-config.php. That logs out every session on every device, including an attacker’s:
wp config shuffle-saltsThen check for administrators or plugins you didn’t add, as described in How to tell if your WordPress site is hacked.
What about hiding the login URL?
Moving wp-login.php to a secret address cuts bot noise in your logs, but it isn’t protection: the address leaks through links and plugins, and it does nothing against a leaked password. Use it as an extra, after 2FA and rate limiting.
What HackGrade checks
The free scan flags usernames that WordPress lists publicly, an open XML-RPC endpoint, and outdated WordPress core, plugins and themes with known vulnerabilities. It never tries to guess passwords, not even in the deep scan.
Frequently asked questions
Does WordPress limit login attempts by default?
No. WordPress core doesn’t limit failed logins. Add a limit at the web server, at your CDN, or with a plugin.
Which two-factor method should I use for WordPress?
An authenticator app (TOTP) with saved backup codes. Email codes are better than nothing, but anyone who gets into the mailbox gets the code too.
Should I change the wp-admin URL?
It reduces bot noise but doesn’t stop a determined attacker or a leaked password. Do it only in addition to 2FA and rate limiting.
Will rate limiting lock out my customers?
Not with a sensible limit such as 10 attempts a minute with a small burst. Real people rarely log in more than a few times a minute.