Connection errors are a common occurrence in HTTP requests. Especially in web scraping where servers may impose strict rate limits or block repeated requests. To handle this — retrying is often an effective strategy.
In this guide, we’ll explore how to retry in Axios, a widely used HTTP client for JavaScript (NodeJS, Deno and Bun). Why retries are essential for error handling and best practices for retry logic. How to analyze status codes and implement exponential backoff and overview common troubleshooting scenarios.
Axios is a popular, promise-based HTTP client for JavaScript and all of it's flavors (NodeJS, Bun, Deno). It simplifies the process of sending HTTP requests through convenient developer expererience features and for this reason it is widely used in both browser and server environments.
Axios is a powerful and versatile HTTP client library that simplifies making API requests in JavaScript applications. Below are some of its standout features:
async/await
for cleaner, more readable code.Axios has become a favorite among developers due to its simplicity, flexibility, and feature-rich design. Axios provides a reliable and efficient way to handle HTTP requests. Here’s why developers consistently turn to this library:
These features make Axios an indispensable tool for many developers, empowering them to write efficient, maintainable, and scalable code with ease.
Retries are critical when dealing with unpredictable environments like web scraping or API integrations.
When making HTTP requests, you might encounter:
Retries help ensure that your application remains functional even in these scenarios.
Next, let's explore different retry methods in Axios.
For developers who prefer control, manual retry logic is a great way to understand how retries work. Here’s an example in nodejs and axios:
// import axios
const axios = require("axios");
async function fetchWithRetry(url, retries = 3) {
let attempt = 0;
// use for loop to retry 3 times at most
while (attempt < retries) {
try {
const response = await axios.get(url);
return response.data; // Success: Return data
} catch (error) {
attempt++;
console.log(`Attempt ${attempt} failed. Retrying...`);
if (attempt === retries) {
throw error; // Fail after exhausting retries
}
}
}
}
This example demonstrates implementing manual retry logic by retrying a request within a while loop. We make our request and retry any thrown errors blindly which is not ideal but it's a good starting point.
For more complex applications, axios-retry simplifies retry logic with minimal setup and great default options.
This library automatically retries requests that fail due to specified conditions.
const axios = require("axios");
const axiosRetry = require("axios-retry");
// Configure axios-retry
axiosRetry(axios, {
retries: 3, // Number of retries
retryDelay: axiosRetry.exponentialDelay, // Use exponential backoff
// attach callback to each retry to handle logging or tracking
onRetry: (err) => console.log(`Retrying request: ${err.message}`),
// Specify conditions to retry on, this is the default
// which will retry on network errors or idempotent requests (5xx)
retryCondition: (error) => axiosRetry.isNetworkOrIdempotentRequestError(error)
});
axios
.get("https://example.com")
.then((response) => console.log(response.data))
.catch((error) => console.error(error));
The axios-retry
library automates retry logic with configurable conditions. In this example, we:
While the default retry conditions are suitable for most cases, you can customize them to fit your specific needs so let's take a look at that next.
Effective retry logic ensures that retries are executed under appropriate conditions without overwhelming the server or violating its rate-limiting policies.
By default we should definitely retry all network errors and 5xx status codes. Though, you can also customize the retry conditions to fit your specific needs which is especially applicable in web scraping.
To start, we can expand the default retry conditions to include more http status codes.
When designing retry logic, it’s essential to focus on status codes that indicate temporary issues. These include:
Status Code | Description | Why Retry? |
---|---|---|
408 | Request Timeout | Indicates the server didn’t receive the request in time, likely due to network issues. Retry as the request might succeed on subsequent attempts. |
500–599 | Server Errors | Covers various server-side errors (e.g., 500 Internal Server Error, 503 Service Unavailable). These are often temporary and resolve after some time. |
429 | Too Many Requests (Rate Limiting) | The server is enforcing rate limits. Retry after a delay, adhering to the Retry-After header if provided. |
Retries should not be used for client-side errors (e.g., 400 Bad Request, 401 Unauthorized) because these typically indicate a problem with the request itself that won’t be resolved by retrying.
Retrying failed requests immediately can lead to unecessary server overload and eventually client being blocked. To avoid this, the best delay strategy is to implement exponential backoff — a strategy where the delay between retries increases exponentially.
Exponential backoff is a critical technique for managing retries effectively in scenarios where network instability or server-side issues occur.
In axios-retry
, you can configure exponential backoff like this:
const axiosRetry = require("axios-retry");
axiosRetry(axios, {
retries: 5, // Number of retry attempts
retryDelay: (retryCount) => {
return Math.pow(2, retryCount) * 1000; // 1s, 2s, 4s, 8s, etc.
},
});
This setup uses axios-retry
to implement exponential backoff, doubling the delay with each retry (1s, 2s, 4s, etc.). You can adjust the multiplier to fit your needs, and the retry limit prevents infinite loops, ensuring reliable and efficient error handling.
When a server returns a 429 Too Many Requests or 503 Service Unavailable status code, it may include a Retry-After
header. This header specifies the amount of time (in seconds) the client should wait before making another request.
The Retry-After header provides crucial guidance from the server on when to attempt the next request, helping your application avoid unnecessary retries.
Retry-After
header ensures your application aligns with the server’s rate-limiting policies.In scenarios like web scraping or API integrations, relying solely on retries may not suffice. Servers often block requests based on repetitive patterns, IP addresses, or user-agent headers.
Proxy rotation is a technique used to mitigate these restrictions by dynamically changing the IP address for each request.
You can learn more about How to Rotate Proxies in Web Scraping in our dedicated article:
Retries are a crucial mechanism in software systems to improve reliability, especially when dealing with external dependencies like APIs, web services, or databases. These systems are often prone to temporary failures caused by network instability, server issues, or rate limiting.
Here’s a more detailed look at why retries are important:
Handling Transient Errors: Many errors, such as timeouts or temporary server overloads, are transient and resolve themselves after a short period.
Dealing with Unreliable Networks: In scenarios like mobile applications or IoT systems, unstable network connections are common. Retrying failed requests can help ensure data is sent or received once the connection stabilizes.
Adhering to Rate Limits: APIs often impose limits on the number of requests allowed within a given timeframe (e.g., 100 requests per minute).
Preventing Data Loss: In critical operations, such as financial transactions or order processing, a failed request without a retry could result in data loss or incomplete operations. Retries provide an additional layer of assurance.
Retries act as a safety net, ensuring applications remain resilient and functional even in unpredictable environments, making them a fundamental part of error-handling strategies.
Retry logic is an essential part of building resilient applications, but its implementation must be carefully designed to avoid introducing new issues. If improperly configured, retries can exacerbate problems rather than solving them.
Here’s a closer look at why retry logic might fail and how to address these challenges effectively.
Common Challenges with Retry Logic:
Challenge | Cause | Impact | Solution |
---|---|---|---|
Insufficient Backoff | Retries are attempted too quickly, overwhelming the server or causing blocks. | Repeated failures, server bans, or degraded application performance. | Implement exponential backoff to gradually increase retry delays. |
Lack of Proxy Rotation | Repeated requests from the same IP address trigger server blocks. | Access denial, ineffective retries. | Use proxy rotation to distribute requests across multiple IPs. |
Ignoring Retry-After | Retry logic doesn’t respect the server-provided Retry-After header. |
Premature retries, unnecessary failures, and potential server bans. | Parse and honor the Retry-After header for accurate retry timing. |
Infinite Retry Loops | No limit on retry attempts leads to endless retries on failure. | High resource usage, server costs, degraded performance, or crashes. | Define a maximum retry limit to prevent infinite loops. |
Retrying Non-Retryable Errors | Retrying for errors like 400 (Bad Request) or 401 (Unauthorized). | Increased latency, server load, and no resolution of the issue. | Configure retries for specific, retryable errors like 408, 429, or 5xx responses. |
Frequent Retry Overhead | Aggressive retry configurations with too many retries in a short time. | High resource consumption and potential application slowdown. | Balance retry attempts and delays to optimize reliability and resource usage. |
ScrapFly provides web scraping, screenshot, and extraction APIs for data collection at scale.
To wrap up this guide, here are answers to some frequently asked questions about Axios retry.
No, Axios doesn't have default retry mechanisms, but libraries like axios-retry can add this functionality.
Limit the number of retries using a counter or configuration options, like the retries
property
in axios-retry
. If you're using manual retries, make sure the retry policy prevents infinite loops.
Ensure you respect the Retry-After
header, throttle your HTTP requests, or consider using proxy
rotation to bypass unfair rate limiting.
Implementing retry logic in Axios improves error handling for web scraping and API integrations and axios-retry
is a great tool that simplifies the process offering:
As for retries themselves, the best practices include:
Retry-After
headers to avoid premature retriesFor advanced needs, tools like Scrapfly's Web Scraping API can simplify the process even further.