530 Unable to Resolve Origin Hostname
Server error response defined by developers.cloudflare.com.
Last updated July 27, 2026
Common causes at a glance
- A proxied CNAME pointing at a hostname that does not resolve
- A CNAME target whose own DNS has expired or been deleted
- A dangling record left behind after a platform migration
- An Origin Rule or Worker route naming a hostname with no DNS answer
Reproduce it
curl -s https://www.example.com/ | grep -oE 'Error 1[0-9]{3}'What 530 Unable to Resolve Origin Hostname means
530 is a wrapper. Cloudflare needed an HTTP status for the wire, picked an unused one, and wrote the real diagnosis into the page. Reading the 530 alone tells you almost nothing; reading the 1xxx code inside it tells you everything. The usual companion is Error 1016, origin DNS error, meaning the hostname a proxied record points to did not resolve.
That makes 530 unlike the rest of the family. Every other code here describes a failure between the edge and a known origin address. 530 means the edge never got as far as having an address.
Where it comes from
530 is not in the IANA HTTP Status Code Registry and has no RFC behind it. Cloudflare documents it on its 5xx error page, which mostly redirects to the 1xxx error index. RFC 9110 §15 requires clients to treat an unrecognised 5xx as 500, which is unusually destructive here: the detail was in the body, not the status line, so collapsing 530 to 500 discards the only useful part. As with every code here the page comes from Cloudflare’s edge, and your origin logs will be empty because the edge could not work out where the origin lives.
What actually causes it
Every one of these reduces to the same thing: a record in Cloudflare’s DNS points at a name with no answer behind it. Platform migrations are the usual source. A CNAME to a Heroku app, an S3 bucket, or a load balancer outlives the resource it named, and the record sits there resolving to nothing. Expired domains do the same at one remove. This stays confusing because the visitor sees an error attributed to your site while the broken name belongs to a third party you stopped using months ago.
How to debug it
Read the 1xxx code first. Everything else is guesswork until you have it, and it is in the body of the error page:
curl -s https://www.example.com/ | grep -oE 'Error 1[0-9]{3}'
For the usual answer, 1016, walk the record chain and find the link returning
nothing. Follow each CNAME to its target and query that target directly; the
failure is at whichever hop returns NXDOMAIN or an empty answer.
The DNS tool does this faster than three rounds of
dig. Then repoint the record or delete it.
Do not bother bypassing the edge with curl --resolve here. Unlike
the other codes in this family there is no origin IP to bypass to, which is the
entire problem. The status code reference covers what a
neighbouring code would have meant.
Working examples
curl
# Step 1: extract the 1xxx code. The 530 itself is not the error.
curl -s https://www.example.com/ | grep -oE 'Error 1[0-9]{3}'
# Step 2: walk the CNAME chain and find the hop with no answer.
dig +short CNAME www.example.com
dig +short A app-name.herokudns.com
# Empty output from the target is your 1016.
Python (requests)
import re, requests, dns.resolver
resp = requests.get("https://www.example.com/", timeout=10)
print(resp.status_code) # 530
# The useful part is in the body, not the status line.
match = re.search(r"Error (1\d{3})", resp.text)
print("cloudflare code:", match.group(1) if match else "not found")
# For 1016, find which hop in the chain resolves to nothing.
try:
target = dns.resolver.resolve("www.example.com", "CNAME")[0].target
print("cname ->", target)
print("resolves to:", dns.resolver.resolve(target, "A"))
except dns.resolver.NXDOMAIN:
print("dead CNAME target — this is your 1016")
Node (fetch)
import { promises as dns } from "node:dns";
const res = await fetch("https://www.example.com/");
const body = await res.text();
console.log(res.status, body.match(/Error (1\d{3})/)?.[1]);
// Chase the CNAME target; the broken hop is the one that throws.
try {
const [target] = await dns.resolveCname("www.example.com");
console.log("cname ->", target);
console.log("a ->", await dns.resolve4(target));
} catch (e) {
console.log("chain broken at:", e.hostname, e.code); // ENOTFOUND -> 1016
}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
- 500 Internal Server Error
- 501 Not Implemented
- 502 Bad Gateway
- 503 Service Unavailable
- 504 Gateway Timeout
- 505 HTTP Version Not Supported
- 506 Variant Also Negotiates
- 507 Insufficient Storage
- 508 Loop Detected
- 510 Not Extended
- 511 Network Authentication Required
- 520 Web Server Returns an Unknown Error
- 521 Web Server Is Down
- 522 Connection Timed Out
- 523 Origin Is Unreachable
- 524 A Timeout Occurred
- 525 SSL Handshake Failed
- 526 Invalid SSL Certificate