dom4in.net
← All resources
Guide · Cloudflare Pages

Attach a custom domain to a Cloudflare Pages project

If the zone is already on Cloudflare, attaching a domain is two clicks and the CNAME appears by itself — the only real work is deciding apex versus www and setting the redirect.

The process

The full path from a working pages.dev site to your own domain with a canonical redirect. Crumbs map to the Directions sections below.

Directions

1Open Custom domains on the Pages project

In the Cloudflare dashboard go to Workers & Pages, open your Pages project, and select the Custom domains tab. Your site is already live at project-name.pages.dev; nothing you do here takes that URL away, it just adds names that route to the same deployment.

2Pick your canonical hostname

Decide once whether the site lives at example.com or www.example.com. On Cloudflare this is a lighter decision than elsewhere because CNAME flattening makes the apex work exactly like any subdomain — there's no technical penalty either way. Pick one, use it everywhere (sitemap, canonical tags, marketing), and redirect the other form in the last step.

For a subdomain deployment (app.example.com, docs.example.com) there is no decision to make; just use the subdomain.

3Add the domain and let Cloudflare create the record

Click Set up a custom domain, type the hostname, and confirm. Because the zone is in the same Cloudflare account, the dashboard creates the CNAME for you and activates it — usually in under a minute. The record points your hostname at the pages.dev target and is proxied automatically, which is correct for Pages.

If the domain's DNS is not on Cloudflare, the dashboard instead shows you a CNAME to add at your external DNS host. That works for subdomains, but the apex of an external zone generally can't hold a CNAME — which is a good moment to move the zone onto Cloudflare anyway.

www.example.com  CNAME  your-project.pages.dev  (proxied — created for you)

4Confirm the certificate is active

Cloudflare issues the edge certificate automatically; the Custom domains tab shows the domain moving from Initializing to Active. Load the site over https:// and confirm there's no certificate warning. If your zone's SSL/TLS mode is Flexible from some ancient setup, set it to Full (strict) — Pages origins support it, and Flexible causes redirect loops on some apps.

5Redirect the non-canonical hostname

Attach the other hostname (apex or www, whichever you didn't pick) so it resolves, then redirect it. The current tool for this is a Redirect Rule: Rules → Redirect Rules → create one matching the non-canonical host, with a 301 to the canonical host preserving the path and query string. Cloudflare's dashboard has a single-click template that builds exactly this.

The result: one canonical URL in search results, no duplicate-content ambiguity, and both spellings of your domain work for visitors.

Rule: if hostname eq "example.com"
-> 301 to https://www.example.com (preserve path + query)

Common issues & fixes

Custom domain stuck on Initializing.

There's usually a conflicting DNS record — an old A record or CNAME on the same hostname. Delete the stale record in the zone's DNS tab; the Pages CNAME can then activate.

Site loads on pages.dev but 522/525 on the custom domain.

SSL/TLS mode mismatch. Set the zone to Full (strict). Also confirm the record is proxied — a grey-clouded CNAME to pages.dev bypasses the edge logic Pages needs.

Apex won't accept a CNAME at an external DNS host.

That's a DNS protocol limit, not a Pages bug. Either use a host that supports ALIAS/ANAME records, or move the zone to Cloudflare where apex CNAMEs are flattened automatically.

Old deployment shows on the new domain.

The custom domain always serves the latest production deployment. If you're seeing stale content it's cache — purge the zone cache and check any HTML-caching page rules.

Preview deployments leak on subdomain wildcards.

Custom domains only attach to production. Preview URLs stay on pages.dev; if you need them protected, enable Cloudflare Access on *.your-project.pages.dev.

Honesty note: articles are drafted with AI assistance, then a human checks each one against the vendor's current setup flow before it publishes — nothing goes live unreviewed. Vendor interfaces still change; if a step looks different, the underlying record is what matters.