The hidden cost of calling Google Fonts

Most personal brand sites load fonts from Google Fonts with a single <link> tag. The tag points to fonts.googleapis.com, which returns a CSS file. The CSS then points the browser to the actual woff2 files on fonts.gstatic.com. The setup is one line of HTML. The cost is hidden.

On a cold load, the browser may need to resolve and connect to two Google-owned origins before it can even start downloading the font file. Preconnect hints help. Cached DNS and warmed connections help. But the dependency is still there: your page needs a third-party CSS file before it knows which font files to fetch. That indirection is real even when caching is doing its job.

The other cost is privacy. The font request necessarily includes the visitor’s IP address and request headers like user-agent. Referrer information may or may not come along depending on the site’s referrer policy. In the EU, a Munich court ruled in 2022 that forwarding a visitor’s IP to Google Fonts without consent violated GDPR. Outside the EU, the privacy cost is softer but still real.

Self-hosting trims both costs. The fonts live on your domain. No third-party origin to negotiate. No font request leaving your origin. No external dependency to break when Google has a bad day.

What changes when you self-host

The browser request flow shrinks. The site already has a connection to your domain because the HTML loaded from it. The CSS and the font files come down on that same connection. Zero extra third-party DNS lookups. Zero extra third-party TLS handshakes. The fonts are right there.

Self-hosting also forces you to audit the exact weights and styles you ship. Many sites’ Google Fonts URLs request weight variants they no longer use. The audit catches that. On my site the inventory landed at seven woff2 files (Barlow Condensed at three weights, Instrument Serif regular and italic, Inter Tight regular, JetBrains Mono regular). The total font payload is under 200KB.

The third change is reliability. Google Fonts has been up almost constantly for over a decade. Almost. When it goes down, every site relying on it falls back to system fonts for the duration. With self-hosted fonts, your fonts are up exactly as often as your site is. Same uptime, same CDN, same problem domain.

How to self-host fonts in five steps

The setup takes about fifteen minutes once. Then it stays solved.

1. Pick the exact fonts and weights you use.

Open your CSS or design system. List every font-family you reference and every font-weight that shows up. On my site that is Barlow Condensed at 400, 700, 800, Instrument Serif at 400 regular and italic, Inter Tight at 400, JetBrains Mono at 400. Seven files. If you list more than ten, you are probably loading variants you do not use. Trim first.

2. Download the woff2 files.

Use google-webfonts-helper by Mario Ranftl. Paste the font name, pick the weights and styles you need, choose the character subset (latin is enough for English-only sites), download the zip. The tool gives you the woff2 files plus the matching @font-face CSS declarations.

If you are not using Google Fonts originally, the same approach works for any open-source font. Most modern fonts ship woff2 directly. If a font only comes as ttf or otf, convert with a tool like fonttools or convertio.

3. Drop the files into a fonts folder.

On a static site that means public/assets/fonts/ or whatever your build tool’s static directory is. Put the woff2 files in there. The path matters for the next step.

4. Add @font-face declarations.

In your global stylesheet, declare each font with its file path. For most text, use font-display: swap so the browser shows fallback text immediately and swaps to the real font when it loads. Without a font-display value, the browser may show invisible text for up to three seconds while waiting (FOIT, “flash of invisible text”). Swap is the safest default for headlines and body. For body fonts where avoiding visual shift matters more than guaranteeing the custom font on the first paint, font-display: optional or fallback are reasonable choices.

@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/assets/fonts/barlow-condensed-v13-latin-800.woff2') format('woff2');
}

Repeat for each weight and style. Seven font files means seven @font-face blocks.

5. Reference the font-family in your CSS.

In your design tokens or global styles, set the font-family for headlines, body, code, and any other element. The browser pulls the matching @font-face declaration based on the family name and weight you specify. No extra work.

:root {
  --font-display: 'Barlow Condensed', system-ui, sans-serif;
  --font-body: 'Inter Tight', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;
}

That is it. Refresh the site. The fonts should load from your domain.

Common gotchas

Skipping font-display entirely. Without a font-display value, the browser may show invisible text for up to three seconds while the font loads. Visitors see a blank page during that window. Pick a value (swap, fallback, or optional) intentionally rather than leaving it off.

