Font subsetter and inspector: shrink TTF, OTF and WOFF web fonts
Inspect a font, keep only the characters you need, export TTF and WOFF.
- Instant
- Free
- Private (processed locally)
- No sign-up
Subset a web font in the browser, nothing uploaded
A full font ships thousands of glyphs while a page uses a fraction of them: font subsetting keeps only the characters you need, then compresses the result as WOFF. The serious tools are command-line programs (pyftsubset from fontTools, glyphhanger) or require uploading the file to a server, which is a problem with a licensed font.
This tool runs entirely in your browser: it reads TTF, OTF, WOFF 1.0 and TTC files, shows a full inspector (names, licence, fsType permissions, variation axes, Unicode coverage per block, languages covered, OpenType features, size of every table), then builds a TrueType subset with component and ligature closure, writes TTF and WOFF, checks that the produced font loads and generates the @font-face CSS with unicode-range.
-
Choose a font
Drop a TTF, OTF, WOFF or TTC file, or click “Choose a font”. For a TTC collection, pick the font to extract. A WOFF2 file (wOF2 signature) is detected and refused with an explanation.
-
Read the inspector
Check the family, version, licence (name ID 13) and fsType embedding permissions, the fvar axes, the Unicode coverage per block, the languages likely supported and the GSUB/GPOS features. The glyph map and the search box answer “does this font have ẞ or €?”.
-
Choose the characters to keep
Paste your text into “Text to keep”, tick presets (Basic Latin, Latin-1, Greek, Cyrillic…) or type Unicode ranges. The counter shows which characters are present, which are missing and how many glyphs are kept after closure.
-
Set the output mode
“Keep OpenType features” preserves kerning, ligatures and variable axes; “Smallest file” renumbers glyphs and drops the layout tables. Decide about hinting removal and the minimal name table.
-
Build the subset
Click “Build the subset”: the tool shows the size before and after, the per-table detail, the rendering self-check, the “Download .ttf” and “Download .woff” buttons and the CSS snippet to copy.
How the subset is built
The tool reads the sfnt directory described by the OpenType specification, then the cmap table (formats 4 and 12 first) to map your characters to glyphs. It then computes the closure: the components of composite glyphs (an “é” that reuses “e” and the accent), then, when features are kept, the GSUB substitutions of types 1 to 4 (single, multiple, alternate and ligature forms such as fi, fl, ffi) iterated to a fixpoint, the sub-lookups of contextual substitutions (types 5, 6 and 8, type 7 extensions resolved) conservatively, the variants of the MATH table and the colour layers of the COLR table.
- “Keep features” mode: glyph IDs do not move; unused outlines are emptied (zero-length loca entries), the cmap is rebuilt, GSUB, GPOS, GDEF, kern and fvar stay untouched and therefore valid, and gvar is only pruned of the removed glyphs.
- “Smallest file” mode: glyphs are renumbered compactly, components are remapped, hmtx, loca, glyf, cmap, maxp, hhea and post are rebuilt, layout and variation tables are dropped.
- Hinting removal: fpgm, prep, cvt, hdmx, VDMX and LTSH go away, instructions are stripped from simple and composite glyphs, maxp and gasp are adjusted the way pyftsubset does.
- Writing: sorted directory, tables aligned on 4 bytes, table checksums and head checkSumAdjustment recomputed, short or long loca depending on size, then WOFF 1.0 with zlib per table (a table stays raw when compression does not help).
- Self-check: the produced font is loaded with the FontFace API and your preview text is rendered with the original and the subset side by side, pixels compared.
What each table weighs and what the tool does with it
| Tables | Role | Treatment |
|---|---|---|
| glyf, loca | TrueType outlines and glyph index: most of the weight | Unused outlines emptied (keep mode) or removed and renumbered (smallest mode) |
| cmap | Unicode character to glyph mapping | Rebuilt: format 4 for the BMP, format 12 added for characters beyond the BMP |
| hmtx, hhea | Advance widths and left side bearings | Kept as is (stable glyph IDs) or rebuilt with an optimised numberOfHMetrics |
| GSUB, GPOS, GDEF, kern | Ligatures, substitutions, kerning, mark positioning | Untouched in keep mode, dropped in smallest mode (warning shown) |
| fpgm, prep, cvt, hdmx, VDMX, LTSH | TrueType hinting and device metrics | Dropped with “Remove hinting”, glyph instructions stripped |
| name, post, DSIG | Names and licence, glyph names, digital signature | name full or minimal (IDs 0 to 6, 13, 14, 16, 17, plus the axis and instance names of a variable font), post as format 3, DSIG always removed |
Behaviour for fonts with TrueType (glyf) outlines. CFF/OTF fonts are inspected, converted to WOFF and stripped of tables, but their outlines are not subset.
When to subset a font
- Marketing site or blog: ship only Basic Latin, Latin-1 and typographic punctuation to speed up the first paint of text.
- Headline or logo set in a display font: keep only the letters of the slogan, a few kilobytes instead of hundreds.
- CJK fonts (TrueType): paste the real text of the page to go from several megabytes to a few dozen kilobytes (IPA Gothic: 6.2 MB down to about 55 KB as WOFF for a paragraph of 154 distinct characters, 22 KB in “Smallest file” mode); CJK fonts shipped as OTF/CFF are not subset.
- Audit before buying or embedding: check language coverage, OpenType features (tnum, smcp, ss01…) and fsType permissions without installing the font.
- TTF to WOFF conversion: get a valid WOFF 1.0 and the matching @font-face snippet without sending a licensed file to a server.
Common problems and fixes
- Some characters show in another font: they are not in the subset; the counter and the self-check flag the missing ones, add them to the text to keep.
- Ligatures or kerning disappeared: you chose “Smallest file”; switch back to “Keep OpenType features”.
- The WOFF is not as small as expected: in keep mode, hmtx and loca keep their original size; WOFF compresses those areas very well, and the smallest mode really shrinks them.
- WOFF2 font refused: convert it to TTF or WOFF with another tool first (the tool ships no Brotli/WOFF2 decoder).
- OTF font not subset: its outlines are CFF; convert it to TTF before subsetting, or use only the inspection and WOFF conversion.
Privacy: the font is read, analysed and rewritten by your browser; no file is uploaded or stored, which matters for a licensed font. Limits: CFF/OTF outlines are not subset, WOFF2 is neither read nor written, contextual substitutions are kept conservatively (the subset may contain a few more glyphs than strictly needed), variation sequences (cmap format 14) are dropped, bitmap and colour tables are dropped in smallest mode, files over 200 MB are refused. Check your licence before publishing a subset font.
Frequently asked questions
What is font subsetting and how much does it save?
Subsetting keeps in the file only the glyphs your pages need, for example Basic Latin plus a few accents instead of the thousands of characters of a full font. The saving depends mostly on what the font contains: on a large multi-script font a Latin subset is often only 5 to 10% of the original, while a font already limited to Latin loses far less. WOFF compression then removes another quarter to half. Measured with this tool: DejaVu Sans (6,253 glyphs, 742 KB) reduced to Basic Latin and Latin-1 weighs about 50 KB as WOFF with OpenType features kept, and 14 KB in “Smallest file” mode. The tool shows the size before and after, table by table.
Am I allowed to subset a font I bought?
It depends on the licence. Open licences such as the OFL or Apache allow modification (the OFL does treat a subset as a Modified Version: if the font carries a Reserved Font Name, the subset file must be renamed); many commercial web licences allow subsetting for embedding, others explicitly forbid it. The tool displays the licence text stored in the font (name ID 13) and decodes the fsType field: if it carries the “no subsetting” bit (0x0100), the licence asks you not to cut the font. Always check your agreement before publishing the file.
Why is WOFF2 not supported?
WOFF2 relies on Brotli compression plus a specific transform of the glyf and loca tables, while the Compression Streams API in browsers only offers gzip and deflate everywhere (native Brotli decoding is still missing from Chrome). Reading or producing WOFF2 would require shipping a Brotli library and that decoder, which this 100% local tool does not do. Convert your WOFF2 to TTF or WOFF with another tool, subset it here, then go back to WOFF2 if you wish: WOFF2 is usually 15 to 30% smaller than WOFF 1.0 (a median gain of about 25% on TrueType fonts according to the W3C evaluation report).
What is the difference between “keep OpenType features” and “smallest file”?
The first mode keeps glyph IDs and only empties the unused outlines: the GSUB, GPOS, GDEF and kern tables stay valid, so ligatures, kerning and the axes of a variable font keep working. The second mode renumbers glyphs and drops those tables: the file is minimal, but without kerning or ligatures, and a variable font becomes its default instance. For a website the first mode is almost always the right choice.
Does removing hinting change the rendering?
TrueType hinting (the fpgm, prep and cvt tables plus glyph instructions) mostly matters for Windows ClearType rendering at small sizes. macOS, iOS, Android and most Linux browsers ignore it. Removing it often shrinks a heavily hinted font by 20 to 50%, at the cost of slightly different Windows rendering at small sizes. The option is on by default; untick it if your audience mostly uses Windows at small text sizes.
How do I use unicode-range in the generated CSS?
The unicode-range descriptor lists the characters the subset contains, in the shortest form (merged ranges, wildcards when a range is aligned). The browser only downloads the file when the page uses at least one of those characters, which lets you split a font into several files (Latin, Cyrillic, Greek) loaded on demand. Paste the @font-face snippet into your stylesheet and place the files at the path given in src.