Skip to content

How to fix "429 Too Many Requests" in WordPress

A 429 means something counted the requests from one address and decided there were too many in a short time. WordPress itself sends it only for comments posted seconds apart. Otherwise it comes from the host, a firewall or a plugin. Wait, then find out which one answered.

By
WP Ministry
Published
Tested on
WordPress 7.1.3, PHP 8.3.35

In short

  • A 429 is a limit, not damage. Nothing is lost, and it clears when the count starts again.
  • The answer often says how long to wait, in a Retry-After header, and who sent it.
  • WordPress itself sends a 429 only for comments posted within 15 seconds of each other and for its post-by-email check.
  • If only you see it, your own address sent too much. If everyone does, the limit is too low or the server takes all visitors for one.
  • Not every rate limit answers 429. nginx's answers 503 unless it is set otherwise, and Wordfence's answers 503.

"429 Too Many Requests" means that whatever answered has been counting requests and decided that one visitor sent too many in a short time. A visitor is usually an IP address. It is a limit, not a fault: once the count starts again, the same request works.

Nothing has been lost. Posts, settings and orders are untouched. A change you were saving when the 429 appeared may not have gone through, so check it once you are back in.

Who sends a 429

WordPress's own code sends this status in two places only: when a comment follows another within 15 seconds, and when its post-by-email address, wp-mail.php, is checked more than once in five minutes. It never sends one for loading a page, logging in or working in the dashboard. Any other 429 comes from one of these:

  • The host or the web server. nginx can limit requests by address.
  • A firewall or CDN in front of the site. Cloudflare's rate limiting rules answer 429 by default, with a page that says "Error 1015" and "You are being rate limited".
  • A plugin that has a rate limit of its own.
  • A service your site calls, answering the site and not the visitor.

A limit does not always answer 429. nginx answers 503 unless its limit_req_status setting names another code. Wordfence's rate limiting also answers 503, on a page headed "Your access to this site has been limited by the site owner". Apache's mod_ratelimit limits the speed of a response, not the number of requests.

Work out who is being limited

  • Only you, mostly in the dashboard? Load the site on your phone over mobile data. If it loads there, your own address is over the limit. Start with the first three fixes.
  • Every visitor? The limit is too low, or the server takes all visitors for one address.
  • Someone sending a comment? That one is WordPress itself. Go to the comment fix.
  • No error page, but a plugin reports a 429? A service is limiting the site. Go to the last fix.

Where it goes wrong

A page request passes through each of these in turn. This one comes from the web server.

  1. Browser
  2. DNS
  3. HTTPS
  4. CDN or firewall
  5. Web server (this error comes from here)
  6. PHP
  7. WordPress
  8. Database and files

What causes it

How to fix it

Wait, and read who sent the 429

  • Easy
  • No risk
  • About 5 minutes
  • Steps tested on WordPress 7.1.3
  1. Step 1: Stop reloading

    Each reload is one more request, and it can keep the count above the limit.

  2. Step 2: Ask for the answer's headers

    From a terminal, with your own address in place of example.com:

    The first line is the status. Your browser's developer tools show the same headers on their network panel.

    bash
    curl -sI https://example.com/
  3. Step 3: Look for Retry-After

    A 429 may carry a Retry-After header. A number is how many seconds to wait. A date is the time after which to try again. Wait that long, then load the page once.

  4. Step 4: Read who answered

    The Server header describes the software that answered. A cf-ray header means the answer came through Cloudflare. The page's own words often carry the name of the plugin or service.

The HTTP status and redirect checker shows what an address answers, with its status code. It asks from its own server, not from your connection. If it gets a 200 while you get a 429, the limit is on your address alone.

Cut down the requests your own browser sends

  • Easy
  • No risk
  • About 10 minutes
  1. Step 1: Close the dashboard tabs you are not using

    A tab in use asks admin-ajax.php for news about once a minute, and more often on a screen where a post is being edited. A tab left alone asks less often and in time stops, so the tabs that count are the ones people are working in.

  2. Step 2: Find what repeats

    Open your browser's developer tools on the network panel and leave one dashboard screen open for a minute. Look for the same address asked for again and again. A request to admin-ajax.php carries a field called action. heartbeat is WordPress's own. Any other name was chosen by a plugin.

  3. Step 3: Deal with the plugin

    If a plugin asks every few seconds, look in its settings for how often it refreshes, or switch it off and see whether the 429 stops.

  4. Step 4: Stop guessing a password

    Failed logins are requests too. Reset the password from the login screen's link instead of trying again.

Have the dashboard check in less often

  • Takes care
  • Low risk
  • About 10 minutes
  • Steps tested on WordPress 7.1.3

WordPress's Heartbeat script accepts a minimalInterval setting. Its own notes say the setting is for hosts that cannot handle frequent requests, and that a value above 120 seconds limits or switches off features such as post locks.

  1. Step 1: Open wp-content/mu-plugins

    Create the folder if it is not there. WordPress loads every PHP file that sits directly in it, and such a file can only be switched off by removing it.

  2. Step 2: Create slow-heartbeat.php with this in it

    wp-content/mu-plugins/slow-heartbeat.php
    <?php
    // Have the dashboard check in no more than once every two minutes.
    add_filter( 'heartbeat_settings', function ( $settings ) {
    	$settings['minimalInterval'] = 120;
    	return $settings;
    } );
  3. Step 3: Reload the dashboard

    Every dashboard screen opened from now on waits at least two minutes between its regular check-ins.

