Vercel custom domain: exact DNS records + 5 traps to avoid

Point an apex + www domain at Vercel with the exact per-project DNS records, dig/curl verification, the CAA fix, and a Cloudflare-in-front setup that does not break SSL. Current as of June 2026.

Vercel’s custom-domain UX is one of the cleanest in the industry, but clean is not the same as trap-free. This walkthrough gives you the exact DNS records (including the per-project CNAME Vercel now hands out), dig + curl verification you can paste, and the five mistakes behind roughly 90% of “my domain won’t go green” support threads. Current as of June 2026.

TL;DR

  1. Add yourdomain.com (apex) in Vercel; accept the www prompt.
  2. Copy the records the dashboard shows you, do not reuse a record from a blog post — the CNAME is now unique per project.
  3. Set an A record (76.76.21.21) for apex and the per-project CNAME for www, both DNS-only.
  4. Verify with dig, wait for the green check, confirm SSL with curl -vI.
  5. Pick one canonical (apex or www); the other gets an automatic 308 redirect.

If certs hang, the cause is almost always a stale record, a Cloudflare orange-cloud proxy, or a CAA record that blocks Let’s Encrypt.

What you need before starting

  • A Vercel project already serving at *.vercel.app.
  • A domain at a registrar you control (Cloudflare, Porkbun, Namecheap, etc.).
  • The ability to edit DNS at that registrar (dashboard or API).
  • A decision on canonical host (apex yourdomain.com or www.yourdomain.com) made before you add either one.

One business note for indie devs: Vercel’s Hobby plan is free but non-commercial as of June 2026. If your custom domain serves a product, paying clients, or anything that generates revenue, Vercel’s terms require the Pro plan ($20/seat/month). Hobby allows up to 50 custom domains per project, but that does not change the commercial-use rule. See Firebase vs Vercel for a commercial side project if the licensing matters to you — Firebase’s free Spark tier permits commercial use.

Before you change anything

  • Lower the TTL on any existing A/CNAME records to 300s 24 hours before the swap, so old answers expire fast.
  • Remove A/CNAME records still pointing at a previous host. A leftover record makes DNS round-robin between the live and dead origin.
  • Confirm your domain’s DNS is actually managed where you think it is (the #1 split-DNS trap below).

Step by step

1. Add the domain in Vercel

Project → SettingsDomains → type yourdomain.comAdd Domain. When you add an apex domain, Vercel prompts you to also add the www prefix and recommends redirecting one to the other. Accept it.

2. Read the records Vercel shows you (this changed)

This is the part most stale guides get wrong. As of 2026 the dashboard gives every project a unique CNAME, not the generic one:

For apex (yourdomain.com):
Type   Name   Value          TTL
A      @      76.76.21.21    300

For www (www.yourdomain.com):
Type   Name   Value                            TTL
CNAME  www    d1d4fc829fe7bc7c.vercel-dns-017.com.   300

The A value 76.76.21.21 is Vercel’s general-purpose anycast IP and is still correct for apex. The CNAME target is per-project — yours will look like d1d4fc829fe7bc7c.vercel-dns-017.com, not cname.vercel-dns.com. The legacy cname.vercel-dns.com still resolves, but copy the value your own dashboard prints. If you use the Vercel CLI, you can print the exact records anytime:

vercel domains inspect yourdomain.com

Why an A record for apex but CNAME for www? DNS RFC 1034 forbids a CNAME at a zone apex (the apex already needs NS/SOA records), so the apex gets an A record and only the subdomain gets a CNAME.

3. Apply the records at your registrar

Dashboard works for any registrar. If you script Cloudflare, the key is proxied: false:

curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE/dns_records" \
  -H "Authorization: Bearer $CF_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"type":"A","name":"@","content":"76.76.21.21","ttl":300,"proxied":false}'

curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE/dns_records" \
  -H "Authorization: Bearer $CF_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"type":"CNAME","name":"www","content":"d1d4fc829fe7bc7c.vercel-dns-017.com","ttl":300,"proxied":false}'

proxied: false keeps Cloudflare in DNS-only (grey cloud) mode. The orange-cloud proxy intercepts HTTPS, which blocks Vercel from completing Let’s Encrypt’s HTTP-01 challenge and you get “Failed to Generate Cert” / “Invalid Configuration”. Keep it grey at least until SSL is issued.

4. Verify DNS propagated before refreshing in Vercel

dig +short A yourdomain.com @1.1.1.1
# 76.76.21.21

dig +short CNAME www.yourdomain.com @1.1.1.1
# d1d4fc829fe7bc7c.vercel-dns-017.com.

If dig still returns the old host, the TTL has not expired. Wait — do not start deleting and re-adding the domain in Vercel yet.

5. Wait for “Valid Configuration” and confirm SSL

