Self-host Google Fonts for GDPR compliance

If your site does this:
<link href="https://fonts.googleapis.com/css2?family=Inter&display=swap" rel="stylesheet">
Every visitor's IP address is being sent to Google. A German regional court ruled in January 2022 that this violates GDPR Article 6 because it happens without explicit consent. Plaintiffs have since started filing claims against EU-based sites that haven't fixed it.
The fix takes 5 minutes. Download the WOFF2, drop it in your project, change one CSS line.
Why fonts.googleapis.com is the problem
When a browser loads a stylesheet from fonts.googleapis.com, it makes a TCP connection. That connection sends the visitor's IP to Google's servers as part of the standard HTTP request. The IP is personal data under GDPR.
If the visitor hasn't consented to that data transfer (and they almost never have, because cookie banners don't usually mention fonts), the transfer is unlawful.
The German court awarded €100 in damages to the plaintiff. Standalone that's nothing, but the same legal theory has been recycled into thousands of demand letters across the EU since.
The fix in 5 steps
1. Pick the fonts you actually use
Most sites load 4-6 weights of one or two families. Look at your CSS, find every font-family reference, list the weights and styles you actually use. Drop the rest.
Common offender: a CSS template that loads Roboto in 12 weights and the site uses Bold and Regular only. That's 10 wasted downloads on every visit.
2. Download pre-compressed WOFF2 files
Don't generate them yourself. Pre-compressed versions of every popular Google Font are available, pick the families and weights you need:
- Inter, workhorse sans-serif, clean at all sizes
- Roboto, Google's default, looks neutral
- Open Sans, friendly, body-text-friendly
- Montserrat, display + body, geometric
- Lato, humanist, warm
- Poppins, geometric, popular for SaaS
Each one downloads as a single WOFF2 file under 30KB after subsetting.
3. Drop them in your project
Create a fonts/ folder at your web root. Move the WOFF2 files in.
your-site/
├── public/
│ ├── fonts/
│ │ ├── inter-regular.woff2
│ │ └── inter-bold.woff2
│ └── ...
4. Replace the Google Fonts link with a local @font-face
Delete this:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
Replace with this (in your CSS):
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
For variable fonts (one file covers all weights), it's even simpler:
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-variable.woff2') format('woff2');
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
5. Set long cache headers
Fonts are content-addressable: once you ship inter-regular.woff2, the bytes never change. Set a 1-year cache header so repeat visitors don't re-download.
For Vercel:
{
"headers": [
{
"source": "/fonts/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
]
}
]
}
For nginx:
location /fonts/ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
Verifying the fix
Open your site in a clean browser, check the Network tab. You should see ZERO requests to fonts.googleapis.com or fonts.gstatic.com. Just your local /fonts/*.woff2 files.
No Google CDN requests = no IP leaks = GDPR compliance restored.
What you might lose
- The Google Fonts CDN is heavily cached. A repeat visitor to a different site that uses the same Google Fonts URL might have it cached. With self-hosting, every visitor downloads it once from your origin.
In practice this matters less than people think. WOFF2 files are 15-30KB. On a modern broadband connection, that's a few hundred milliseconds the first time. After that, your origin's cache headers serve it from disk.
- Loading fonts via the CSS API gives you a unicode-range optimization where Google serves separate files for Latin, Latin-ext, Cyrillic, etc. and the browser only downloads what the visitor's text needs. Self-hosted single-subset WOFF2 is simpler but downloads a bit more.
For most sites with English-only content, this is a non-issue. The Latin-only WOFF2 covers everything you'll render.
What about the rest of Google's CDNs?
This guide only covers fonts. Google Analytics, Tag Manager, Maps, reCAPTCHA, and Ads all have the same IP-transmission problem under GDPR. Each needs its own fix:
- Analytics: switch to a server-side or self-hosted alternative (Plausible, Fathom, Umami)
- Maps: replace with a server-rendered map image where possible, or use OpenStreetMap
- reCAPTCHA: replace with hCaptcha or Cloudflare Turnstile
- Ads: hard to avoid; usually requires a consent banner with proper opt-in
Fonts are the easiest fix and the lowest-stakes one to start with.
Quick recap
1. Identify the fonts and weights your site actually uses 2. Download pre-compressed WOFF2 files for each weight 3. Drop them into a /fonts/ folder 4. Replace the Google Fonts <link> with a local @font-face 5. Set long cache headers (1 year, immutable) 6. Verify no requests go to fonts.googleapis.com
That's it. Five minutes, no more IP leaks, no more demand letters.
Frequently asked
Is loading Google Fonts from fonts.googleapis.com really illegal in the EU?
A German regional court ruled in January 2022 that embedding Google Fonts via the CDN transmits the visitor's IP to Google without consent, which violates GDPR. Other EU jurisdictions have followed similar reasoning. Self-hosting eliminates the issue entirely.
Do I need to update my privacy policy if I self-host?
No. Self-hosting means no data leaves your server, so there's nothing new to disclose. If you previously had a Google Fonts disclosure in your privacy policy, you can remove it once you've fully migrated.
Will self-hosting be slower than the Google CDN?
On a modern host with HTTP/2 or HTTP/3, self-hosted fonts often load FASTER because there's no extra DNS lookup or cross-origin connection. Pre-compressed WOFF2 files are tiny enough that CDN distance rarely matters.
What about other Google services like Analytics?
This guide only covers fonts. Google Analytics, reCAPTCHA, Maps, and Tag Manager all transmit IPs and need separate consent or alternatives. Fonts are the lowest-effort fix and a common starting point.