Introducing ScrapeGraphAI V2 — better, faster, cheaper APIs. Read the blog →
ScrapeGraphAIScrapeGraphAI
Dark

What Are Cloudflare 521, 522, and 525 Errors?

Last updated: Jul 14, 2026

TL;DR

Cloudflare 521, 522, and 525 errors all mean the edge could not talk to the origin server: 521 is a refused connection, 522 is a connection timeout, and 525 is a failed SSL handshake. For web scrapers they signal origin-side trouble, so the response is patient retries and rate reduction, not proxy rotation.

Decoding the Three Codes

521 Web Server Is Down. Cloudflare reached the origin's IP and the origin actively refused the TCP connection. The web server process is down, or a firewall on the origin is rejecting Cloudflare's IP ranges.

522 Connection Timed Out. Cloudflare tried to connect and got silence within its time budget. The origin is overloaded, network-partitioned, or dropping packets. Of the three codes this is the one scraper traffic most often causes, because sustained concurrency can push a small origin into exactly this state.

525 SSL Handshake Failed. The TCP connection worked but the TLS negotiation between Cloudflare and the origin failed, usually because of an expired origin certificate or mismatched cipher configuration.

All three live in the same family as 520, and none of them are challenge pages: Cloudflare accepted your request and failed upstream of you.

What Scrapers Should Do

The shared property is that your request never reached the application, so scraping-side identity changes (headers, proxies, fingerprints) change nothing. The playbook:

  • Retry on a schedule, not in a loop. These conditions last minutes to hours. Retry after 1, 5, and 15 minutes, then park the URLs and move on.
  • Cut concurrency on 522 bursts. If 522s correlate with your crawl ramping up, you are the load. Halve the rate and watch the error rate respond.
  • Treat 521 and 525 as fully external. A stopped server and a broken certificate are site operator problems; poll occasionally and wait.
  • Separate 52x metrics from block metrics. Mixing them into one "error rate" hides whether you need patience or evasion.
RETRY_SCHEDULE = {521: [300, 1800], 522: [60, 300, 900], 525: [600, 3600]}
 
delays = RETRY_SCHEDULE.get(response.status_code)
if delays:
    requeue(url, delays)  # try again later instead of burning retries now

Key Takeaways

  • 521 = refused, 522 = timed out, 525 = TLS failure, all between Cloudflare and the origin.
  • Identity changes are useless here; scheduled retries and lower request rates work.
  • Bursting 522s are frequently self-inflicted; measure your own concurrency first.

How ScrapeGraphAI Handles This

ScrapeGraphAI classifies Cloudflare 52x responses as origin-side failures, retries them on an appropriate schedule, and reports persistent outages as explicit errors instead of burning your credits on doomed retries. The scrape endpoint tells you when a site is down rather than pretending it was blocked.