
Building Resilient Web Scrapers: Retry, Circuit Breaker, and Fallback Patterns
Learn how to add retry logic, circuit breakers, and fallbacks to your scraping pipelines to handle transient failures and maintain data collection reliability.
AlterLab handles this automatically — scrape any URL with one API call. No infrastructure required.
Try it freeTL;DR
Add retry logic with exponential backoff and jitter, implement a circuit breaker to halt requests after repeated failures, and define fallbacks like cached data or alternative endpoints. These patterns keep your scraping pipeline reliable despite transient network issues, rate limits, or temporary blocks.
Why Resilience Matters in Scraping
Web scraping pipelines encounter intermittent failures: network timeouts, HTTP 5xx responses, rate limits, or temporary anti-bot challenges. Without handling these, a single hiccup can halt an entire data collection job, leading to stale datasets and wasted compute. Resilience patterns isolate failures, allow automatic recovery, and preserve throughput.
Retry Strategies: Exponential Backoff with Jitter
A basic retry simply repeats the request immediately, which can worsen load on a struggling server. Instead, use exponential backoff: wait 1s, then 2s, then 4s, etc., up to a maximum delay. Adding jitter (random delay) prevents thundering herd problems when many clients recover simultaneously.
Python SDK Example
import time
import random
import alterlab
client = alterlab.Client("YOUR_API_KEY")
def scrape_with_retry(url, max_attempts=5):
attempt = 0
while attempt < max_attempts:
try:
response = client.scrape(url)
if response.status_code < 500:
return response
except alterlab.APIError as exc:
if exc.status_code >= 500:
pass # treat as retryable
else:
raise # client errors (4xx) are not retried
attempt += 1
delay = (2 ** attempt) + random.uniform(0, 1) # exponential backoff + jitter
time.sleep(delay)
raise RuntimeError(f"Failed to scrape {url} after {max_attempts} attempts")
# usage
data = scrape_with_retry("https://example.com/public-data")
print(data.json)cURL Example with Retry Header
curl -X POST https://api.alterlab.io/v1/scrape \
-H "X-API-Key: YOUR_KEY" \
-H "Retry-After: 1" \
-d '{"url": "https://example.com/public-data", "max_retries": 4}'Note: The AlterLab API honors the
Retry-Afterheader and respects themax_retriesparameter, applying exponential backoff internally when enabled.
Circuit Breaker Pattern
A circuit breaker tracks consecutive failures. After a threshold (e.g., five failures), it trips and blocks further requests for a cooldown period (e.g., 30 seconds). During the cooldown, calls fail fast, saving resources and allowing the remote service to recover. After the cooldown, a limited trial request tests if the service is healthy.
Implementation Sketch
import time
from enum import Enum
class State(Enum):
CLOSED = 0
OPEN = 1
HALF_OPEN = 2
class CircuitBreaker:
def __init__(self, fail_threshold=5, timeout=30):
self.fail_threshold = fail_threshold
self.timeout = timeout
self.fail_count = 0
self.state = State.CLOSED
self.last_failure_time = None
def call(self, func, *args, **kwargs):
if self.state == State.OPEN:
if time.time() - self.last_failure_time > self.timeout:
self.state = State.HALF_OPEN
else:
raise RuntimeError("Circuit breaker is OPEN")
try:
result = func(*args, **kwargs)
self.on_success()
return result
except Exception as exc:
self.on_failure()
raise exc
def on_success(self):
self.fail_count = 0
self.state = State.CLOSED
def on_failure(self):
self.fail_count += 1
self.last_failure_time = time.time()
if self.fail_count >= self.fail_threshold:
self.state = State.OPENIntegrate the breaker around your scrape call:
breaker = CircuitBreaker(fail_threshold=4, timeout=20)
def safe_scrape(url):
return breaker.call(scrape_with_retry, url)
# usage
try:
data = safe_scrape("https://example.com/public-data")
except RuntimeError as err:
print("Scrape unavailable:", err)Fallbacks: Cached Data and Alternative Endpoints
When the circuit breaker is open or retries exhaust, serve stale data from a cache or query a mirror site. This ensures downstream processes continue receiving data, albeit possibly less fresh.
Simple Cache Fallback
import json
import os
from datetime import datetime, timedelta
CACHE_DIR = "./scrape_cache"
CACHE_TTL = timedelta(hours=6)
def get_cached(url):
path = os.path.join(CACHE_DIR, hash(url) + ".json")
if not os.path.exists(path):
return None
with open(path) as f:
entry = json.load(f)
if datetime.fromisoentry["fetched"] + CACHE_TTL < datetime.utcnow():
return None
return entry["data"]
def save_cache(url, data):
os.mWas this article helpful?
Frequently Asked Questions
Related Articles

Choosing a Web Scraping API in 2026: Pricing, Anti-Bot Tiers, and Reliability
Compare pricing models, anti-bot handling, and reliability factors when selecting a web scraping API for scalable data pipelines.
Herald Blog Service

Apify Alternative: Simple Web Scraping Without Actor Marketplace Complexity
Learn how to replace Apify's actor-based workflow with a straightforward scraping API that handles proxies, browsers, and anti-bot measures automatically.
Herald Blog Service

Self-Serve Scraping: Bright Data Alternative for Startups
Learn how startups can replace expensive enterprise scraping tools with a self-serve API that offers automatic anti-bot handling, rotating proxies, and pay-as-you-go pricing.
Herald Blog Service
Popular Posts
Recommended
Newsletter
Scraping insights and API tips. No spam.
Recommended Reading

How to Scrape AliExpress: Complete Guide for 2026

Why Your Headless Browser Gets Detected (and How to Fix It)

AlterLab vs Firecrawl: Which Scraping API Is Better in 2026?

How to Scrape Twitter/X Data: Complete Guide for 2026

How to Scrape Cloudflare-Protected Sites in 2026
Stay in the Loop
Get scraping insights, API tips, and platform updates. No spam — we only send when we have something worth reading.
Explore AlterLab
Anti-Bot Handling API
Automatic challenge handling for protected sites — works out of the box.
JavaScript Rendering API
Render SPAs and dynamic content with headless Chromium.
Pricing
5-tier pricing from $0.0002/page. 5,000 free requests to start.
Documentation
API reference, SDKs, quickstart guides, and tutorials.
Web Scraping API Resources
Part of the Web Scraping API Documentation cluster
Complete API reference with 5-tier auto-escalation — Curl to challenge resolution.
Pillar pageConfigure Tier 4 browser rendering for SPAs and dynamic content.
Scrape pages behind login using session management.
Real success rates and cost data across all 5 tiers.
MCP Server, Python SDK, and Firecrawl-compatible API for AI agent workflows.