5 min read · 2026-10-26
What an Arabic webfont actually weighs
Measured WOFF2 sizes for Arabic families, why the Arabic subset can be lighter than the Latin one, and what to do about it.
Every family on Google Fonts that ships an Arabic subset, measured in one pass: 57 families, the WOFF2 files Google actually serves at weight 400, counted in bytes. At the median the Arabic file is 1.35× the size of the same family's Latin file — and the range around that median runs from 0.50× to 12.75×.
| family | Arabic | Latin | ratio |
|---|---|---|---|
| Noto Nastaliq Urdu | 233 | 20 | 11.67× |
| Gulzar | 204 | 25 | 8.29× |
| Noto Sans Arabic | 162 | 31 | 5.28× |
| Cairo | 30 | 33 | 0.91× |
| Tajawal | 9 | 10 | 0.87× |
Why the spread is that wide
A Naskh face drawn for interface text carries a few hundred glyphs. A Nastaliq face carries thousands, because the script's shaping rules stack and join letters into context-dependent forms that cannot be composed from a base glyph plus marks. Gulzar and Noto Nastaliq Urdu are beautiful for poetry and expensive for a product page. Cairo and Tajawal compile to something smaller than their own Latin companion, which is the opposite of the folk rule.
That is the argument for measuring: the ratio is a property of an individual drawing, not of a script.
Ask for one weight, get a smaller file
The same family weighs very differently depending on the CSS you requested it with.
Ask Google for a range of weights and you get the variable file, which carries the whole
axis. Ask for a single weight and you get a static instance cut from it — for Cairo,
under half the bytes. The two columns are two real requests:
family=Cairo:wght@400 and family=Cairo:wght@400;700. The font
library's Arabic column is the second shape, so its numbers are the range, not the single
weight.
| family | 400 only | 400 + 700 | Latin, 400 only |
|---|---|---|---|
| Cairo | 13 | 30 | 15 |
| Tajawal | 9 | 9 | 10 |
| Noto Naskh Arabic | 51 | 92 | 11 |
| Noto Sans Arabic | 48 | 162 | 10 |
| Amiri | 106 | 106 | 19 |
| IBM Plex Sans Arabic | 42 | 42 | 19 |
The last two rows did not move because those families ship static weights: one file per weight either way. Of the 57, 30 serve the identical file for 400 and 700, which is how you can tell a variable family from a static one without asking.
So the practical rule is dull: request the weights you actually use. A page that sets Arabic body text at one weight should ask for one weight.
What the visitor actually downloads
Google splits each family into unicode-range subsets, and a browser only fetches the ranges the page's characters fall into. An Arabic page loads the Arabic file; a Latin visitor to the same page loads the Latin file and never touches the Arabic one. The number that matters is the subset your reader needs, not the total in the CSS.
pyftsubset Cairo-Regular.ttf --unicodes="U+0600-06FF,U+0750-077F,U+200C-200D,U+0020-007E" --layout-features="kern,liga,calt,init,medi,fina,rlig" --flavor=woff2 --output-file=cairo-subset.woff2
Two things go wrong with aggressive subsetting. Dropping U+200C and
U+200D breaks joining behaviour in copied text, and dropping vocalisation
marks (U+064B–U+0652) makes any diacriticised content render
from a fallback font mid-sentence.
The four things worth doing
- Measure your family before you commit to it, at the weight you will ship.
- Request only the weights you use, so you are not paying for an axis you ignore.
- Preload only the subset the first screen needs, and only if the page is in that language.
- Keep
font-display: swapandunicode-rangeon the face, so a Latin-only reader never waits on Arabic.
The numbers above come from the webfont cost tool, which fetches and counts the files in your browser rather than quoting a table. The library lists all 57 with their measured sizes.
Sources
- W3C Arabic Layout Requirements §7.4 — Arabic ascenders and descenders extend much further than Latin, which is part of why the file and the leading both differ.
-
Measured from
fonts.googleapis.com/css2and the WOFF2 files it names, 2026-10-26, 57 families shipping an Arabic subset. The table above is rendered fromsrc/data/fonts.json, whichscripts/fetch-library.mjsregenerates.