What Is a 521 Status Code?
A 521 status code is a Cloudflare error, "Web server is down", returned when the origin web server refuses the connection from Cloudflare. Either the web server application is offline, or a firewall or security tool on the origin is blocking Cloudflare’s IP addresses. It is a Cloudflare extension, not part of the HTTP standard.
- Code
- 521
- Name
- Web Server Is Down
- Class
- Cloudflare extension
- Retry?
- Yes, with backoff
What causes error 521?
- →The web server process on the origin is stopped or crashed.
- →A firewall or security tool on the origin blocking or rate limiting Cloudflare’s IPs.
- →The origin not listening on the port the SSL mode needs: 80 for Flexible, 443 for Full and Full (strict).
How do you fix error 521 when web scraping?
- →Retry with backoff. If the site is down for everyone, retries will not help until it recovers.
- →Check the site from a normal browser. A 521 there confirms the origin is down, not that you are blocked.
- →Use a cached copy of the page for time-sensitive jobs.
How do you fix error 521 on your own server?
- →Confirm the web server is running and responding locally.
- →Allow all Cloudflare IP ranges in your firewall and security software.
- →If SSL mode is Full or Full (strict), make sure the origin serves HTTPS on port 443.
How do you handle error 521 in a retry loop?
fetch() treats 521 as temporary. It waits for Retry-After when the server sends a number of seconds, otherwise backs off exponentially with jitter, caps every wait at 60 seconds, and gives up after five attempts.
import random
import time
import requests
RETRYABLE = {408, 429, 500, 502, 503, 504, 520, 521, 522, 523, 524}
def fetch(url: str, max_attempts: int = 5) -> requests.Response:
for attempt in range(max_attempts):
try:
response = requests.get(url, timeout=(10, 60))
except requests.Timeout:
time.sleep(2**attempt + random.uniform(0, 1))
continue
if response.status_code not in RETRYABLE:
response.raise_for_status()
return response
retry_after = response.headers.get("Retry-After", "")
backoff = 2**attempt + random.uniform(0, 1)
time.sleep(min(int(retry_after) if retry_after.isdigit() else backoff, 60))
raise RuntimeError(f"Gave up on {url} after {max_attempts} attempts")
How does Context.dev handle error 521?
Context.dev retries the fetch for you, and by default Scrape can reuse a capture made in the last 3 days (maxAgeMs), so a page that is briefly down may still come back from cache. If no capture is available, the failed output carries an error_code and message inside an HTTP 200 response, and a request where every output fails is not charged.
See what the web scraping API does on every request, or read how to fix HTTP errors in web scraping for a longer walkthrough.
Frequently asked questions about error 521
What does Cloudflare error 521 mean?
Cloudflare tried to connect to the site’s origin server and the connection was refused. The site’s server is down or blocking Cloudflare.
Can a visitor fix a 521 error?
No. Only the site owner or host can restart the server or fix the firewall. Visitors can only wait and retry.
What is the difference between 521 and 522?
A 521 is an active refusal. A 522 is a timeout: Cloudflare got no answer at all.
Which status codes are related to 521?
Sources
Last reviewed