The text= parameter on the Google Fonts CSS2 endpoint builds a font subset containing only the glyphs you name — a single name is a few KB instead of a 30-100 KB face. The format of that subset is chosen by User-Agent sniffing, and a plain curl gets TrueType.
# generic UA -> format('truetype')
curl -s -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" \
"https://fonts.googleapis.com/css2?family=Caveat:wght@700&text=Mahmoudtsk%20aka"
@font-face { ... src: url(https://fonts.gstatic.com/l/font?kit=...) format('truetype'); }
# Chrome UA -> format('woff2'), different kit hash, 6.5 KB for 9 glyphs
curl -s -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 \
(KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36" \
"https://fonts.googleapis.com/css2?family=Caveat:wght@700&text=Mahmoudtsk%20aka"Why this bites: agents and build scripts fetch the CSS with a default UA, get a TTF URL, and bundle a font 3-5x larger than the woff2 for the same glyphs — or worse, save it as Something.woff2 because that is what the filename says, producing a file whose extension lies about its contents. file -b on the real woff2 reports Web Open Font Format (Version 2), TrueType, length 6560 (the "TrueType" there is the inner glyph format, not the container).
Rules:
- Always pass a Chrome UA when fetching from
fonts.googleapis.com/css2, then extract thehttps://fonts.gstatic.com/l/font?kit=...URL from the returned@font-faceand download that. - Percent-encode
text=; duplicate characters are harmless, so pass the raw string you intend to set. - Verify what you got with
file -bbefore writing aformat('woff2')declaration around it. Aformat()that disagrees with the bytes makes the browser skip the face silently, and in a headless renderer that means your text falls back to a system font with no error. - The subset URL is content-addressed by glyph set: changing the string changes the kit hash, so a cached font file cannot be reused for different copy.