To secure the WordPress login page, stack seven protections in this order: long, unique passwords, two-factor authentication for every account that publishes or administers, a cap on login attempts, a login URL that is no longer wp-login.php, XML-RPC switched off, usernames nobody can guess, and finally a login log. Each one blocks a different attack; none is enough on its own. This guide gives you the order of priority, the right settings for each type of site and how to avoid locking yourself out.
We have already written a dedicated article on each measure. This one is the big picture: where to start, what to combine and what to skip depending on your site.
Why the login is the most attacked door
The login form is identical on every WordPress site, at the same URL, and WordPress does not limit login attempts by default. A brute force bot therefore needs no research at all: it sends username and password pairs taken from dictionaries or data breaches, thousands of times a day. It is not targeting your site in particular, it is targeting every site.
The login does not have just one door. Here are the entry points bots try, and the defence that closes each one:
| Entry point | What the bot tries | Main defence |
|---|---|---|
wp-login.php | Password guesses in a row | Attempt limiting, 2FA, moved URL |
xmlrpc.php | Hundreds of guesses per request (system.multicall) | Turn off XML-RPC |
/?author=1, /wp-json/wp/v2/users | Harvesting usernames | Hide authors |
| Lost password | Flooding inboxes, testing email addresses | Limiting, moved URL |
| Application passwords | Bypassing 2FA through the API | Turn them off if you don’t use them |
The seven measures, in order of priority
The order follows the ratio between effort and risk avoided. The first two protect you even against an attacker who knows your login URL and your username; the others cut the volume of attacks and what bots learn about your site.
| Measure | Blocks | Effort | Priority |
|---|---|---|---|
| Long, unique passwords | Dictionaries, leaks | Low | 1 |
| Two-factor authentication | Stolen or guessed password | Medium | 1 |
| Attempt limiting | Repeated brute force | Low | 2 |
| Moved login URL | Generic bots, noise | Low | 2 |
| XML-RPC turned off | Batched guesses | Low | 2 |
| Hidden usernames | Account discovery | Low | 3 |
| Login log | Attacks that go unnoticed | Low | 3 |