Vercel polls every few minutes and provisions the Let’s Encrypt cert automatically over HTTP-01, usually within minutes once DNS is correct. Confirm the cert subject and issuer:

curl -vI https://yourdomain.com 2>&1 | grep -E 'subject:|issuer:|HTTP'
# subject: CN=yourdomain.com
# issuer: C=US, O=Let's Encrypt, CN=...
# HTTP/2 200

If it sits on “Invalid Configuration” for more than an hour with correct DNS, the usual culprit is a CAA record that does not authorize Let’s Encrypt (see pitfall 5).

6. Confirm the 308 redirect on the non-canonical host

Once both apex and www are added, Vercel creates a 308 redirect from the non-canonical variant to the one you picked. Verify the direction:

curl -sI https://www.yourdomain.com | head -3
# HTTP/2 308
# location: https://yourdomain.com/

7. Point canonical, sitemap, and og:url at the chosen host

In your Astro layout:

<link rel="canonical" href={`https://yourdomain.com${Astro.url.pathname}`} />

Then grep the built output to catch any URL leaking the wrong host:

grep -ROIE 'rel="canonical"|og:url' dist | grep -v 'https://yourdomain.com' | head
# any line = a leak (vercel.app, the www variant, or http)

8. (Optional) Keep the Cloudflare proxy on

If you want the orange cloud for caching/WAF, turn it on only after Vercel has issued SSL. Then in Cloudflare set SSL/TLS mode to “Full (strict)”. Full works but skips origin-cert validation; Flexible causes an infinite redirect loop because Cloudflare talks to the origin over HTTP while Vercel forces HTTPS.

Verification checklist

CheckCommand / whereExpected
Apex resolvesdig +short A yourdomain.com76.76.21.21
www resolvesdig +short CNAME www.yourdomain.comyour *.vercel-dns-017.com target
Both DNS-onlyCloudflare DNS tabgrey cloud on both records
Cert validcurl -vI https://yourdomain.comsubject = domain, issuer = Let’s Encrypt
Redirect workscurl -sI https://www.yourdomain.com308 → canonical host
Canonical cleangrep over distno non-canonical URLs
Both greenVercel → Domainsgreen check on apex and www

The 5 traps behind most stuck domains

  1. Split DNS. You changed nameservers to your registrar but added the records somewhere else (or vice versa). Vercel sees nothing. Confirm with dig NS yourdomain.com which provider actually answers, and edit records there.
  2. Cloudflare orange cloud during issuance. The proxy intercepts the HTTP-01 challenge → “Failed to Generate Cert”. Set the records DNS-only (grey) until the cert is live.
  3. Only one of apex/www added. Half your traffic hits a 404 or no redirect. Add both; let Vercel handle the 308.
  4. Stale long-TTL records. You swapped DNS but old answers are still cached. Lower TTL to 300s before the swap, not after, then wait for the old TTL to expire.
  5. CAA record blocking Let’s Encrypt. If your zone has a CAA record, it must authorize Let’s Encrypt or issuance fails silently with “Invalid Configuration”. Add or fix it:
Type   Name   Value
CAA    @      0 issue "letsencrypt.org"

Check existing CAA with dig +short CAA yourdomain.com. No CAA record at all is fine (any CA may issue); a CAA that lists only other CAs is what breaks Vercel.

After launch

  • Search Console: run URL Inspection on the new host; it should show “URL is on Google” within 1–2 weeks if the property was already verified.
  • Lighthouse: loads over valid HTTPS with no mixed-content warnings.
  • Vercel → Domains: green check on both apex and www.

FAQ

  • How long does SSL really take? Usually a few minutes once DNS is correct, since Vercel uses Let’s Encrypt’s HTTP-01 challenge. If it is stuck past an hour, re-check the exact CNAME target, that the proxy is off, and your CAA record.
  • The dashboard shows a weird CNAME like d1d4fc...vercel-dns-017.com — is that right? Yes. As of 2026 each project gets a unique CNAME target. Copy what your dashboard shows; the old generic cname.vercel-dns.com still resolves but is not what Vercel hands you now.
  • Apex or www as the canonical? Either works in 2026. Pick one and keep canonical, sitemap, and og:url consistent site-wide. Vercel’s docs lean toward redirecting to www, but apex is equally valid.
  • Can I host the same project on multiple domains? Yes, but choose one canonical and 308 the rest to avoid duplicate-content SEO problems.
  • Can I use a custom domain on the free Hobby plan? You can add it, but Hobby is non-commercial only. A revenue-generating site needs Pro ($20/seat). For a free commercial option, Firebase Hosting’s Spark tier allows commercial use.
  • Same domain works on Vercel but is “needs setup” on Firebase? Vercel issues the cert straight from the A/CNAME record; Firebase requires a separate TXT ownership step first (why a domain works on Vercel but not Firebase).

Tags: #Indie dev #Vercel #Hosting #Domain #DNS #SSL