If your security plugin keeps reporting failed login attempts and the number won’t go down, it isn’t broken. It’s working exactly as designed, on a layer the attack was built to walk around. Two of the most common WordPress login complaints turn out to be the same problem: a rotating-IP brute force that ignores rate limits, and a renamed login page that gets hit within minutes anyway. In both cases the defense keys on the wrong layer.
Let me start with a quote, because a competitor’s own support team said the thing more bluntly than I could.
“Changing the URL does not stop bots from reaching the authentication endpoints”
On a recent wordpress.org support thread, a site owner running a popular login-URL plugin asked why they were still getting roughly 25 “user locked out” notifications a day even though the login page was, in their words, hidden. The plugin’s own support representative answered honestly: changing the URL of the login page does not prevent login attempts, and it does not stop bots from trying to reach WordPress authentication endpoints.
That is the whole article in one sentence, delivered by the people who make the renaming tool. Renaming the login form relabels one door. WordPress authenticates through more than one.
I’m using the asker’s “25 a day” as an anecdote, not a statistic — the same goes for the “40–50 failed logins a day from rotating IPs” and the “over a million attempts a day” you’ll see in other threads. They’re reader-reported symptoms, not measured network data. What’s worth your time is the mechanism underneath them, because it’s identical across all three.
Symptom one: the rotating-IP attack that laughs at rate limiting
A common version goes like this. You get alerts about failed logins from many different IP addresses, a few dozen a day, and they keep coming from fresh addresses. Manual blocking is pointless because the source never repeats. The instinct, and the advice you’ll get in most forums, is to turn on rate limiting or lower the lockout threshold.
Here’s why that doesn’t end it. Rate limiting and IP lockout both make their decision based on the source IP. They count failures per address and lock that address after N tries. A rotating-IP botnet is purpose-built to defeat exactly that control: each request arrives from a new IP, so the per-IP counter never reaches its threshold. You can lower the limit to two attempts and it changes nothing, because no single IP makes a second attempt. The control is sound. The attacker simply isn’t operating on the axis the control measures.
So the dashboard fills with “blocked” and “locked out” events, the owner sees activity and assumes protection, and the actual probe volume hitting WordPress doesn’t move. The plugin is doing its job. Its job just isn’t the one that would make this stop.
Symptom two: the renamed login page that gets attacked anyway
The second complaint is the one that feels like a breach. Someone changes their login slug to something custom, and minutes later sees fresh login attempts against the site. The natural conclusion is that the secret leaked, that there must be a hole somewhere.
There usually isn’t. What’s happening is that the attacker never needed the renamed page. WordPress exposes a second authentication register at /xmlrpc.php, and the wp.getUsersBlogs method takes a username and password and validates them, completely independently of the login form. A bot calling that endpoint is authenticating credentials against your site without ever loading /wp-login.php or your custom slug. In the exact thread where this gets asked most clearly, the support reply traces the “mystery” attempts to an XML-RPC wp.getUsersBlogs call.
Renaming the login form does nothing to that endpoint. You moved one door and left the other one in its original frame, unlocked, with a sign on it. XML-RPC also supports system.multicall, which lets an attacker batch many credential guesses into a single HTTP request, so it’s not just an alternate door, it’s a more efficient one for brute forcing.
Both symptoms, one root cause: the defense is on the wrong layer
Put the two together and the pattern is obvious. Rate limiting keys on the source IP, and the attack changes IPs. Slug renaming keys on the visible form URL, and the attack uses a different endpoint. Each defense measures one attribute, and each attack is constructed to vary that exact attribute. You can tune these controls forever and the attempts keep arriving, because you’re optimizing the wrong variable.
The metric most plugins put front and center makes this worse. “Attempts blocked” counts events that already reached PHP and got handled. It’s a measure of how much work your server did on behalf of the attacker, not a measure of attacks prevented. The request that matters is the one that never trips the counter at all.
What actually changes the outcome

The fix is to move the defense to a layer the attacker can’t vary by swapping an IP or an endpoint: the request itself, before WordPress runs.
Two changes do the work. First, reconfigure the default login paths so that a request to /wp-login.php and /wp-admin returns 404 at the rewrite layer, in the Apache or nginx config, before PHP loads. There’s no form to brute-force and no process spends CPU rejecting the attempt, because the process never starts. This is structurally different from rate limiting: rate limiting reacts after the request reaches the application; a rewrite-layer 404 terminates the connection before any WordPress code runs. The rotating IPs stop mattering, because the thing they’re all aimed at no longer responds.
Second, close the XML-RPC authentication vector. If you don’t use XML-RPC (most sites don’t anymore; the Jetpack and legacy mobile-app cases are the main exceptions), disable it, or at minimum block the authentication methods so wp.getUsersBlogs and system.multicall can’t validate credentials. That removes the second door entirely, instead of relabeling the first one.
To be fair about the tool most people are already running: Wordfence is genuinely good at what the locked-out site owner has it doing. The monitoring, the lockouts, the 2FA, the alerting are real value, and I’m not suggesting anyone switch it off. The point is that those are application-layer, reactive controls, and a rotating-IP brute force and an XML-RPC auth call are specifically shaped to get past application-layer, reactive controls. The missing piece sits in front of them, not in place of them.
On the WordPress sites we run at Squirrly, that front layer is WP Ghost’s Paths Security, which reconfigures the login paths to return 404 at the rewrite layer and includes the option to disable XML-RPC, alongside its server-level firewall. We keep a scanner in the stack for detection regardless. The path layer is what makes the rotating-IP attempts and the XML-RPC calls stop reaching anything, so the lockout notifications drop because the requests 404, not because we finally found the right IP to block.
FAQ
Why does my renamed login page still get login attempts?
Because renaming the slug only relabels the interactive form. WordPress also authenticates through /xmlrpc.php (the wp.getUsersBlogs method validates a username and password with no login form involved), and through the REST API in some configurations. The bot isn’t finding your secret URL. It’s authenticating against a different endpoint that the rename never touched.
Will rate limiting stop a rotating-IP brute force?
Not on its own. Rate limiting and IP lockout decide based on the source address, and a rotating-IP botnet sends each attempt from a fresh IP so the per-IP counter never trips. The attempts keep arriving. The durable fix is to make the login path return 404 before PHP loads, so there’s no form to attack regardless of how many addresses the bot cycles through.
Should I just disable XML-RPC?
If nothing on your site uses it, yes. The common exceptions are Jetpack and some older mobile-publishing apps. If you need it, block the authentication methods (wp.getUsersBlogs, system.multicall) rather than leaving the whole interface open, since those are the ones used for credential validation and batched guessing.
Is changing the login path just security through obscurity?
No. Obscurity assumes a human attacker who eventually finds the renamed path. The threat is scripted bots hitting predictable endpoints across many domains. Reconfigure the path so the default endpoint returns 404 at the rewrite layer and the script gets nothing back before any authentication code runs, then moves on. The password check, 2FA, and rate limiting still do their work on the legitimate traffic that remains; the path change cuts the volume that ever reaches them.
My plugin says it blocked 48,000 attempts. Isn’t that good?
It means 48,000 requests reached your application and were handled there. It’s a measure of load you absorbed, not attacks prevented. A more useful question is how many requests never reached a login form at all. If your defense works at the rewrite layer, that “blocked” number goes down because the attempts 404 before they’re ever counted.
