Introducing Highlights: the context that matters

What Is a 522 Status Code?

A 522 status code is a Cloudflare error, "Connection timed out", returned when Cloudflare cannot complete a connection to the origin server in time. Cloudflare waits 19 seconds for the TCP handshake and 90 seconds for the origin to acknowledge the request. Blocked or rate-limited Cloudflare IPs and overloaded servers are the most common causes.

Code
522
Name
Connection Timed Out
Class
Cloudflare extension
Retry?
Yes, with backoff

What causes error 522?

  • →The origin firewall dropping or rate limiting Cloudflare IP addresses (the most common cause).
  • →An overloaded or offline origin that drops connections.
  • →The origin IP in Cloudflare DNS no longer matching the host’s current IP.
  • →TCP keepalives disabled at the origin, or packets dropped on the way.

How do you fix error 522 when web scraping?

  • →Retry with backoff and fewer parallel requests to that site.
  • →If the 522s are constant, the site is unreachable through Cloudflare for everyone. Fall back to a cached copy.

How do you fix error 522 on your own server?

  • →Allow all Cloudflare IP ranges in .htaccess, iptables, and any firewall.
  • →Check that the A or AAAA record points at the current origin IP.
  • →Enable TCP keepalives and check origin capacity.
  • →If it persists, run an MTR or traceroute from the origin to a Cloudflare IP and send it to your host.

How do you handle error 522 in a retry loop?

fetch() treats 522 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 522?

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 522

What does 522 connection timed out mean?

Cloudflare could not finish connecting to the site’s origin server: no reply to the TCP handshake within 19 seconds, or no acknowledgment of the request within 90 seconds.

Is error 522 caused by Cloudflare?

Usually not. Cloudflare reports it, but the cause is almost always at the origin: a firewall, an overloaded server, or a wrong IP in DNS.

What is the difference between 522 and 524?

With a 522 the connection never completed. With a 524 the connection worked, but the origin did not send a response before the read timeout.

Which status codes are related to 522?

Sources

Last reviewed

Ship an agent that actually knows things.

Free tier, 10-minute integration, and the same API powering agents at Mintlify, daily.dev, and Propane. No credit card to start.