Request failed with status code 429: Meaning, diagnosis, and fixes
Aug 20, 2026 · Troubleshooting · 9 min read
An inventory sync can run normally until several workers begin sending requests at once. Axios then reports Request failed with status code 429, and the updates stop. The same status can appear on a login form after several submissions. The wording is identical, but the first case may involve request rate, concurrency, or an API-key quota, while the second may be an account-level authentication throttle. Immediate retries add more rejected traffic, and repeating a state-changing request can also create duplicate work.
HTTP 429 means the server received the request but refused to process it because a rate limit was reached. Axios is only reporting that response. It did not create the limit, and suppressing the error will not remove it. The response body, headers, and provider documentation are what separate one case from the other.
What does error code 429 mean?
HTTP 429 is the Too Many Requests client error response. RFC 6585 defines it as rate limiting: the server has counted too many requests from the actor or resource it identifies within a period of time. The response may include Retry-After to tell the client how long to wait.
The phrase “user has sent too many requests” is easy to misread. The “user” is whatever identity the server counts. A service may count a source IP, an authenticated account, an API key or access token, a cookie or session, one endpoint, active concurrency, or a provider quota. It may also enforce more than one of these limits at the same time.
The status code does not reveal which dimension fired. That is why 429 rate limit requests exceeded describes the category of the error, not the complete diagnosis.
Diagnose the limit before choosing a fix
Start with the response rather than a list of generic browser fixes. Current Axios error-handling documentation separates three cases:
error.responseexists: the server sent a response outside Axios’s accepted status range. A 429 belongs here.error.requestexists buterror.responsedoes not: the request was sent, but no response arrived. That is a network or transport path, not a confirmed 429 response.- Neither exists: Axios could not finish setting up the request.
Log only the diagnostic fields you need. Do not print authorization headers, cookies, full tokens, or personal data.
import axios from "axios";
async function fetchItems() {
try {
const response = await axios.get("https://api.example.com/items");
return response.data;
} catch (error) {
if (axios.isAxiosError(error) && error.response) {
const { status, data, headers } = error.response;
console.error({
status,
retryAfter: headers["retry-after"],
errorCode: data?.code ?? data?.error,
message: data?.message,
});
}
throw error;
}
}

Axios lowercases response header names, so read Retry-After as headers["retry-after"].
Next, compare what you observe with the likely limit dimension:
| What you observe | What it can indicate | Correct next action | How to verify |
|---|---|---|---|
Retry-After is present |
A temporary window with a server-supplied wait | Wait at least that long | Send one controlled request after the interval |
| The body names a quota, account, token, or endpoint | A provider-specific limit | Read that provider’s quota documentation and usage data | Confirm the named quota has reset or capacity is available |
| Failures begin when several workers run together | A burst or concurrency limit | Reduce parallelism and put requests through a queue | Increase load slowly and watch the 429 rate |
| The first request from one process returns 429 | A shared IP, key, account, application, or earlier quota use is possible | Check other clients and shared credentials before changing code | Correlate provider logs and usage for the same identity |
| A login endpoint returns 429 | Authentication throttling or a temporary lockout is possible | Stop attempts and use the service’s recovery path | Retry once after the stated wait or after support clears the issue |
| A different IP still fails with the same account or key | The limit may not be IP based | Investigate the account, key, session, or provider quota | Test only through documented provider controls |
These branches narrow the diagnosis, but they do not prove which limit fired. Confirm the cause with the response body, headers, provider documentation, and server-side logs.
Read Retry-After correctly
Do not assume Retry-After is always a number. RFC 9110 allows two formats:
Retry-After: 120
The client should wait 120 seconds from the moment it receives the response.
Retry-After: Fri, 21 Aug 2026 14:30:00 GMT
Here, the client should wait until the timestamp in the header. It should support both formats.
If the header is missing, check the provider’s documentation and error body. If neither supplies a reset time, use a finite retry policy with exponential backoff and jitter. Do not pick a fixed sleep value and retry forever. A fixed delay can be too short for one provider and unnecessarily slow for another.
Fix 429 in Axios without a retry storm
The following helper retries GET requests only. It honors Retry-After first. When the header is absent or invalid, it uses capped exponential backoff with jitter. Four retries means no more than five total attempts.
import axios from "axios";
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
function parseRetryAfterMs(value) {
if (!value) return null;
const text = String(value).trim();
if (/^\d+$/.test(text)) {
return Number(text) * 1000;
}
if (!/[A-Za-z]{3}/.test(text)) return null;
const retryAt = Date.parse(text);
if (Number.isNaN(retryAt)) return null;
return Math.max(0, retryAt - Date.now());
}
async function getWith429Retry(url, config = {}) {
const maxRetries = 4;
const baseDelayMs = 1000;
const maxDelayMs = 30000;
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
try {
return await axios.get(url, config);
} catch (error) {
const status = error.response?.status;
const isLastAttempt = attempt === maxRetries;
if (status !== 429 || isLastAttempt) {
throw error;
}
const retryAfterMs = parseRetryAfterMs(
error.response?.headers?.["retry-after"],
);
const backoffCapMs = Math.min(
maxDelayMs,
baseDelayMs * 2 ** attempt,
);
const delayMs =
retryAfterMs ??
Math.floor(backoffCapMs / 2 + Math.random() * (backoffCapMs / 2));
console.warn(
`HTTP 429. Retry ${attempt + 1}/${maxRetries} in ${delayMs} ms.`,
);
await sleep(delayMs);
}
}
}
const response = await getWith429Retry(
"https://api.example.com/items",
{ timeout: 10000 },
);
console.log(response.data);

