Skip to content
WPExpertsHub
  • Plugins
  • WooCommerce
  • Services
  • Support
0 Explore Plugins
Esc

Popular User Security Guard for WordPress Media and Database Cleaner for WordPress Backup & Restore by WpExperts Hub

  • Plugins
  • WooCommerce
  • Services
  • Support
  • Cart (0)
Explore Plugins My Account
  1. Home
  2. Blog
  3. Limit Login Attempts on WordPress to Stop Brute-Force Attacks

Limit Login Attempts on WordPress to Stop Brute-Force Attacks

Updated 27 October 2026 · 13 min read

On this page

  1. 01What a brute-force login attack looks like
  2. 02What you can do without a plugin
  3. 03Setting up User Security Guard step by step
  4. 04How blocking works
  5. 05When the attacker changes address on every request
  6. 06When each address tries only once: password sprays
  7. 07When the bot signs up instead: fake customer accounts
  8. 08How to avoid locking yourself out
  9. 09What the security log and weekly digest show
  10. 10Further reading
In short

How brute-force login attacks work, what you can do without a plugin, and how to limit login attempts with User Security Guard without locking yourself out.

Contents10 sections
  1. 01What a brute-force login attack looks like
  2. 02What you can do without a plugin
  3. 03Setting up User Security Guard step by step
  4. 04How blocking works
  5. 05When the attacker changes address on every request
  6. 06When each address tries only once: password sprays
  7. 07When the bot signs up instead: fake customer accounts
  8. 08How to avoid locking yourself out
  9. 09What the security log and weekly digest show
  10. 10Further reading

To limit login attempts on WordPress, use a plugin that counts failed sign-ins per IP address and per account and blocks the source when the risk crosses a threshold. User Security Guard for WordPress does this out of the box: install it, add your own IP address to its allowlist and start with the defaults. Strong passwords and a second factor still matter alongside it.

What a brute-force login attack looks like

A brute-force attack is automated password guessing. A script submits many username and password pairs to wp-login.php, often starting with names such as admin, until one works. Some attacks rotate through many IP addresses, and others probe for exposed files such as /.env first.

In your logs this shows up as bursts of failed sign-ins from one address, many failures against one account from many addresses, requests for default usernames that do not exist on your site, and repeated 404 requests for paths no real visitor asks for.

What you can do without a plugin

  • Use long, unique passwords for every account, ideally from a password manager.
  • Do not keep an account called admin, since it is the first name attackers try.
  • Add a second factor for administrators. Guessing a password is not enough if a second proof is required.
  • Ask your host whether it offers rate limiting at the server or firewall level.

None of this counts failed attempts or blocks the source on your site. That is the gap a login-limiting plugin fills.

Setting up User Security Guard step by step

The plugin requires WordPress 6.2 or later and PHP 7.4 or later. It is a paid plugin, but the documentation states that no sign-in protection feature checks the licence; the key only unlocks updates.

  1. Download the zip under My Account → Downloads on wpexpertshub.com.
  2. In WordPress, go to Plugins → Add Plugin → Upload Plugin, choose the zip, click Install Now, then Activate Plugin. The plugin then works with its default settings.
  3. Open User Security → Allowlist, add your own IP address with a label and click Add to allowlist. The screen shows the address you are browsing from. Only add addresses you control.
  4. Make sure the site has a second administrator account. The Dashboard and Settings warn when there is only one.
  5. If the site is behind Cloudflare or another proxy, open User Security → Settings → Reverse proxies, tick Trust proxy headers and choose the header your proxy sets. Then check User Security → Tools → Sign-in diagnostics, which says “Working” when the visitor’s address is read correctly.
  6. Open User Security → Emails (version 1.5.0 and later). Every email the plugin can send is listed there with a switch and one line that says when it is sent; leave Send them to empty to use the site administration address, and keep Send a digest at Every week.
  7. If another login-limiting plugin is active, keep only one. The plugin names the ones it detects, because two plugins counting the same failures can lock the wrong person out.

The key protections and their defaults

  • Login limits: failed sign-ins are counted per IP address, username and email within a rolling window of 60 minutes (Counting window (minutes)). An address counts as suspicious after 5 failures (Suspicious attempts per IP), and the per-IP limit is 10 (Block after failed attempts from one IP).
  • Administrator protection: administrator accounts get a stricter limit of 5 (Failed attempts before an admin account is treated as targeted).
  • Default usernames: names such as admin that are not real accounts on your site are watched, and the address is blocked after 3 attempts.
  • Exploit probing: an address that makes 5 requests for known exploit paths that answer 404 within 10 minutes is blocked from signing in.
  • Rotating addresses: 10 different addresses of one network (an IPv4 /24, an IPv6 /64) that are refused or try names that are not accounts block the whole network; 25 spread over at least three networks block the IPv4 /20 around them.
  • Sign-in form check: a sign-in post that carries no valid token of a form this site served is refused before the password is looked at; a form stays valid for 24 hours.
  • Distributed attacks: 8 different addresses that fail with unknown names or post without the form inside an hour halve the per-address limits for an hour.
  • XML-RPC: blocked by default with a generic 403 (Block XML-RPC).
  • WooCommerce: the My Account and checkout sign-in forms are protected when WooCommerce is active.

