# 429 Too Many Requests

> You sent more requests than the server allows in a given period, so it's refusing you until the window resets.

Source: https://cwp.sg/errors/429-too-many-requests/  
Author: Ben Johnson  
Last verified: 2026-08-04

**Also seen as:** Too Many Requests, rate limited, 429 error

## What it means

`429` is a rate limit. Something counted your requests — by IP, by API key, or by account — decided there were too many in too short a time, and is turning you away deliberately.

This is different from [508](/errors/508-resource-limit-is-reached/) or [503](/errors/500-internal-server-error/). Those mean the server is out of capacity. `429` means the server has plenty of capacity and has decided **you specifically** have had enough for now.

A well-behaved `429` includes a header telling you how long to wait:

```
Retry-After: 60
```

Check for it before guessing. It's the difference between backing off correctly and hammering a server that's already annoyed with you.

## Why it happens

### An API you're calling has a rate limit

Nearly every third-party API caps requests per minute or per hour. Code that loops through records and calls an API for each one will hit this quickly.

The cap is often lower than you'd expect on free tiers — sometimes a handful of requests per second.

### A security plugin is rate-limiting your visitors

WordPress firewall plugins rate-limit login attempts and sometimes normal browsing. Legitimate visitors behind a shared IP — an office, a school, a mobile carrier's NAT — can trigger it collectively.

### You're being rate-limited while developing

Refreshing rapidly while debugging, or a script in a tight loop against your own site, will trip your host's protection. This looks alarming and is usually just you.

### A crawler hit an expensive endpoint

A scraper walking every filter combination on a shop, or a search endpoint, can trigger rate limiting that then affects real visitors sharing that path.

## How to fix it

### 1. Read the Retry-After header

```
curl -sI https://api.example.com/endpoint | grep -i -E 'retry-after|x-ratelimit'
```

Many APIs also send `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`. Those tell you exactly how much budget you have left and when it resets, which is far better than guessing.

### 2. Back off exponentially, and respect the header

Retrying immediately makes things worse. Wait longer after each failure:

```php
$delay = 1;
for ($attempt = 0; $attempt < 5; $attempt++) {
    $response = call_api($url);

    if ($response['status'] !== 429) {
        return $response;
    }
    // Honour the server's own instruction when it gives one
    $wait = $response['headers']['retry-after'] ?? $delay;
    sleep((int) $wait);
    $delay *= 2;   // 1, 2, 4, 8, 16
}
```

Note that sleeping inside a web request burns your execution time budget — see [maximum execution time exceeded](/errors/maximum-execution-time-exceeded/). For anything more than a brief retry, move the work to a background job.

### 3. Cache API responses

The best way to stay under a rate limit is to make fewer calls. If the data doesn't change every second, don't fetch it every second:

```php
$cache = __DIR__ . '/cache/rates.json';
if (!file_exists($cache) || filemtime($cache) < time() - 3600) {
    file_put_contents($cache, call_api($url));
}
$data = json_decode(file_get_contents($cache), true);
```

One call an hour instead of one per visitor usually removes the problem entirely.

### 4. Batch requests where the API supports it

Many APIs accept multiple items in one call. Ten items in one request is one request against your limit, not ten. Check the documentation before writing a loop.

### 5. Whitelist yourself in your own firewall

If a security plugin is rate-limiting you while you work, add your IP to its allow-list rather than turning the protection off. Turning it off entirely and forgetting is how sites get brute-forced.

## On CWP hosting specifically

CWP enforces a daily request cap per account — 50,000 on free plans, resetting at midnight UTC. Crossing it serves a limit page rather than your site until the reset.

Most accounts that hit it are being crawled rather than visited. Check your access logs for the top user agents before assuming it's real traffic; blocking a scraper in [.htaccess](/tools/htaccess-generator/) is usually the whole fix.

## When this means you have outgrown free hosting

Consistently hitting the daily request cap with genuine human traffic is a good problem and a clear upgrade signal.

Rule out bots first. In our experience the majority of accounts that hit the cap are serving crawlers, not people, and blocking a handful of user agents brings usage back under it.

---

Content Website Platform (cwp.sg) operates the free hosting it writes about; see https://cwp.sg/about/ for the methodology and the commercial disclosure.