To undo it: Delete the file.

Raise the limit where it is set

  • Takes care
  • Low risk
  • About 20 minutes
  1. Step 1: In a security plugin

    Open its rate limiting settings and raise the number of requests it allows, or lengthen the period it counts over. The plugin's documentation names the settings.

  2. Step 2: In Cloudflare

    Review the thresholds of your rate limiting rules. Cloudflare's own advice for a rule that counts over a very short period, such as one second, is to lengthen the period to 10 seconds.

  3. Step 3: On your own nginx

    The limit is the rate in limit_req_zone and the burst in limit_req. With no burst, nginx refuses every request that arrives faster than the rate. Raise the rate or allow a burst, then reload nginx.

  4. Step 4: Anywhere else, ask the host

    Send them the time, the address of the page and your own IP address. Ask which limit answered, and whether it can be raised or your address exempted.

To undo it: Set the old numbers again.

Switch the limiting plugin off to get back in

  • Takes care
  • Low risk
  • About 10 minutes
  • Steps tested on WordPress 7.1.3

Use this when a plugin's limit keeps you out of the dashboard, so that you cannot reach its settings.

With WP-CLI, use the plugin's folder name:

bash
wp plugin deactivate plugin-folder-name

Without WP-CLI, how to fix the 403 Forbidden error shows how to switch a plugin off by renaming its folder.

If the 429 is gone, that plugin was the one counting. Activate it again and raise its limit straight away. If the 429 is still there, the limit is not the plugin's. Ask the host.

To undo it: Activate the plugin again.

Tell the server where to find the visitor's address

  • Advanced
  • Low risk
  • About 20 minutes

Look at the server's access log. If every request in it comes from the same address, the server is recording the proxy and not the visitor.

The proxy passes the visitor's address on in a header. The web server has to be told which header to read and which addresses to believe it from. 203.0.113.10 stands for your proxy's address. Your CDN's documentation gives its header and its addresses. Cloudflare's header is CF-Connecting-IP.

RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 203.0.113.10
Apache accepts these in the server's main configuration or a virtual host, not in .htaccess. On nginx they go in the http or server block.

On Apache this needs mod_remoteip, and on nginx a build that includes the realip module. On shared hosting, ask the host to do it.

To undo it: Remove the lines and reload the web server.

Wait 15 seconds between comments

  • Easy
  • No risk
  • About 5 minutes
  • Steps tested on WordPress 7.1.3

"You are posting comments too quickly. Slow down." is WordPress's own 429. WordPress compares each new comment with the last one from the same address or the same email address, and refuses it if the two are less than 15 seconds apart.

  1. Step 1: Wait, then send the comment again

    Fifteen seconds is enough. Logged-in administrators and moderators are never held to this, so you will not see it while testing as yourself.

  2. Step 2: If people who sent one comment each see it, check the addresses

    WordPress takes a commenter's address straight from the web server. The Comments screen shows it under each author's name. With WP-CLI:

    People in one office can truly share an address. If different people's comments all carry the address of your proxy or CDN, the server takes every visitor for the same one. Use the fix above.

    bash
    wp comment list --number=10 --fields=comment_ID,comment_author,comment_author_IP,comment_date_gmt

Slow the site's own calls to an outside service

  • Takes care
  • Low risk
  • About 20 minutes
  1. Step 1: Find which plugin reports it

    Look in that plugin's settings screen or its log for the name of the service that refused.

  2. Step 2: Read the service's limit

    Its documentation says how many requests it accepts and over what period. If its answer carries Retry-After, that is how long to wait.

  3. Step 3: Make the plugin ask less often

    Lower how often it syncs or refreshes. If it has no such setting, tell its author. WordPress's guidance to plugin authors is to keep a copy of an answer and reuse it until it needs refreshing.

When to get help

If the 429 comes back after you have waited, none of your plugins sets a limit and the host says the limit is not theirs, something between the visitor and the server is counting requests and nobody has named it. Finding it means reading response headers and server logs side by side, which needs access to the server.

Common questions

Is a 429 the same as a 403?

No. A 429 is a count that starts again by itself. A 403 is a refusal that stays until the rule behind it changes or a block is lifted. How to fix the 403 Forbidden error covers that one.

My access log is full of 429s but the site works. Is something wrong?

Not by itself. Each line is the limit refusing a request. If the addresses are not yours and the requests are for wp-login.php or xmlrpc.php, they are likely to be programs trying passwords, which is what a limit is for. How to protect WordPress from brute force attacks covers the login page, and how to disable XML-RPC covers the other file.

Does WordPress limit logins by itself?

No. Its own code answers 429 only for comments and post by email. A limit on failed logins comes from a security plugin, a firewall or the host.

More on this subject

Would you rather we fixed it?

Quick Fix is $49. One issue, one site, up to about an hour. No fix, no fee. 30-day warranty. It starts with a free diagnosis.