Invite-only beta · 9 free places left · Managed hosting on AWS

AceMedia HostRequest invite

SECURITY · 22 OCTOBER 2026

What a WordPress login lockout should actually do

Every WordPress site gets password guessing. A lockout helps, but only if it counts the right things, says nothing useful to an attacker and never locks out the person who owns the account.

Look at the access log of almost any WordPress site and you will find POST /wp-login.php requests from addresses you have never heard of. Most are automated guesses against common usernames. They rarely get in, but they cost CPU time, fill logs and occasionally do find a reused password.

The usual answer is a lockout: after a few failures, stop accepting attempts for a while. That is sound advice, but a badly built lockout can be worse than none. These are the checks I use when judging one, whichever plugin or server rule provides it.

1. Count failures per account and per address

Counting only by account stops someone hammering one username, but not someone trying one password against hundreds of usernames. Counting only by IP address stops one machine, but not a botnet spreading guesses across thousands of addresses. You want both, with different limits: a low one for a single account and a higher one for a single address, so a shared office connection does not lock everyone out after one person's typo.

For IPv6, count the whole /64 network rather than the single address. A single connection usually controls an entire /64, so counting individual addresses lets one machine rotate through millions of them.

2. Make sure it sees the real visitor address

If your site sits behind Cloudflare or another proxy, PHP sees the proxy's address unless something translates it. Then every visitor looks like the same handful of Cloudflare servers, and an IP lockout either does nothing or locks out everyone at once.

The fix is to read the visitor's address from the proxy's header, but only when the request genuinely came from that proxy. Trusting X-Forwarded-For from anyone lets an attacker choose their own address with every request. I covered the server side of this in locking your origin to Cloudflare.

3. Say the same thing for every lock

If the message for a locked real account differs from the message for a username that does not exist, the lockout becomes a way to discover which usernames are real. Use one wording for every lock type, and lock unknown usernames after the same number of failures as real ones. Then a guess tells an attacker nothing either way.

A sign-in form showing the message: Too many failed login attempts. Try again in 1 minute(s).
One message for every kind of lock, with the time it lifts.

4. Do not lock out the owner

An attacker who knows your username can keep your account locked indefinitely just by failing on purpose. A good lockout lets a correct password through from an address that account has successfully signed in from before. The owner at their usual desk still gets in, and the attacker gets nowhere.

5. Never lock private addresses

Locking 127.0.0.1 or a 10.x address usually means locking your own server, your load balancer or a monitoring check. Exclude private, loopback and reserved ranges from IP locks entirely.

6. Keep a log a human can read

When someone says they cannot sign in, you need to know quickly whether they were locked out, by which rule and until when. A short log of failed and blocked attempts, with username, address, time and the reason, answers that in seconds. It also shows you when one address is behind most of the failures, which is the point to block it further upstream.

A login attempt log in the WordPress dashboard listing each attempt's time, username, IP address, browser and whether it failed or was blocked.
A log you can read beats guessing why someone cannot get in.

7. Fail closed, and say so

If the lockout or a second factor depends on something that breaks, such as a missing PHP extension after a server change, the safe behaviour is to refuse the sign-in with a clear message. The unsafe behaviour is to quietly let people in without the second factor. Test this deliberately before you rely on it.

8. Treat the lockout as the last line, not the only one

A lockout slows guessing; it does not make a weak password safe. Pair it with two-factor authentication for anyone who can publish or install code, and offer passkeys where you can, because a passkey cannot be guessed or reused from another site's leak.

How I handle it

I built all of this into Ace Login Block, a free plugin on WordPress.org, and version 0.431.0 added the lockout and the log described above. By default, five failures within fifteen minutes locks an account for thirty minutes, twenty failures locks an address, and a Trusted Proxy Header setting reads Cloudflare's header only from Cloudflare's own ranges. Every number can be changed, and accounts or addresses can be unlocked from a Security tab.

You can try it in your browser on a small demo site. Get the password wrong five times and see what happens; the demo shortens the lock to one minute.

Quick checks for your own site: fail a sign-in five times from your phone on mobile data, then try the correct password from your usual connection. Check the message does not change for a username that does not exist. Then look at what your logs recorded.

If you host with us and want this set up, or you would like a second opinion on how your site handles sign-ins, get in touch.

More hosting tipsTalk about your hosting

INVITE-ONLY BETA

Tell us about your site.

Nine free beta places remain for projects that will help shape the service. Tell us what you’re building; we’ll reply personally. Fields marked * are required.

Please do not send passwords or private customer data. We’ll use these details to reply. Privacy notice.

Prefer email? Write to [email protected].