Look at the access log of any WordPress site that has been online for more than a week and you will find them: hundreds, sometimes thousands, of POST requests to /wp-login.php, each one trying a different password against admin. This is not a targeted attack. It is background radiation. Automated botnets spray every WordPress login they can find, and they do it cheaply because the login page, by default, will let them guess as many times as they like. This guide walks through closing that door, in the order that gives you the most protection for the least effort. None of it is exotic, and all of it takes an afternoon.

Prerequisites: WordPress 6.x with administrator access, the ability to install plugins, and either access to your .htaccess file (Apache) or your hosting control panel. Tested against WordPress 6.6 on Apache and Nginx. If you can edit files over SFTP, keep a client open; a couple of these steps touch server config.

Step 1: Stop using guessable usernames

Every brute-force script starts with the username admin, because for years that was the WordPress default. If your administrator account is still called admin, you are handing the attacker half of the credential for free. WordPress will not let you rename a user in the dashboard, so create a new administrator account with a non-obvious name, log in as that account, and delete the old admin user, assigning its content to the new one. While you are there, make sure the account’s public display name is not the same as its login name, because the author archive at /?author=1 will happily leak the login otherwise.

Don’t skip this: a strong password on a known username is a single unknown. A strong password on an unknown username is two, and the attacker’s script is not written to guess both.

Step 2: Limit login attempts

This is the single highest-value change on the list. Out of the box, WordPress imposes no penalty for a wrong password, so a bot can try forever. A login-limiter locks out an IP after a handful of failures, which turns “unlimited guesses” into “five guesses an hour” and makes password-spraying pointless.

Install a maintained plugin such as Limit Login Attempts Reloaded or the login component of Wordfence. Set a low retry count, four or five, a lockout window of twenty minutes or more, and enable the option to lengthen the lockout for repeat offenders. That is it. You will see the lockouts pile up in the log within a day, which is a useful reminder of how constant the traffic is.

Step 3: Turn on two-factor authentication

A limiter slows guessing; two-factor makes a guessed password nearly useless on its own. Plugins like Two-Factor (maintained by contributors to WordPress core) or the 2FA feature bundled with most security plugins add a one-time code from an authenticator app to the login. Enable it for every administrator and editor account at minimum. If you do only one thing beyond limiting attempts, do this.

Step 4: Deal with XML-RPC

Here is the part most guides forget. Even with /wp-login.php locked down, older WordPress installs expose /xmlrpc.php, and its system.multicall method lets an attacker test hundreds of passwords in a single request, sailing straight past a limiter that only counts login-page hits. If you do not use the Jetpack app, the WordPress mobile app, or pingbacks, disable it. The cleanest way is a rule in .htaccess:

# Block all access to xmlrpc.php
<Files xmlrpc.php>
  Require all denied
</Files>

If you do rely on something that needs XML-RPC, a plugin like Disable XML-RPC Pingback removes just the abused methods while leaving the rest working.

Step 5: Put a wall in front of wp-admin

For a site with a small, fixed set of editors, the strongest option is to require a second, server-level password before WordPress even loads the login form. On Apache, an .htpasswd file protecting /wp-admin/ means a bot hitting the login never reaches PHP at all. Your host’s control panel almost certainly has a “password-protect directory” tool that sets this up without editing files by hand.

If your editors work from unpredictable locations that rules out an IP allowlist, this HTTP-auth layer is the next best thing, and it costs the attacker a second credential they have no way to guess.

A warning before you do this: it is genuinely easy to lock yourself out with server-level rules. Make the change when you have SFTP or control-panel access open in another tab, so that if a typo in .htaccess throws a 500 error you can revert it immediately. Never edit these rules on a live site with no way back in.

What to skip

You will see advice to “hide” the login by moving it to a secret URL. It is fine as noise reduction, and a plugin like WPS Hide Login does it cleanly, but treat it as tidiness, not security. A secret URL is obscurity; it stops the dumb bots and none of the determined ones. Spend your effort on Steps 2 and 3, which actually change what an attacker can do, before you spend any on Step-6 URL games.

Put together, the first three steps stop the overwhelming majority of what hits a WordPress login, and Steps 4 and 5 close the paths the automated tools use to route around them. For the broader picture of locking down the rest of the install, the older WordPress security basics guide still holds up on the fundamentals. If you want a running list of which plugins are currently being exploited so you can vet what you install, keep an eye on Patchstack and the Wordfence blog, which track WordPress vulnerabilities as they are disclosed.