How blocking works

Before WordPress checks a password, the plugin asks whether the address or account is already blocked. If it is, the request is refused even when the password is correct. After a wrong password, a risk engine adds up points from signals and answers allow, suspicious or block. A request is blocked when a rule asks for a block or when the total reaches the block score of 80 (Risk score for “block”).

One point deserves care: the per-IP limit blocks by itself. With the defaults, an ordinary account guessed from one address with a normal browser marks the address suspicious on the 5th failed attempt, and the address is blocked on the 10th. The failed attempt is written down first and judged second, so the limit counts the attempt that reaches it. A script that tries invented usernames from one address is blocked on its 10th failed sign-in too. (Versions before 1.1.0 judged first, so a block landed one failure late, and an address that only guessed names that are not accounts was never blocked.)

Other facts worth knowing:

  • Blocked visitors see the same generic message as for any wrong password: “The username or password you entered is incorrect.”
  • Every block stores a readable reason. By default a block lasts until an administrator removes it. Automatic release after a set number of hours is opt-in (Release automatic blocks after (hours)); the one exception is a wide range of addresses that the plugin blocks by itself, which lifts after 48 hours.
  • Administrator accounts are not blocked automatically by default. The plugin blocks the attacking address instead and sends an “Administrator block refused” alert.
  • Blocks stop new sign-ins only. Sessions that already exist keep working until their cookies expire.
  • The plugin does not add a CAPTCHA, hide wp-login.php or support authenticator apps. Its only second factor is an optional emailed code, off by default.

When the attacker changes address on every request

A botnet or proxy service can spread one attack over dozens of addresses that each try once or twice, so no per-address limit is ever reached. User Security Guard counts the different addresses of one network instead (an IPv4 /24, an IPv6 /64): when 10 of them are refused or try names that are not accounts within the counting window, the whole network is blocked. A bot that also hops between neighbouring networks is caught one level up: 25 addresses spread over at least three networks block the IPv4 /20 (IPv6 /48) around them, and the /16 (IPv6 /32) is available as an opt-in.

Because a wrong guess there refuses many people, the plugin leaves a network or range alone when somebody signed in successfully from it in the last 90 days, when a trusted address is inside it, or when the sign-ins of customers are not logged, and a wide range lifts by itself after 48 hours. These blocks refuse sign-ins only, never browsing or guest checkout. The card What the recorded attempts show at the top of the Dashboard says in plain words whether this is happening and offers Block network or Block range.

When each address tries only once: password sprays

The sprays that reach a small site look different again: 30 addresses in unrelated networks, one invented username each (backup_manager, adm1nverified, wpadmim98), a credential list posted straight at wp-login.php by a client that never loads the sign-in form. No per-address limit and no network ever fills. Since version 1.4.0 the plugin closes that gap at the form itself: every sign-in form it knows (wp-login.php, forms made with wp_login_form(), the WooCommerce My Account and checkout forms) carries a hidden, signed, time-limited token. A sign-in post without a valid token never loaded the form, so it is refused before the password is looked at, recorded as “form not loaded” rather than a failed sign-in, and an address that keeps doing it is blocked. A real person whose form sat open for longer than a day is simply told to reload and try again.

Behind that, the plugin watches the whole site: when 8 different addresses fail with unknown names or post without the form inside an hour, it treats the site as under attack for an hour. Per-address limits are halved (never below two tries), a network is blocked at half the usual number of addresses, the Dashboard shows an Under attack line, and you get one email. The state ends by itself, and a customer’s wrong password on a real account never starts it. The REST users list and the ?author=1 redirect, the two ways a visitor turns a number into a username, are closed to visitors who are not signed in, while author pages at their normal addresses stay as they are. None of this touches a page a search engine reads: Googlebot and the other engines are verified by DNS, a real crawler is never counted as a scanner, and the plugin never answers 403 for a page, a 404 or a public REST route.

When the bot signs up instead: fake customer accounts