1. Long, unique passwords that are never reused
NIST, in its SP 800-63B guideline revised in 2025, asks for at least 15 characters for a password used on its own, no forced composition rules, and a check against lists of already leaked passwords. Reuse is the real danger: a password that leaked somewhere else will be tried on your site, which is credential stuffing. A password manager solves the problem for the whole team. Since WordPress 6.8, passwords are stored with bcrypt, which slows down an attacker who steals the database, but does nothing for a weak password typed into the form.
2. Two-factor authentication for sensitive accounts
With a one-time code generated by an app (TOTP), a stolen password is no longer enough. WordPress does not include it: you need a plugin. Make it mandatory for administrators and editors, set up backup codes, and be wary of codes sent by SMS or email, which are easier to intercept. The methods in detail, passkeys included, are covered in our guide to choosing and rolling out two-factor authentication.
3. Limit login attempts
Blocking an IP address after a few failures makes brute force too slow to succeed. The usual setting: 5 failures in 15 minutes, then a lockout that gets longer for repeat offenders. Two traps: behind Cloudflare or a proxy, the plugin must read the visitor’s real address, otherwise it blocks everyone; and locking by username rather than by IP lets anyone lock you out of your own account. Thresholds and false positives are covered in how to limit login attempts.
4. Move the login URL
When wp-login.php returns a 404, generic bots move on to the next site: less load, readable logs. The measure does not protect an account whose password has leaked, it cuts the volume. For it to hold, /wp-admin/ must not redirect anonymous visitors to the new URL, and the login page must stay out of the cache. The pitfalls (WooCommerce, lost password, caching) are in changing the wp-login.php URL.
5. Turn off XML-RPC and the access points you don’t use
xmlrpc.php accepts hundreds of password guesses in a single request. If you use neither Jetpack nor an old publishing app, turn it off completely (see disabling XML-RPC). Do the same check for application passwords: they open the REST API without two-factor authentication, useful for an integration, pointless otherwise.
6. Don’t hand out your usernames
By default, /?author=1 redirects to a URL that contains the author’s username, the REST API lists authors, and the login error message tells you whether a username exists. An attacker who knows the username only has to guess the password. Use a login username that differs from the display name and hide authors (see preventing user enumeration).
7. Keep a record of logins
A log of successful and failed logins, with IP address and time, flags what the other measures did not stop: an administrator login at 3 a.m. from an unfamiliar country, an account created for no reason. An email alert on every administrator login is enough on a small site.
The path of a login attempt
Each layer stops a different type of attacker. The animation follows three visitors: a generic bot, an attacker who knows the new URL, and you.
Which setup for which site?
Not every measure carries the same weight on every site. Start with the row that looks like yours:
| Type of site | Essential | Recommended | Watch out for |
|---|---|---|---|
| Blog, single administrator | Unique password, 2FA | Moved URL, XML-RPC off | Keeping the backup codes |
| Business site, several authors | 2FA required by role, limiting | Login log, hidden authors | Accounts of former contractors |
| WooCommerce store | 2FA for the team, limiting | Moved admin login URL | The customer login on “My account” stays public |
| Agency, many sites | 2FA, limiting, named accounts | Same settings exported to every site | No username shared between colleagues |
The mistakes that lock you out
- Forgetting the new URL: save it in your password manager before you activate it, and test it in a private window.
- Losing your 2FA phone without backup codes: print them or store them in the team vault.
- Locking yourself out through attempt limiting behind a misconfigured proxy: check in the log that the recorded address really is yours.
- Caching the login page: the form token expires and nobody can log in any more. Exclude it from every cache rule.
- Stacking two plugins that move the login or limit attempts: they contradict each other. One plugin per function.
Always keep an emergency exit: FTP or SFTP access to wp-config.php. Most security plugins provide a constant that suspends them while you regain control. To go further on the server side (protecting wp-admin by IP address or HTTP password), see protecting wp-admin at server level.
The login with WP Masquerade
WP Masquerade covers most of these measures in a single setting, without touching core files:
- Free version: custom login URL, tested before activation;
wp-login.phpandwp-admininvisible to logged-out visitors; XML-RPC and pingbacks blocked; bots probing for vulnerabilities counted. - Pro: login attempt limiting, app-based two-factor authentication with backup codes and enforcement by role, hidden authors (
/?author=, REST API, sitemaps), administrator activity log and email alerts. - Emergency exit: the line
define('CMS_MASQUERADE_DISABLE', true);inwp-config.phpsuspends every transformation and restoreswp-login.php;define('CMP_DISABLE_2FA', true);suspends Pro’s two-factor authentication.
WP Masquerade is not a firewall, an antivirus or a backup: pair it with an off-site copy of your data and, if needed, a web application firewall. How the hidden page works is described on the WP Masquerade custom login page.
Key takeaways
- Unique passwords and two-factor authentication first: they are the only measures that hold against an attacker who knows your URL and your username.
- Attempt limiting, a moved URL and XML-RPC turned off cut the volume of attacks and the load on the server.
- Don’t hide a store’s customer login form: limit it.
- One plugin per function, login page kept out of the cache, emergency exit in
wp-config.php. - A login log reveals what the other layers did not stop.
Frequently asked questions
Is changing the login URL enough to secure WordPress?
No. It gets rid of most generic bots and lightens the load on the server, but an attacker who finds the URL or holds a leaked password still gets in. Combine it with attempt limiting and two-factor authentication.
How many login attempts should you allow?
Five failures in fifteen minutes, followed by an IP lockout that gets longer for repeat offenders, suits most sites. Lock by IP address rather than by username, so that a stranger cannot lock you out of your account.
Is a CAPTCHA on the login page worth it?
It slows down simple bots, but it annoys users and stops neither a stolen password nor XML-RPC. Attempt limiting and two-factor authentication do more with less friction; a CAPTCHA mostly makes sense on a heavily targeted public form.
Should two-factor authentication be mandatory for every user?
Not necessarily. Enforce it for the roles that can publish, install plugins or manage accounts (administrator, editor, shop manager). For subscribers or customers, offer it without requiring it.
What should I do if I’m locked out of my site?
Connect over FTP or SFTP and add your plugin’s emergency constant to wp-config.php, or rename its folder in wp-content/plugins. With WP Masquerade, define('CMS_MASQUERADE_DISABLE', true); restores wp-login.php. Remove the line once the problem is fixed.
Protect your login page in a few minutes
The free version moves the login, hides wp-login.php and wp-admin and turns off XML-RPC. Pro adds login attempt limiting, two-factor authentication by role, the activity log and alerts.
Sources
- WordPress Developer Resources: Brute Force Attacks (external link, opens in a new tab)
- WordPress Developer Resources: Hardening WordPress (external link, opens in a new tab)
- OWASP: Authentication Cheat Sheet (external link, opens in a new tab)
- NIST SP 800-63B: Authentication and Authenticator Management (external link, opens in a new tab)


