Skip to content
Control Plane Labs

523 Origin Is Unreachable

Server error response defined by developers.cloudflare.com.

Last updated July 27, 2026

Common causes at a glance

  • An A or AAAA record pointing at an IP that is not publicly routable
  • A VPC or on-premises route table capturing Cloudflare's 172.64.0.0/13 range
  • The origin IP was reassigned and the DNS record was never updated
  • Upstream BGP or transit trouble between Cloudflare and the origin network

Reproduce it

dig +short A origin.example.com @1.1.1.1 && mtr -rwc 5 203.0.113.10

What 523 Origin Is Unreachable means

523 sits one layer below 521 and 522. Those two assume a reachable destination that misbehaved; 523 means the packet had nowhere to go. Cloudflare describes it as a network device between the edge and the origin lacking a route to the origin’s IP address.

The most instructive documented case is in AWS. Cloudflare uses public addresses in 172.64.0.0/13, and a VPC route table with an over-broad 172.0.0.0/8 entry aimed at a private destination captures traffic meant for Cloudflare. Everything looks correct from inside the VPC because the break is in the return path.

Where it comes from

There is no specification for 523. It is not in the IANA registry, and its only definition is Cloudflare’s error documentation. RFC 9110 §15 has clients interpret any unrecognised 5xx as 500, so nothing downstream attaches meaning to the specific number. As with the rest of this family, the page is written by Cloudflare’s edge. Your origin logs show no matching request, and neither will your load balancer’s, because no packet arrived. That is a useful negative result: if you can see Cloudflare’s connection attempts at all, you are not debugging a 523.

What actually causes it

The overwhelmingly common version is a DNS record pointing somewhere useless. Someone enters an RFC 1918 address, a CNAME chain terminates at a hostname resolving to nothing, or an instance was rebuilt with a fresh public IP and the record still holds the old one. The AWS route table case is genuinely hard to see: the misconfiguration lives in infrastructure nobody associates with the web server, and the fix is a more specific route for 172.64.0.0/13 toward the Internet Gateway rather than touching the application at all.

How to debug it

Start with the record, because it is wrong more often than the network is. Resolve what Cloudflare would resolve and check the answer is a public address you actually control:

dig +short A origin.example.com @1.1.1.1
mtr -rwc 5 203.0.113.10

An mtr run that dies inside your provider’s network, or never leaves it, is the routing story. One that reaches the origin cleanly means the address is fine and you are looking at a different code. The DNS tool shows the full record set including any CNAME chain, where unroutable answers hide. If the origin lives in a VPC, audit the route tables for over-broad entries before you spend an afternoon on tcpdump.

Working examples

curl

# Confirm the record resolves to a public, routable address.
dig +short A origin.example.com @1.1.1.1

# Trace the path from outside; note where it stops.
mtr -rwc 5 203.0.113.10

# If the address is reachable at all, this succeeds and 523 is the wrong lead.
curl -sv --connect-timeout 10 \
  --resolve www.example.com:443:203.0.113.10 \
  https://www.example.com/ 2>&1 | grep -E 'Trying|Connected|No route'

Python (requests)

import ipaddress, socket

# Catch the classic mistake: a private or reserved address in a public record.
addr = socket.gethostbyname("origin.example.com")
ip = ipaddress.ip_address(addr)
print(addr, "global:", ip.is_global, "private:", ip.is_private)

import requests
resp = requests.get("https://www.example.com/", timeout=30)
print(resp.status_code)  # 523 from the edge; nothing in your origin log

Node (fetch)

import { promises as dns } from "node:dns";

// Resolve the origin record and flag unroutable answers.
const records = await dns.resolve4("origin.example.com");
console.log(records);
for (const ip of records) {
  const priv = /^(10\.|127\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.)/.test(ip);
  if (priv) console.log(ip, "is private — Cloudflare cannot route to it");
}

const res = await fetch("https://www.example.com/");
console.log(res.status); // 523

Reference and tooling

The authoritative list of assigned status codes is theIANA HTTP Status Code Registry. For a searchable copy with the semantics summarised, use theHTTP status code reference on this site. To see exactly what a server is sending, theheader inspector shows the raw status line and response headers, and thecurl builder assembles the request flags for you.

Other 5xx codes