WordPress Login Security: How to Stop Brute Force Attacks in 2026
WordPress login pages are the single most attacked endpoint on the web. Wordfence’s 2025 threat report recorded an average of 2.8 million brute force attempts per minute across monitored WordPress sites, and Sucuri attributes 16% of all WordPress compromises to weak or reused passwords combined with unlimited login attempts. If your site still runs the default /wp-login.php page with no rate limiting, no two-factor authentication, and no IP blocking, automated bots are trying your credentials right now — and they have all the time in the world.
This is a complete, practical guide to WordPress login security. We’ll cover exactly what a brute force attack looks like in 2026, why the default WordPress login is so exposed, and every concrete step — from free built-in settings to advanced server-level protections — that locks attackers out without making login painful for your real users.
Whether you run a small blog, a WooCommerce store, or a multisite network with dozens of clients, the techniques below apply. By the end, you’ll have a prioritized checklist and a clear understanding of where to spend your time (and where not to).
What a WordPress Brute Force Attack Actually Looks Like
A brute force attack against WordPress isn’t one attacker sitting at a keyboard guessing passwords. It’s a distributed botnet — often tens of thousands of compromised routers, IoT devices, and servers — submitting username/password combinations to wp-login.php or xmlrpc.php from hundreds of different IP addresses at once. A single campaign can attempt millions of combinations in an hour, and because the traffic is distributed, IP-level defenses that only block one address at a time are easily bypassed.
There are three variants you should know:
- Dictionary attacks — cycling through the 10,000 most common passwords (
password123,admin2024,letmein, seasonal patterns likeSpring2026!). Fast, cheap, surprisingly effective against sites with no enforcement of password complexity. - Credential stuffing — using username/password pairs leaked from unrelated breaches (LinkedIn, Adobe, Dropbox), betting that users reuse passwords across sites. This is the most dangerous modern variant because it bypasses password complexity rules entirely — the attacker already has a password that worked somewhere.
- Targeted attacks — a human attacker who has researched your site, gathered usernames from your author archives or staff page, and is focused specifically on you. Rare, but devastating when successful.
Credential stuffing now accounts for the majority of successful WordPress compromises, according to Verizon’s 2025 Data Breach Investigations Report. That matters because it means password complexity alone is no longer enough. You need defenses that work even when the attacker has a valid password.
Why the Default WordPress Login Page Is So Exposed
Out of the box, WordPress is remarkably generous to attackers. The defaults include:
- Unlimited login attempts — a single IP can submit thousands of guesses per minute without being slowed down or blocked.
- A predictable login URL — every WordPress site on the internet lives at
/wp-login.phpand/wp-admin/. Attackers scan the entire internet for this path and queue your site for attack automatically. - Username enumeration — the REST API, author archives, and login error messages all reveal valid usernames, cutting an attacker’s guessing space in half.
- XML-RPC enabled — a legacy endpoint that accepts authentication and supports request batching, letting attackers try hundreds of passwords in a single HTTP request.
- No activity logging — even if you’re being attacked right now, you have no way to see it unless you manually tail the nginx access log.
Every one of those defaults is an attacker’s best friend. The good news is that each one can be fixed in minutes once you know where to look.
1. Enforce Strong Passwords and Require 2FA
The cheapest defense is a password an attacker cannot guess. For every account with publishing or admin privileges, require:
- Minimum length of 14 characters — shorter passwords fall to offline cracking in seconds on modern GPUs
- A mix of uppercase, lowercase, numbers, and symbols
- No dictionary words, no site name, no year, no username embedded
- Stored in a password manager (1Password, Bitwarden, KeePass) — never reused across sites, never written in a note, never saved in a browser profile that can be exfiltrated from a compromised laptop
Why Two-Factor Authentication Is Non-Negotiable
Two-factor authentication defeats credential stuffing entirely. Even if an attacker has a valid username and password, they still need the time-based one-time password (TOTP) on your phone. Google’s internal data shows that adding a second factor stops 100% of automated bot attacks and 99% of bulk phishing attacks.
Prefer authenticator apps (Google Authenticator, Authy, 1Password TOTP) or hardware keys (YubiKey) over SMS. SMS-based 2FA is vulnerable to SIM swapping — an attack where the attacker convinces your mobile carrier to port your number to their device. It’s no longer theoretical; it’s a routine attack vector for high-value accounts.
2. Limit Login Attempts per IP (and Username)
Rate limiting is the single biggest improvement you can make to login security. A well-configured login limiter stops botnets dead: after 3–5 failed attempts from an IP, the IP is blocked for 15 minutes to 24 hours depending on severity. The attacker’s cost jumps from thousands of guesses per minute to effectively zero.
Good rate limiting should:
- Track attempts per IP, not per username — if you only lock by username, attackers rotate usernames and keep going
- Track attempts per username across IPs too, as a second layer — this catches distributed attacks targeting a specific account
- Handle reverse proxies correctly — if your site sits behind Cloudflare, nginx, or a load balancer, you need to extract the real client IP from
X-Forwarded-FororCF-Connecting-IP, not the proxy’s IP, or every attacker will look like your own server - Escalate on repeat offenders — first block 15 minutes, second block 1 hour, third block 24 hours, permanent block after that
- Allowlist trusted IPs — office networks, VPN exit points, your own home IP, so you don’t lock yourself out
- Log every attempt — username, IP, user agent, country, timestamp — so you can audit after an incident
3. Add reCAPTCHA v3 to Your Login Form
Google’s reCAPTCHA v3 runs invisibly in the background and returns a confidence score from 0.0 (definitely a bot) to 1.0 (definitely human) on every form submission. Rejecting requests below a threshold — typically 0.5 — eliminates the vast majority of automated login traffic without asking legitimate users to click on traffic lights or identify fire hydrants.
Unlike v2 (the checkbox), v3 is genuinely invisible. The only cost is a small JavaScript payload and a single API call per submission. Google’s service is free for up to 1 million assessments per month, which covers nearly every WordPress site.
Our Emnes Oversight Pro plugin adds reCAPTCHA v3 to the WordPress login form, the password reset form, and WooCommerce login/register/checkout flows, with the score threshold configurable per form so you can be stricter on high-value pages like checkout.
4. Change the Default Login URL
Moving the login page from /wp-login.php to something unique — /staff-entrance, /secure-access, or anything non-obvious — won’t stop a determined human attacker, but it eliminates the entire class of drive-by automated scans that only target the default URL. That’s 80–90% of attack traffic on an average WordPress site, according to data from WP White Security’s honeypot network.
This is security through obscurity, and it is not a replacement for rate limiting, 2FA, or monitoring. It is a noise reduction layer. Bots scanning the internet for default WordPress installs simply skip your site and move on to the next one. Your server load drops, your logs get cleaner, and your other defenses get to focus on the attackers who actually bothered to find your real login URL.
Important: custom login URLs must work consistently across the whole site. Make sure the new URL:
- Correctly handles the password reset flow (attackers probe
wp-login.php?action=lostpassword, not just the base URL) - Redirects
/wp-admin/to the new login URL for logged-out users, or the hidden login is still discoverable - Plays nicely with multisite networks if applicable
- Is documented internally so new team members can find it
5. Disable or Restrict XML-RPC
The xmlrpc.php endpoint is a login vector most site owners completely forget about. It accepts authentication using the same credentials as wp-login.php, and — critically — it supports request batching via system.multicall. A single HTTP request can try hundreds of username/password combinations at once, bypassing most login-attempt limiters that count HTTP requests rather than credential attempts.
Your decision tree:
- Don’t use the WordPress mobile app, Jetpack, or a remote blog editor? Disable XML-RPC entirely. Block it at the nginx level with
location = /xmlrpc.php { deny all; return 403; }. - Need XML-RPC for Jetpack or similar? Restrict it to specific IP ranges at the firewall or nginx level. Jetpack publishes their IP ranges; allowlist only those.
- Need XML-RPC and can’t restrict by IP? At minimum, disable
system.multicallvia a plugin ormu-plugin, and make sure your login limiter inspects XML-RPC POST bodies, not just HTTP request counts.
6. Block Username Enumeration
WordPress leaks usernames through several endpoints by default. Every leak hands attackers a valid username and cuts their guessing space in half. Close them all:
- Author archives —
/?author=1redirects to/author/username/. Disable author archives entirely if you don’t use them, or redirect all author requests to the homepage. - REST API users endpoint —
/wp-json/wp/v2/userslists every user with publishing privileges. Disable this endpoint for unauthenticated requests via a simple filter infunctions.phpor a plugin. - Login error messages — by default, WordPress returns “Unknown username” vs “Incorrect password”, confirming username validity. Override the error to always return a generic “Invalid credentials” message.
- XML-RPC
wp.getUsersBlogs— returns different errors for valid vs invalid usernames. Covered by disabling XML-RPC above.
Also: never use the username admin. If you installed WordPress before 2013 you may still have it. Create a new administrator account with a unique username, verify you can log in, then delete admin and reassign its posts.
7. Monitor, Log, and Alert in Real Time
Prevention gets you most of the way. The rest is visibility. You need to know when someone is attacking you — not a week later when a customer reports something weird, but the moment it starts.
At minimum, log every login attempt with username, IP, user agent, country, and timestamp. Then alert on:
- Successful admin logins from new IPs or countries — if your only admin always logs in from Bangladesh, a successful login from Russia is an incident
- Bursts of failed logins — more than 10 failures in 5 minutes on a quiet site, or an unusual spike vs your baseline
- Failed logins against the
adminusername — nobody on your team should be using that username, so every attempt is hostile - Changes to user roles, especially promotions to administrator
- New user registrations if you don’t expect them
- Plugin or theme installations from accounts that don’t normally install things
Emnes Oversight records every login attempt (success or failure) with full metadata, and the Pro version sends email alerts when any of these thresholds are crossed. It also surfaces the top attacking IPs and countries in a dashboard so you can see trends at a glance.
8. Server-Level Defenses Worth Configuring
Everything above can be done inside WordPress. But if you control the server (or your host allows it), a few server-level defenses add another layer that attackers have no way around from the application side:
- fail2ban — parse nginx or WordPress logs and block IPs at the firewall level after repeated failures. Faster than PHP-level limiters because the kernel drops packets before they reach your application.
- Cloudflare WAF rules — free plan includes bot management and rate limiting on login endpoints. Pro plan ($20/month) adds OWASP rule sets. You can rate-limit
wp-login.phpandxmlrpc.phpto a few requests per minute across the entire internet. - HTTP Basic Auth on
/wp-admin/— adds a second password layer before WordPress even loads. Trivial to configure in nginx, and bots hammeringwp-login.phpnever get past it. - Country-level IP blocking — if you only serve customers in a handful of countries, block login traffic from everywhere else at the Cloudflare or nginx layer. Controversial but effective.
WordPress Login Security Checklist
Work through this checklist in order. Each item takes 5–30 minutes. The first five cover the vast majority of real-world attacks.
- 14+ character passwords, stored in a manager, never reused across sites
- Two-factor authentication (TOTP, not SMS) enabled on every admin account
- Login attempts rate-limited per IP and per username, with correct reverse-proxy IP handling
- reCAPTCHA v3 on login, register, and password reset forms
- Default login URL moved to a non-obvious path, with
/wp-admin/redirects updated - XML-RPC disabled, or restricted by IP if you need it
- Username enumeration blocked across author archives, REST API, and login error messages
- No account uses the username
admin - Real-time logging and email alerts for suspicious login activity
- fail2ban or Cloudflare rate-limiting configured at the server/edge level
- Regular backups stored off-site, so you can recover if prevention fails
Frequently Asked Questions
How often do brute force attacks on WordPress actually happen?
Constantly. Wordfence reports 2.8 million brute force attempts per minute across monitored sites in 2025. A new WordPress install with no security hardening will start receiving automated login attempts within hours of being indexed — and often before, via IP-range scanning.
Is changing the login URL alone enough to secure WordPress?
No. Changing the login URL stops dumb bots, but a targeted attacker will find the new URL in minutes via brute-forcing common paths or analyzing your site’s assets. Use it as a noise reduction layer, not a primary defense. Rate limiting and 2FA do the real work.
Should I use a plugin or configure security at the server level?
Both. Plugins give you application-level context (username tried, failed logins by role) that the server can’t see. Server-level defenses (fail2ban, Cloudflare WAF) block traffic before it costs you PHP cycles. Layer them.
What’s the difference between brute force and credential stuffing?
Brute force tries many passwords against a known username. Credential stuffing uses valid username/password pairs leaked from other breaches, betting on password reuse. Strong passwords stop brute force; only 2FA and unique passwords stop credential stuffing.
Does disabling XML-RPC break anything?
Only if you use the WordPress mobile app, Jetpack, or certain remote-editing tools. Check what’s connected before disabling. If nothing is, disabling XML-RPC closes a major attack vector with zero downside.
Start With Visibility
If you do only one thing after reading this, turn on login logging. You cannot defend against attacks you cannot see. Once you can see the traffic — which IPs, which usernames, which times of day — the right defenses become obvious, because you’re tuning them against real attack patterns on your site instead of guessing.
Our Emnes Oversight plugin is free and covers login logging, attempt limits, and username enumeration blocking out of the box. The Pro version adds reCAPTCHA v3, custom login URLs, country blocking, and real-time email alerts. Get in touch if you’d like help auditing your site’s login security end-to-end.
For a broader look at WordPress hardening, see our guide to WordPress plugin security in 2026 and our complete WordPress backup strategy, both of which complement the login-security layer covered here.