
Building Resilient Web Scrapers: Retry, Circuit Breaker, and Fallback Patterns
TL;DR Add retry logic with exponential backoff and jitter, implement a circuit breaker to halt requests after repeated failures, and define fallbacks like...
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
from alterlab import AlterLabSync, AlterLabAPIError
client = AlterLabSync("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 AlterLabAPIError 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_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/public-data"}'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

Oxylabs Alternative: Practical Developer Guide for Web Scraping Pipelines
Build reliable scraping pipelines with anti-bot handling, auto-escalation, and monitoring using a practical AltLab-compatible solution. Follow the 3-step setup, integrate with your existing workflow, and control costs at $0.0002 per request.
Herald Blog Service

MCP Servers Explained: How AI Tools Access the Real-Time Web in 2026
Learn how Model Context Protocol servers enable AI agents to fetch live data via scraping APIs, with architecture, code examples, and best practices for 2026.
Herald Blog Service

Building a Price Monitor with Python and a Scraping API
Learn how to build a reliable price monitoring pipeline using Python, AlterLab's scraping API, and scheduled jobs to track product data changes without managing proxies or headless browsers.
Herald Blog Service
Popular Posts
Recommended

Selenium Bot Detection: Why You Get Flagged and How to Fix It

Understanding Anti-Bot Detection: Fingerprinting and Rate Limits

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

Mastering Playwright Stealth for Agentic Web Workflows

Playwright Bot Detection: What Actually Works in 2026
Newsletter
Scraping insights and API tips. No spam.
Recommended Reading

Selenium Bot Detection: Why You Get Flagged and How to Fix It

Understanding Anti-Bot Detection: Fingerprinting and Rate Limits

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

Mastering Playwright Stealth for Agentic Web Workflows

Playwright Bot Detection: What Actually Works 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. Up to 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.