How to Fix Cloudflare Errors 520, 521, 522, 523, 524, 525 and 526
Cloudflare is up, but it could not get a good answer from your server. Each code names a different failure. Test the origin directly, then fix firewall, SSL or timeout.
A subdomain needs three things: a DNS record, a server that knows the name, and a certificate that covers it. Test each one separately and the broken link shows itself.
You set up shop.example.com, staging.example.com or portal.example.com, and it does not work. The browser says DNS_PROBE_FINISHED_NXDOMAIN or This site can’t be reached, or it loads your main website instead, or shows a hosting company placeholder, a bare 404, or a certificate warning such as NET::ERR_CERT_COMMON_NAME_INVALID or ERR_SSL_VERSION_OR_CIPHER_MISMATCH.
A subdomain is a separate hostname, and it has to be set up at three layers. DNS must turn the name into an IP address. The web server at that IP must have a configuration (a virtual host) that claims the name and knows which folder or app to serve. And for HTTPS, a certificate must list the name. Designers and site owners usually do one of the three, often the DNS record, and assume the rest happens automatically.
Each error message tells you which layer failed:
| What you see | Layer | Likely cause |
|---|---|---|
| NXDOMAIN, “server IP address could not be found” | DNS | No record, a typo, or a record at the wrong provider |
| Your main site, or a host placeholder page | Web server | No vhost for the subdomain, so the default site answers |
| 404 Not Found from the server | Web server | Vhost exists but points at an empty or wrong folder, or the app does not know the name |
| Certificate name warning | SSL | The certificate does not list this hostname |
| ERR_SSL_VERSION_OR_CIPHER_MISMATCH behind Cloudflare | SSL at the edge | No edge certificate covers the hostname, often a multi level name |
| Times out | Network | Wrong IP, firewall, or the server is not listening |
Work through them in that order: DNS, then the server, then the certificate.
You need access to the DNS host for the domain (find out who that is in Step 1) and to the hosting panel or server where the subdomain should live. SSH access helps for Step 3 but is not essential. Nothing in the diagnosis changes anything; before editing a server config file, copy it to a backup with a dated name.
How to run the commands. dig and curl run on your own computer. Both are built in on macOS; on Linux, install dnsutils or bind-utils for dig; Windows 10 and 11 include curl.exe, and WSL gives you dig (PowerShell’s Resolve-DnsName also works). Server commands in Step 3 run over SSH on the server. WordPress commands run over SSH in the site folder, the one containing wp-config.php, using wp or wp-cli depending on your host.
A missing or wrong record is the most common cause. First find out which provider is authoritative, so you test and edit in the right place:
dig +short NS example.com
dig @AUTH_NS sub.example.com A +noall +answer
dig @AUTH_NS sub.example.com CNAME +noall +answer
example.com is your main domain and sub is the subdomain label. AUTH_NS is one of the nameservers printed by the first command. Asking it directly with @ shows what is published right now, with no caching. +noall +answer shows only the answer lines.
Good output is an A record with your server IP, or a CNAME pointing at a hostname that itself resolves. No output from either means the record does not exist at the provider that matters. If you created it somewhere else, that is the problem; our guide on DNS changes not showing up covers the wrong provider trap in detail.
Many editors append the domain automatically. Typing sub.example.com in the name field can create sub.example.com.example.com. In the editor, the name field should normally hold just sub.
sub.example.com has a CNAME, it cannot also have an A, MX or TXT record. Editors usually refuse to save the CNAME, or some silently keep the old record. Delete the conflicting record first.dig @AUTH_NS sub.example.com AAAA +short
If this returns an old IPv6 address, devices with IPv6 (most phones on mobile data) go there while your laptop on IPv4 goes to the right place. Delete or correct it.
A wildcard such as *.example.com answers for any subdomain that has no records of its own. It is useful for multisite networks and SaaS apps, and confusing everywhere else.
sub.example.com has only a TXT record (for a verification, for example), a lookup for its A record gets “no data”, not the wildcard’s IP. This catches people out constantly.*.example.com matches a.b.example.com only when b.example.com has no records at all.Test whether a wildcard exists with a label nobody would use:
dig @AUTH_NS RANDOMSTRING.example.com A +short
RANDOMSTRING is any made up label. An IP in the answer means a wildcard is active. If your subdomain resolves only through the wildcard, give it an explicit record so it does not change when someone edits the wildcard.
If DNS is right but you see the main site, a host placeholder or a generic 404, the web server received the request and did not recognize the name. Web servers pick a site by the Host header (or, for HTTPS, the SNI name in the handshake). When no virtual host claims it, the server uses its default, which is the first configured site or one marked as default.
curl -I --resolve sub.example.com:443:SERVER_IP https://sub.example.com/
curl -I --resolve sub.example.com:80:SERVER_IP http://sub.example.com/
SERVER_IP is the IP address the subdomain should point at (from your hosting panel). --resolve makes curl connect to that IP for that hostname and port without asking DNS, so you can test before DNS is right or while it is cached. -I fetches only the response headers. Add -k to the HTTPS line if you need to skip certificate checks while testing the vhost alone.
Good output is HTTP/2 200 or HTTP/1.1 200, or a redirect to the right URL, with headers that look like your app (for example a link header pointing at /wp-json/ for WordPress). Bad output is a redirect to the main domain, a 404, or headers from a different site. Compare with the same command for the main domain to spot whether you are getting the default site.
On managed hosting and panel servers, creating the subdomain in the panel (often under Domains, Subdomains or Websites) generates the vhost, the document root folder and usually the certificate. A DNS record alone is not enough. If the panel has the subdomain but the folder is empty, you get a 404 or a directory listing refusal.
On Apache, the subdomain must be the ServerName or a ServerAlias in a vhost:
<VirtualHost *:443>
ServerName sub.example.com
DocumentRoot /var/www/SUB_FOLDER
# SSL directives for the certificate go here
</VirtualHost>
This goes in the Apache config file for the site, typically under /etc/apache2/sites-available/ or /etc/httpd/conf.d/. SUB_FOLDER is the folder holding the subdomain’s files. List what Apache currently matches with apachectl -S (or apache2ctl -S) over SSH: it prints each port, the default server and every name and alias. If your subdomain is missing from that list, Apache does not know it. Test the syntax with apachectl configtest and look for Syntax OK before reloading.
On Nginx, the name goes in server_name:
server {
listen 443 ssl;
server_name sub.example.com;
root /var/www/SUB_FOLDER;
}
This lives in a file under /etc/nginx/sites-available/ or /etc/nginx/conf.d/. Run nginx -T over SSH to print the full active configuration and search it for your subdomain; nginx -t tests syntax and should end with test is successful. Reload with systemctl reload nginx. If a different server block carries default_server on the same port, that is the site you have been seeing.
If DNS and the vhost are right but the browser shows a certificate warning, the certificate being served does not list your subdomain. Read the names on it:
openssl s_client -connect SERVER_IP:443 -servername sub.example.com </dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName
This runs on your computer (or WSL). -connect sets the IP and port, -servername sends the subdomain as the SNI name so the server picks the matching certificate, and the second command prints the Subject Alternative Names. Good output lists DNS:sub.example.com or a wildcard DNS:*.example.com. If only the main domain is listed, issue a certificate for the subdomain in your panel or with your ACME client. Full troubleshooting for name mismatches is in our certificate name mismatch guide, so we will not repeat it here.
If the subdomain is proxied through Cloudflare, visitors see Cloudflare’s edge certificate, not yours. Cloudflare’s free Universal SSL certificate covers the bare domain and one level of subdomains (example.com and *.example.com). A name like dev.www.example.com or shop.eu.example.com is two levels deep and is not covered, which typically shows up as ERR_SSL_VERSION_OR_CIPHER_MISMATCH.
Your options, per Cloudflare’s documentation: rename to a single level (for example dev-www.example.com), set the record to DNS only so your own server’s certificate is used, order an advanced certificate that names the hostname, upload a custom certificate, or enable Total TLS. Check current plan requirements at developers.cloudflare.com.
A subdomain multisite network (sites like site1.example.com) needs all three layers set up for wildcards:
*.example.com record, or an explicit record per site.ServerAlias *.example.com on Apache, or server_name example.com *.example.com; on Nginx, pointing at the same WordPress folder.Check that WordPress itself knows the site:
wp site list --fields=blog_id,url
Run this over SSH in the WordPress folder. It lists every site’s ID and URL. If the subdomain is not in the list, WordPress shows the network’s “site not found” behavior or redirects to the main site. Also confirm define( 'SUBDOMAIN_INSTALL', true ); in wp-config.php; if it is false, the network uses subfolders and subdomain URLs will not route.
If a site’s URL is wrong (for example after a migration), inspect the network tables with the --url flag, which tells wp-cli which site to act on:
wp option get siteurl --url=sub.example.com
Good output is the subdomain’s own URL. An error saying the site was not found means the wp_blogs table has a different domain for it.
When everything looks right and it still fails, trace one request through each layer and write down the result of each.
dig +trace sub.example.com A. The final block should come from your authoritative servers and show the record. If a parent label like eu.example.com has its own NS records, the subdomain is delegated to different nameservers, and your record must live there.dig @1.1.1.1 sub.example.com A +short and dig @8.8.8.8 sub.example.com A +short. A difference from the authoritative answer is caching, possibly negative caching if someone looked the name up before you created it.curl -v --resolve sub.example.com:443:SERVER_IP https://sub.example.com/ -o /dev/null. -v shows the connection, the TLS handshake and the certificate subject; a hang at “Trying” means a firewall or wrong IP.Our diagnostic tools can also check DNS and certificates for a hostname from outside your network.
If DNS resolves to the right IP but the server serves the wrong site, the vhost or panel configuration is the problem, and on managed hosting only your host can fix it. Open a ticket with:
dig @AUTH_NS sub.example.com A and of the curl -I --resolve test.cf-ray value from any error page.If the whole site is down rather than just one subdomain, start at the Emergency Room.
Did this fix it?
Still stuck? Start again from what you can see in the Emergency Room.
Still stuck?
Print a free one-page checklist to keep, or open the Emergency Room if the symptom does not match.
Get the free checklistsKeep reading
Search the field manual
Or jump straight to a symptom
Press / to search from any page, Esc to close