Some bots never guess a password. On a shop with customer accounts they create accounts: the tool loads the My Account page, reads its hidden fields, solves the image CAPTCHA by OCR and posts the registration form like a person, from a new address every time, and a few minutes later it probes xmlrpc.php. It never fails a password, so none of the limits above ever see it. Since version 1.7.0 User Security Guard checks the WooCommerce My Account and wp-login.php registration forms before the account is created. It refuses a form that was posted without the page’s JavaScript running, sent back within a few seconds or with a hidden field filled in; an email domain that cannot receive mail, or a throw-away domain that accepts mail for any made-up name (a wildcard MX); a browser that stopped updating years ago; and more than three sign-ups an hour from one address. A refused person sees the form again with a short message, never an error page, and accounts created at checkout or by an administrator are never checked.

A fake account that still gets through can be marked as fake on the Users screen. After a confirmation the plugin blocks the address it signed up from, adds the domain’s own mail server and the domain to the sign-up block lists, and deletes the account, so the next sign-up from that domain or that mail server is refused at once. It never learns Gmail, Outlook or the other free providers, and it leaves accounts with orders alone. A new account that requests xmlrpc.php within an hour of signing up is blocked automatically. Every refusal is in the security log under the kind Sign-ups, with the check that refused it.

How to avoid locking yourself out

Start with the allowlist. Allowlisted addresses are never scored and never receive an automatic block. It has limits, though. It does not lift a block that already exists, it does not protect you from an account block, and it does not skip the email sign-in code. Treat each entry as a deliberate gap and add only addresses you control.

If you are locked out, the documentation lists these ways back in:

  • WordPress’s “Lost your password?” link. Password reset is never blocked.
  • Another administrator’s session: unblock the address or account under User Security → Blocked IPs or User Security → Blocked Users.
  • WP-CLI, which works without a browser session:
wp wpus blocks
wp wpus unblock --account=your-admin-login --reason="Locked out"

You can also use wp wpus unblock --ip=<address>. If you turn on the email sign-in code and mail does not work, a correct password is still refused; use Send me a test email first, and wp wpus two-factor --disable is the way back in.

Emergency mode

During an attack, User Security → Tools → Turn emergency mode on tightens the limits at once. For example, the per-IP block limit drops to 2, the block score to 50, and XML-RPC stays blocked. It is never switched on automatically, your saved values are untouched, and blocks never lapse while it is on. Turn it off on the same screen.

What the security log and weekly digest show

User Security → Security Logs records 23 event types, filterable by event, risk level, result, address and date. The password field, cookies, tokens and request bodies are never stored; the name typed into a failed sign-in is kept so that you can see what attackers guess, and you can switch that off. Log rows are kept for 90 days by default. User Security → Dashboard adds a 14-day chart and, since version 1.6.0, three cards under it: the latest successful and failed sign-ins with the address and its country, the countries the last seven days of attacks came from, and the top blocked IPs for 24 hours, 7 days or 30 days. The countries are looked up in a small file that ships inside the plugin, so no address is sent to a lookup service.

The security digest is an email, weekly by default (a clear card coloured by the threat level, with a plain-text version for mail apps that prefer text), set under User Security → Emails (Send a digest). It reports the threat level, failed sign-ins, requests refused by existing blocks, new blocks, the five busiest IP addresses, the five most-targeted accounts and, since version 1.7.0, the sign-ups that were accepted and refused. When nobody failed to sign in, it says so, which also shows the protection was running. The first digest arrives one full period after the schedule is first seen as switched on, and it needs WP-Cron.

Since version 1.5.0 the emails have a screen of their own, User Security → Emails: a master switch, the address they go to, the nine alerts each with a switch and a line that explains when it is sent, the repeat window, the accounts to watch and the digest schedule, plus the sign-in code and the test email that go to the person signing in. If the alerts are too much for a busy site, that is the place to thin them out, and the master switch turns all of them off at once. The same version made every screen of the plugin usable on a phone, so a block can be lifted or an alert switched off from wherever the email reaches you.

Further reading

Every setting, WP-CLI command and alert is covered in the full documentation. Browse all plugins for more.

User Security Guard for WordPressStop brute-force logins, bots, password sprays and fake sign-ups, even when they change address on every request
View plugin →
More tutorialsKeep reading.
How to Send WordPress Email Through SMTP and Keep an Email Log → How to Create Product Collections in WooCommerce → How to Schedule WordPress Backups to Google Drive or Dropbox →
WPExpertsHub

WordPress and WooCommerce plugins, custom development and technical support.

support@wpexpertshub.com

Products

  • All plugins
  • WooCommerce plugins
  • WordPress plugins
  • Free plugins

Services

  • WordPress development
  • WooCommerce development
  • Maintenance & optimization
  • Migration & security
  • API & integrations

Resources

  • My downloads
  • Documentation
  • Blog
  • Plugin support
  • Refund policy

Company

  • Services
  • Contact
  • My account
© 2026 WpExperts Hub. All rights reserved.
  • Privacy Policy
  • Terms of Service
  • Refund Policy