Cloudflare Pages Custom Domains: What "Pending" Actually Means
“Pending” is the least useful word in the Cloudflare Pages dashboard.
I have had a custom domain sit on that label while the site served correctly over HTTPS, and I have had one flip to active while the zone’s DNS record list stayed completely empty. In neither case did the badge describe what was happening. If you are debugging a custom domain right now, the badge is the last thing worth trusting.
The three states you will see
| Status | What it usually means |
|---|---|
initializing | The binding was accepted, the certificate is being issued |
pending | Waiting on something — usually DNS |
active | Bound and serving |
The middle one is the problem. pending covers two situations that need opposite responses: the domain genuinely is not resolving, or it is resolving fine and the status simply has not caught up.
Check three things instead of the badge
Forget the interface for a minute and test the domain itself.
# Does it serve over HTTPS?
curl -sI https://your-domain.com/ | head -1
# Does plain HTTP redirect to HTTPS?
curl -sI http://your-domain.com/ | head -1
You want 200 from the first, and 301 or 308 with a location: header pointing at https:// from the second. If you get both, the domain works. Whatever the badge says after that is cosmetic.
To inspect the binding itself, ask the API rather than the dashboard:
curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/pages/projects/$PROJECT/domains" \
-H "Authorization: Bearer $API_TOKEN"
Look for "status": "active" on each entry. That field is what the badge renders, and it is the one that carries meaning.
Two ways to attach a domain, and they do not behave alike
Most of the confusion traces back to this.
Through the dashboard. Workers & Pages → your project → Custom domains → Set up a custom domain. When the domain’s DNS lives on the same Cloudflare account, this path completes the DNS side as part of the flow.
Through the API. A POST to the project’s /domains endpoint also succeeds — 200 with "success": true — but succeeding only means the binding was recorded:
{
"name": "your-domain.com",
"status": "initializing",
"validation_data": { "status": "pending", "method": "http" }
}
Nothing creates a DNS record. The domain sits at pending until a record exists that points it at <project>.pages.dev.
That is a real behavioural difference from Workers. Attach a custom domain to a Worker and Cloudflare creates the DNS record and removes the old one on your behalf. The Pages domain endpoints do not.
A counter-intuitive case worth knowing
While setting up one project I attached the domain through the dashboard, then queried the zone to see what had been created:
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?per_page=100" \
-H "Authorization: Bearer $API_TOKEN"
The list came back empty. No CNAME, no A record, nothing.
The domain was active anyway, serving 200 over HTTPS with a valid certificate.
I am not going to claim I know the internal mechanism. What matters practically is the conclusion: an empty DNS record list is not proof that the domain is broken. Test the domain instead of auditing the list.
If it genuinely is not resolving
Work down this list in order. Each step can mask the one below it.
- Is the zone on the same Cloudflare account as the Pages project? If not, records must be added by hand — nothing will do it for you.
- Does the record exist, and is it a CNAME? Point
@andwwwat<project>.pages.dev. An A record aimed at an arbitrary IP will not work, and a stale record left behind by a previous host is the most common cause of a domain that “should” work. - Is the proxy on? The record must be proxied — the orange cloud — not “DNS only”.
- Is the certificate issued? SSL/TLS → Edge Certificates. Universal SSL takes a few minutes on a new domain. A domain can resolve perfectly and still fail in the browser at this stage.
- Has enough time passed? Minutes for a zone already on Cloudflare. Hours if nameservers changed.
One more thing: a fresh deploy takes a moment
Not a custom domain problem, but it costs people the same evening.
Right after a deployment finishes, the edge can still serve the previous build for a few seconds. A page you just created may return 404 on the first request and 200 on the next one.
If a new deploy appears to be missing, retry before you start debugging. Nothing is wrong.
The short version
The status badge is a hint, not a verdict. A custom domain works when https:// returns 200, http:// redirects to it, and the project’s own domain list reads active. Check those three, and an empty DNS list or a stale “pending” label stops being alarming.
Written by TestedHost. Every recommendation on this site comes from running the setup described, on a live deployment — not from a vendor spec sheet. Spotted something out of date? Tell us.