Backoff increases the upper bound of the wait after each failure. Jitter chooses a different delay inside that bound so many workers do not wake up together. A retry cap stops a persistent quota or configuration problem from becoming an endless loop. This follows the principles in AWS guidance on controlling retries.
Do not copy this automatic retry behavior to every POST, checkout, payment, account update, or other state-changing request. HTTP semantics warn against automatically retrying a non-idempotent operation unless the client knows it is safe to repeat or can determine that the first attempt was not applied. Use the provider’s documented idempotency mechanism, then verify the operation’s final state.
Changing Axios validateStatus is not a fix. It can make Axios resolve a promise for status 429, but the server still rejected the request. You would only move the same handling logic from catch into the normal response path.
Choose the fix for your context
API quota or rate limit
Read the provider’s response body and quota documentation. Check whether the limit applies per second, minute, billing period, token, account, or endpoint. Reduce the matching demand. That may mean pacing calls, batching supported operations, removing duplicates, caching reusable GET results, or requesting more capacity through the provider’s approved process.
Do not create extra keys or accounts to evade a published quota. That hides demand instead of controlling it. Use the provider’s approved capacity process instead.
Burst or concurrency limit
An application can stay below an average requests-per-minute limit and still exceed a shorter burst or concurrency limit. Put outbound calls behind a shared queue or worker pool. Set an explicit concurrency ceiling and let one component own the retry budget. Otherwise each worker can add its own retries to already excessive traffic.
Verify this change gradually. Start with low concurrency, confirm requests succeed, then raise the level in small steps while watching response codes and provider usage.
Browser or app session
Stop refreshing the page and close duplicate tabs or app instances that may be polling the same endpoint. Wait for the service’s stated reset period. Check its status page or support channel if ordinary use continues to fail.
Clearing cookies is conditional, not routine. Use it when the service’s documented recovery asks you to reset the session. It will sign you out, and it does not reset an IP, account, API-key, application, or provider quota.
First request already returns 429
“First request” describes the first request you observed in one process. It does not establish that the limited identity had no earlier traffic. That identity may also be used by another worker, browser tab, server, teammate, customer behind the same public IP, or application sharing the same credential.
Check usage at the same scope named by the provider. If the response names an account quota, inspect account usage. If it names a key, locate every client using that key. If it names an IP rule, check other traffic leaving through the same public address. Until that evidence exists, changing the network is a guess.
If you failed to log in with status 429
A failed to log in status 429 message needs a different response from an API batch job. Login throttling is a security control that slows password guessing and other automated attacks. The OWASP Authentication Cheat Sheet describes maximum-attempt controls and temporary account lockout as common defenses.
If you are the user:
- Stop submitting the form. Repeated attempts can extend or retrigger a lockout.
- Wait for the period shown by the service.
- Confirm that your password manager is using the current credential.
- Use the official password-reset or account-recovery flow if the credential is uncertain.
- Contact the service if the error continues after the wait period.
If you operate the login system, inspect account-bound and network-bound throttles separately. Check for broken clients that submit the form more than once, repeated background authentication, and distributed attempts against one account. Keep recovery available without disclosing which internal limit fired.
Do not rotate IPs to get around a login throttle. The counter may be attached to the account, and bypassing an authentication control is not a safe troubleshooting method.
When a proxy can help with 429
A proxy is relevant only after three conditions are true:
- The workflow is authorized, such as permitted collection of public data.
- Response evidence or provider documentation shows that the rate limit is keyed to source IP.
- The total request pattern remains within the target’s allowed rate and access rules.
If the 429 is tied to an account, API key, session, endpoint, application, or provider quota, changing the IP leaves that limited identity in place. Even with an IP-based limit, lower the request rate and honor Retry-After. Rotation is not a substitute for backoff.
For an authorized public-data workflow that has confirmed an IP-scoped restriction, the Rola IP rotating residential proxy setup documents request-based rotation and session configuration. Choose the setting that matches the IP continuity required by that specific branch. See the Scrapy rotating proxies setup guide and the web scraping use case for related implementation context. Neither option changes account-level or API-key quotas.

Prevent the error from returning
Once requests work again, fix the demand pattern that caused the incident.
- Put request generation behind a queue with an explicit concurrency ceiling.
- Deduplicate identical work and cache reusable GET responses where the provider permits it.
- Track provider quotas at the same scope used by the limit: account, key, endpoint, resource, or IP.
- Centralize retries so nested libraries and workers do not each retry the same failure.
- Record status, provider error code, retry delay, attempt count, endpoint, and a redacted request identifier.
- Set a maximum retry count or elapsed-time budget, then surface a controlled failure to the caller.
- Test burst and concurrency behavior before production traffic reaches the limit.
After the change, run the normal workload long enough to confirm that requests keep succeeding, retry volume remains bounded, and usage stays below the documented limit. A single successful request is not enough.
Summary
Request failed with status code 429means the server returned a rate-limit response; Axios only surfaced it.- Inspect the response body and headers before choosing a fix.
- Honor
Retry-After. If it is absent, use a finite exponential backoff policy with jitter for requests that are safe to repeat. - Match the fix to the limited identity. IP, account, key, session, endpoint, concurrency, and provider quotas are different problems.
- Treat login throttling as a security control. Stop attempts and use the official recovery path.
- Use proxy rotation only for an authorized workflow with evidence of an IP-scoped limit, and keep backoff and total request pacing in place.