Shipping unnecessary glyphs. Google Fonts often returns multiple @font-face blocks split by unicode-range, and modern browsers usually download only the ranges they need. When you self-host, that optimization becomes your responsibility. If your site is English-only, download or generate a Latin subset rather than hosting a full multilingual font file. google-webfonts-helper exposes the subset choice when you download.

Ignoring the font license. Google Fonts are generally licensed for self-hosting. Commercial fonts are not. Before converting or hosting any font yourself, confirm the license allows web embedding, self-hosting, and format conversion. A foundry license that allows desktop use does not always cover web hosting.

Forgetting cache headers. Self-hosting is only a performance win if your server returns long-lived cache headers on the font files. A good default is Cache-Control: public, max-age=31536000, immutable for files with versioned or hashed names. Without it, repeat visitors keep refetching files that should be cached for a year.

Using ttf or otf for the web. Both are larger and load slower than woff2. Use woff2 for browsers. Keep ttf only if you need it for non-web contexts (I keep ttf copies of my fonts in /assets/fonts/ttf/ for the Python script that generates blog OG images, because Pillow does not read woff2).

Missing the preload hint for above-the-fold fonts. If a specific font weight is critical for the hero, add <link rel="preload" as="font" type="font/woff2" href="/assets/fonts/whatever.woff2" crossorigin> to the <head>. The browser starts fetching it before the CSS parses. Optional, but it shaves more time off the first paint.

Mixing self-hosted and Google Fonts. Pick one. If you self-host, remove every reference to fonts.googleapis.com from your HTML and CSS. A leftover Google Fonts link defeats the purpose.

Put This Into Practice

If your site is currently calling Google Fonts and you want to switch, paste this into Claude or ChatGPT.

I want to switch my site from loading fonts from Google Fonts to self-hosted fonts. Walk me through this one step at a time:

  1. Ask me to list every font-family and font-weight my site currently uses.
  2. For each font, give me the exact filename pattern I should expect to download (woff2, latin subset, named by weight).
  3. Generate the @font-face CSS declarations for my list, with font-display: swap and the correct file paths assuming I drop the files in /assets/fonts/.
  4. Generate the font-family CSS variables I should add to my :root or design tokens.
  5. Tell me which @font-face declarations or link tags I should remove from my current setup so nothing still calls fonts.googleapis.com.
  6. Suggest a preload hint for any font weight that is critical for above-the-fold content.

Wait for my answer at each step. The output should be a copy-paste-ready CSS block I can drop into my site, plus a list of changes I need to make to my HTML.

The prompt does not download the files for you. That step happens on google-webfonts-helper or whatever font source you use. Everything else is mechanical.

Subtract the dependency

Self-hosting fonts is one of those small infrastructure decisions that pays compounding interest. The site loads slightly faster on every visit. The site never breaks because Google has a bad routing day. The visitor’s data does not get logged by a third party for a font request. None of it is dramatic on its own. All of it adds up over years of operation.

The same logic applies to most third-party dependencies on a personal brand site. Each one is a thing that can break, slow down, or change pricing on you. Self-hosting fonts is the easiest one to remove. The setup is fifteen minutes. The win lasts forever.

Come build with me.

~ Anthony

◆ Come build with me

The build log.

New post drops, tool tests, and the occasional honest look at what isn't working. One email at a time. Unsubscribe in one click.

Anthony Tran

Anthony Tran

Marketer. Air Force veteran. One person building a personal brand with AI, in public. Writing and recording from Chandler, Arizona.

Frequently asked.

Why should you self-host fonts on a personal brand site?

Three reasons: speed (no third-party origin to negotiate on a cold load, no separate CSS file to fetch first), privacy (no font request to Google carrying the visitor's IP and request headers), and control (your fonts do not depend on a CDN you do not run). The tradeoff is a small one-time setup cost for fonts that load with fewer network hops and never break because of a third-party outage.

How do you self-host web fonts?

Pick the fonts and weights you actually use. Download the woff2 files, ideally with a tool like google-webfonts-helper that lets you choose a character subset. Drop the files into a /fonts folder on your site. Add @font-face declarations in your CSS with an appropriate font-display value. Reference the font-family in your stylesheet. The total payload should be under 200KB if you only ship the weights and subset you use.

What is the difference between woff2 and ttf?

Woff2 is the modern web format. It is smaller, compresses better, and loads faster in browsers. Ttf is the desktop format. Use woff2 for the web. Keep ttf around only if you need to render fonts in tools like Pillow or print pipelines that do not read woff2.