Skip to content
All guides

How to Stop Brute Force Attacks on WordPress

For everyone 10 min readChecked October 26, 2026

A brute force attack is a robot trying thousands of passwords until one works. To stop brute force attacks on WordPress you need several layers, because no single setting covers every way a robot can guess. This guide explains the attacks and builds the layers one at a time.

What a brute force attack is

In a classic brute force attack, a bot tries many passwords for one username. In a credential stuffing attack, it tries username and password pairs leaked from other sites. In a low and slow attack, it spreads guesses over many addresses and many hours so no single address looks busy.

The target is usually the login page, but the same guessing can be sent to XML-RPC, the REST API with application passwords, and password reset forms.

Signs you are being attacked

Attacks are constant on every public WordPress site, but a spike is worth noticing.

  • Your activity log or server logs show many failed sign-ins in a short time.
  • You receive lockout emails or password reset emails you did not request.
  • The site is slow, or the server's CPU rises with requests to wp-login.php or xmlrpc.php.
  • Requests come from many different countries and addresses with the same few usernames.

How to stop brute force attacks on WordPress, layer by layer

Think of defences as layers. Each one removes a type of attack, and together they leave little.

  • Limit failed attempts per address and, if you can, per username.
  • Use long, unique passwords and refuse passwords known from breaches.
  • Turn on two-factor sign-in so a guessed password is not enough.
  • Close the side doors: XML-RPC and application passwords.
  • Stop usernames leaking, so attackers have nothing to start with.
  • Rate limit the login page at the server or CDN, before PHP runs.
  • Read the real visitor address when you are behind a CDN or proxy.

Limit login attempts

The core of any answer on how to stop brute force attacks on WordPress is a limit. After a few wrong passwords from the same address within a short time, lock that address out for a while. A good starting point is five tries in five minutes, then a fifteen minute lockout.

Real people rarely miss that many times, and a robot's guessing rate drops from thousands per hour to a handful. Lock out repeat offenders for longer, and consider counting failures per username too, so an attack spread across many addresses still hits a limit.

Passwords and two-factor

Limits slow guessing down but cannot stop a correct guess. Strong passwords make a correct guess unlikely, and two-factor makes it useless.

  1. 1Set a minimum length of at least 12 characters and encourage passphrases.
  2. 2Refuse passwords that appear in known breaches.
  3. 3Require two-factor for administrators, then for everyone who can publish.
  4. 4Remove the admin username from your site.

Close the side doors

Attackers use whatever door is easiest. XML-RPC can test many passwords in a single request with the system.multicall method, so a lockout based on login page requests may never see it. If you do not use XML-RPC, disable it.

Application passwords let an app sign in over the REST API without the login form, and they skip two-factor. Disable them if no app needs them.

Also stop the site revealing usernames through author archives and the REST API, so a bot has no usernames to try beyond common guesses.

Rate limit at the server or CDN

Server and CDN limits act before WordPress loads, which saves resources during an attack. Cloudflare and most CDNs offer rate limiting and bot rules for specific paths. On nginx you can limit requests to the login file yourself.

Make the limit generous enough that a person who mistypes a few times is not blocked.

nginx: rate limit wp-login.php to about 10 requests a minute per address
# In the http block
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=10r/m;

# In your server block, add limit_req to the location that already
# handles wp-login.php and passes PHP to your PHP handler
location = /wp-login.php {
    limit_req zone=wplogin burst=5 nodelay;
    # ...keep your existing PHP handling lines here
}

Get the real visitor address

If your site sits behind Cloudflare or another proxy, every request can appear to come from the proxy's address. A limit then counts everyone together, and either locks out real visitors or never triggers at all.

Configure your security tooling to read the real address from the proxy's header, and only trust that header from your proxy's own addresses. Otherwise anyone can fake the header.

Do not lock yourself out

Add your own fixed address to an allow list if you have one, so you are never counted. Know your way back in before you tighten anything, such as renaming the plugin folder over SFTP. If you do get locked out, wait for the lockout to end or sign in from another connection, such as your phone off Wi-Fi.

Stop brute force attacks on WordPress: questions

Can a brute force attack hurt a site with strong passwords?

It can still slow your server down, but a strong, unique password makes a successful guess very unlikely. Lockouts and two-factor make it safer still.

Will limiting login attempts lock out real users?

Rarely. Five wrong tries in five minutes is more than most people need, and a lockout expires on its own.

Does hiding the login page stop brute force attacks?

It stops most automated ones, because bots cannot find the page, but it is not a substitute for lockouts and two-factor.

Why do I see attacks from many different addresses?

Botnets spread guesses across thousands of machines so each stays under simple limits. Per-username limits, two-factor and server-level bot rules handle these better than address limits alone.

Do I need a CAPTCHA?

Not always. It helps against persistent bots on login, registration and reset forms, but it can annoy people, so add it if lockouts and two-factor are not enough.

Protect your WordPress site free

Most of this guide is one switch in Stack Guard.