Firebase Hosting hands you a *.web.app URL by default. To put your site on yourbrand.com you add a custom domain in the console, then prove you own it via DNS. The whole thing takes 15 minutes if you do it in the right order — and a frustrated afternoon if you do not. The DNS records and verification commands below are what make the difference.
Background
Firebase issues free SSL via Let’s Encrypt for both apex (yourbrand.com) and subdomain (www.yourbrand.com) variants. The flow has two stages: ownership verification (a TXT record) and pointing the domain (A or CNAME records). Most failures come from skipping verification, leaving stale records at the registrar, or DNS caching.
How to tell
*.web.appURL works; you now want a real brand domain.- You own the domain at a registrar (Cloudflare, Namecheap, Porkbun, etc.).
- You are okay editing DNS records — that is the only manual part.
- You want both apex and www to resolve, not just one.
- You need free SSL; you do not need a wildcard cert.
Quick verdict
Add the domain in Firebase first, finish DNS verification, then add the second variant (www or apex) so they share one SSL cert.
Before you start
- Lower TTL on existing DNS records to 300s at least 24 hours before the switch.
- Remove any old A records pointing at a previous host.
- Have the Firebase project ID and the target domain in hand.
Step by step
- Add the domain in Firebase Console. Firebase Console → Hosting → Add custom domain → type
yourbrand.com. Firebase shows a TXT record value like:
Host: @ (or yourbrand.com)
Type: TXT
Value: hosting-site-verification=hZxK... (Firebase-issued)
TTL: 300
- Add the TXT record at your registrar. Cloudflare example via API for reproducibility:
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": "TXT",
"name": "@",
"content": "hosting-site-verification=hZxK...",
"ttl": 300
}'
- Verify the TXT has propagated before clicking Verify in Firebase:
dig +short TXT yourbrand.com @1.1.1.1
# "hosting-site-verification=hZxK..."
- Click Verify. Firebase then shows the A records you need to point apex at its anycast IPs:
Host: @ Type: A Value: 199.36.158.100
Host: @ Type: A Value: 199.36.158.101
For the www variant, use CNAME:
Host: www Type: CNAME Value: your-project.web.app
- Add the A records (or CNAME) and verify resolution:
dig +short A yourbrand.com @1.1.1.1
# 199.36.158.100
# 199.36.158.101
dig +short CNAME www.yourbrand.com @1.1.1.1
# your-project.web.app.
If you see additional IPs (e.g. from a previous host), delete those stale records — DNS will round-robin between live and dead targets.
- Wait for status to flip to “Connected”. SSL is automatic — usually 15 min to a few hours. Probe with
curl:
curl -vI https://yourbrand.com 2>&1 | grep -E 'subject:|issuer:|HTTP'
# subject: CN=yourbrand.com
# issuer: C=US, O=Let's Encrypt, CN=...
# HTTP/2 200
-
Add the second variant. If you added apex first, now add
www(or vice versa). Firebase will provision the cert and auto-create a redirect to your primary. -
Confirm redirects work as expected in incognito:
curl -sI http://yourbrand.com | head -2
# HTTP/1.1 301 Moved Permanently
# Location: https://yourbrand.com/
curl -sI https://www.yourbrand.com | head -2
# HTTP/2 301
# location: https://yourbrand.com/ (if apex is canonical)
- Update Search Console, sitemap, and canonical tags. Verify the new domain as a Domain property, then resubmit the sitemap so Google picks up the new canonical surface.
Implementation checklist
- TXT verification record is removed (or left in place — it does no harm).
- A or CNAME records resolve correctly from at least two resolvers (
@1.1.1.1and@8.8.8.8). - SSL cert subject matches the requested domain —
curl -vIconfirms. - Both apex and www are registered in Firebase Hosting; one canonical, one redirecting.
- Search Console has the new domain verified as Domain property.
After-launch verification
dig +short A yourbrand.comfrom at least two networks returns only Firebase IPs.curl -Ishows HTTP/2 200 on the canonical and 301 on the non-canonical.- Hosting → Custom domains shows status “Connected” with a green check.
- Lighthouse or a basic browser test confirms no mixed-content warnings.
Common pitfalls
- Adding only the A records and forgetting the TXT — verification stays pending forever.
- Leaving old A records pointing to a previous host — DNS returns both and routing flaps. Detection:
dig +short Areturns extra IPs. - Using a CNAME on the apex domain — most registrars do not allow it. Use Cloudflare’s CNAME flattening or use A records.
- Forgetting to add both apex and www, then losing traffic from one variant.
- Aggressive DNS caching at the registrar — clear the registrar’s cache or wait an hour.
- Forgetting to keep the TXT record if Firebase requires periodic re-verification. Leaving it in place is harmless.
- Putting the site behind Cloudflare proxy (“orange cloud”) before SSL is issued — break the proxy temporarily, let Firebase issue the cert, then re-enable.
FAQ
- How long does SSL take?: Usually under an hour. If it is stuck after 24 hours, double-check DNS — provisioning needs propagation to complete.
- Should I make apex or www primary?: In 2026 most indie sites use apex as primary. Pick one, set it as canonical everywhere (Search Console, sitemap, canonical tags).
- Can I move from another host without downtime?: Yes if you lower the TTL on existing records first (300 seconds), verify the new setup on a preview channel, then switch records.
- Why does the dashboard still say “needs setup” after I added records?: Either propagation is incomplete or the record values do not exactly match. Re-copy from Firebase and use
digto verify. - Why does the same domain work on Vercel within minutes but fail on Firebase?: Different ownership models. Vercel auto-issues certs once the CNAME or A record resolves; Firebase needs the separate TXT verification step first (why a domain works on Vercel but not Firebase).
- Can I use Cloudflare in front of Firebase?: Yes. Set the Cloudflare DNS record to “DNS only” (grey cloud) during cert issuance, then switch to “Proxied” (orange cloud) afterwards.