You open your site, or hit an API, and get "429 Too Many Requests." Nothing is down. The server is simply telling you (or your visitors) to slow down. The annoying part is that a 429 can come from five different places, and fixing the wrong one wastes an afternoon. Here's how we track it down on SkyServer hosting and VPS plans.

What a 429 actually means

HTTP 429 is a rate-limit response. Something in the chain counted too many requests from one client in a short window and refused the rest. It isn't a crash, and it usually isn't a bug in your code. The question is who said no.

Where it comes fromTypical clueWho fixes it
Nginx limit_req on your VPSEntries in the error log: "limiting requests"You
ModSecurity / CSF / cPHulk ruleBlock appears in the firewall or ModSecurity audit logYou or support
Cloudflare rate-limiting or bot rulesResponse has a cf-ray headerYou, in the Cloudflare dashboard
A WordPress plugin or security toolOnly wp-login.php, XML-RPC or REST routes failYou
A third-party API (payment, maps, email)Error appears in your PHP log, not in the browserThe provider's limits

Step 1: Read the response headers

Before touching any config, look at what came back. From any terminal:

curl -sI https://example.com/ | head -20

Check three things:

  • Retry-After: if present, it tells you how many seconds the limiter wants you to wait. That's a strong hint the limit is deliberate and time-based.
  • server / cf-ray: cf-ray means Cloudflare answered. server: nginx without it points to your own origin.
  • The body: a plain nginx-styled page, a Cloudflare-branded page, and a WordPress plugin message all look different.

Step 2: If it's Nginx on your VPS

Look for a rate-limit zone in your config:

grep -Rn "limit_req" /etc/nginx/
tail -n 50 /var/log/nginx/error.log | grep -i limiting

A typical setup looks like this:

limit_req_zone $binary_remote_addr zone=perip:10m rate=5r/s;

location / {
    limit_req zone=perip burst=20 nodelay;
    limit_req_status 429;
}

The usual cause of surprise 429s is a rate that's fine for one visitor but too tight for a page that loads 40 assets. A browser fetching CSS, JS and images in parallel can burn through 5r/s with a small burst in a moment. Two sensible fixes:

  • Raise burst (try 50–100) so a single page load fits comfortably.
  • Apply the strict limit only to expensive paths such as /wp-login.php and /xmlrpc.php, not to the whole site.

Also check whether everyone shares one IP. Behind a load balancer or Cloudflare, $binary_remote_addr is the proxy's address, so all your visitors count as one client. Restore the real IP first (the real_ip_header CF-Connecting-IP; directive plus set_real_ip_from for Cloudflare's ranges), then reload:

nginx -t && systemctl reload nginx

Step 3: If it's a firewall or ModSecurity

On cPanel servers, CSF/LFD and ModSecurity can answer with 429 or a similar block when an IP trips a threshold. Check whether your own IP is listed:

csf -g YOUR.IP.ADDRESS
grep YOUR.IP.ADDRESS /var/log/lfd.log | tail

If it's blocked, unblock and whitelist it (csf -dr YOUR.IP then csf -a YOUR.IP). If you're on shared hosting and can't run these, open a ticket with your public IP and the time of the error, and we'll check the logs for you.

Step 4: If it's Cloudflare

A response with a cf-ray header means the limit sits in front of your server. In the Cloudflare dashboard, open Security → Events and filter by the time you saw the error. The event shows which rule fired. Common culprits:

  • A rate-limiting rule written too broadly (for example, counting every request to /*).
  • Bot Fight Mode challenging your own monitoring tool or a cron-driven script.
  • A WAF rule that matches your API path.

Narrow the rule's expression or add an exception for your office IP, then retest. Don't turn the protection off entirely.

Step 5: If it's WordPress itself

When only login, XML-RPC or the REST API return 429, the cause is almost always a security plugin's brute-force protection or a rate-limiting feature in an SMTP/API plugin. Try this:

  1. Rename the suspect plugin's folder over SFTP or File Manager (for example wp-content/plugins/security-plugin to security-plugin-off).
  2. Retest. If the 429 disappears, you've found it.
  3. Re-enable the plugin and loosen its threshold, or whitelist your IP in its settings.

With WP-CLI you can do the same quickly: wp plugin deactivate plugin-slug.

Step 6: If your site is the one receiving 429s from an API

Sometimes the error is in your PHP log because your code hammered an external service. Payment gateways, geocoding and email APIs all throttle. The fix belongs in your code:

  • Cache responses instead of calling the API on every page view.
  • Honor the Retry-After header and back off (wait, then retry with a growing delay).
  • Move bulk calls into a queue or a cron job that spreads them out.

Prevention

  • Set limits per path, not per site. Be tight on login and XML-RPC, relaxed on static files.
  • Serve static assets from cache or a CDN so they don't count against origin limits.
  • Whitelist your own office IP and uptime monitors.
  • Log rate-limit hits and review them weekly. A spike often points to a bot, and that's worth blocking at the firewall.
  • Test after any change with curl -sI in a loop to confirm the limit behaves as you expect.

Frequently Asked Questions

Is a 429 error bad for SEO?

A short burst isn't a problem. If Googlebot keeps getting 429s for days, it will crawl less. Check your limits aren't catching search crawlers, and verify the bot's IP before whitelisting it.

How long does a 429 block last?

It depends on the limiter. Nginx zones recover within seconds. Firewall blocks like CSF can last from minutes to a day. The Retry-After header, when sent, tells you directly.

Should I just disable rate limiting?

No. It protects your server from scrapers and password-guessing bots. Tune it instead: raise the burst, scope it to the right paths, and whitelist trusted IPs.

Why do I get 429 only from my home or office network?

Your IP probably got flagged by a firewall or plugin after repeated failed logins or fast requests. Check the firewall or plugin block list, or try from mobile data to confirm.

Can SkyServer support raise the limits for me?

On shared hosting, yes. Open a ticket with the URL, the time of the error and your public IP, and we'll check what fired.