How to remove truetype hinting from any font
- Step 1Drop your font on the upload zone — Click the drop zone or drag a `.ttf`, `.otf`, `.woff`, or `.woff2` file onto it. WOFF is zlib-inflated and WOFF2 is Brotli-decompressed back to a flat sfnt before processing, so the format you start with doesn't matter for the strip step.
- Step 2Press Process — There is no options panel for this tool — the button just says **Process**. It always removes the same seven tables (`fpgm`, `prep`, `cvt `, `gasp`, `hdmx`, `VDMX`, `LTSH`). There is deliberately no toggle to keep `cvt ` or strip only `fpgm` + `prep`; if you need that level of control, use a desktop tool like `fonttools`.
- Step 3Read the result panel — After processing you get metric chips: `Removed tables: fpgm, prep, cvt, gasp, hdmx, VDMX, LTSH`, the original size, the output size, and — when the strip actually shrank the file — a green `Saved: N%` chip. If the chip is missing, the font had none of those tables (common for OTF/CFF) and nothing was removed.
- Step 4Download the .unhinted.ttf — The download button is labelled **Download TTF**. The output is always a raw TrueType sfnt named `yourfont.unhinted.ttf` with MIME `font/ttf` — even if you uploaded a WOFF2. This is the single most important thing to understand: you have decompressed your font back to TTF.
- Step 5Re-compress to WOFF2 for the web — A raw unhinted TTF is bigger than the WOFF2 you may have started with. Feed the result into [TTF → WOFF2](/font-tools/ttf-to-woff2) to Brotli-compress it. The hinting strip (5–20%) compounds with WOFF2 (often 35–50% over raw TTF) for the real shipping size.
- Step 6Keep your source font in version control — The strip is destructive — the hint bytecode is gone from the output and cannot be reconstructed identically. Keep the original hinted font in your repo so you can regenerate later (e.g. with `ttfautohint`) if you ever need hints back for a legacy audience.
The seven tables this tool removes
Exact tags passed to the table-removal routine, in source order. The OpenType tag for the control-value table is four bytes with a trailing space (cvt ); the tool handles that internally.
| Tag | Name | What it holds | Removed? |
|---|---|---|---|
fpgm | Font program | Global hint bytecode functions, run once at font load | Yes |
prep | Control-value program (pre-program) | Bytecode run at every new pixel size to set up the rasteriser | Yes |
cvt | Control Value Table | Reference coordinate values the hint bytecode reads (note the trailing space in the tag) | Yes |
gasp | Grid-fitting And Scan-conversion Procedure | Per-size rules for when to grid-fit vs. grayscale vs. subpixel | Yes |
hdmx | Horizontal Device Metrics | Pre-computed glyph advance widths at specific pixel sizes | Yes |
VDMX | Vertical Device Metrics | Pre-computed clipping/line heights at specific pixel sizes | Yes |
LTSH | Linear Threshold | Pixel size above which advance widths scale linearly | Yes |
What survives the strip
The strip is surgical: only the seven hint-related tags are touched. Everything load-bearing for shape, spacing, encoding, and naming is preserved byte-for-byte.
| Table | Role | Kept? |
|---|---|---|
glyf / loca | TrueType outlines and their index | Kept — outlines never change |
cmap | Character-to-glyph mapping | Kept |
GSUB / GPOS | OpenType layout (ligatures, kerning, alternates) | Kept |
kern | Legacy kern pairs | Kept |
name | Family / style / copyright strings | Kept (use name-table-cleaner to scrub those) |
head checkSumAdjustment | Whole-file checksum field | Not recomputed — left as-is (see edge cases) |
Per-tier file size limits
Single-file, browser-side. The free ceiling already exceeds any normal single-weight web font, so most users never see a limit.
| Tier | Max file size | Batch in this UI |
|---|---|---|
| Free | 5 MB | 1 file at a time |
| Pro | 50 MB | 1 file at a time (UI picks one) |
| Developer | 1 GB | 1 file at a time (UI picks one) |
Cookbook
Realistic before/after for the cases people actually drop in. Sizes are illustrative of the documented 5–20% band; your exact numbers depend on how heavily the source was hinted.
A heavily-hinted system TTF
ExampleOld workhorse faces (the original Verdana, Times New Roman, Arial Unicode) carry large fpgm/prep programs from the GDI era. These are where the strip pays off — the upper end of the 5–20% band.
Input: verdana.ttf (738.0 KB) Process → removes fpgm, prep, cvt, gasp, hdmx, VDMX, LTSH Output: verdana.unhinted.ttf (601.4 KB) Result chips: Saved 19% · Removed tables: fpgm, prep, cvt, gasp, hdmx, VDMX, LTSH
A lightly-hinted modern web TTF
ExampleMost fonts shipped by Google Fonts and modern foundries are lightly hinted or autohinted. The strip still helps, just at the low end of the band.
Input: Inter-Regular.ttf (312.0 KB) Process Output: Inter-Regular.unhinted.ttf (296.4 KB) Result chips: Saved 5% · Removed tables: fpgm, prep, cvt, gasp, hdmx, VDMX, LTSH
WOFF2 in → raw TTF out (the gotcha)
ExampleDrop a WOFF2 and you get back a decompressed TTF, not a smaller WOFF2. The output is larger than the input even though hinting was removed — because WOFF2's Brotli compression is gone. You must re-compress.
Input: Inter-Regular.woff2 (96.0 KB, Brotli-compressed) Process → decompresses to sfnt, strips hints Output: Inter-Regular.unhinted.ttf (296.4 KB, raw) ← bigger! Fix: feed Inter-Regular.unhinted.ttf into /font-tools/ttf-to-woff2 → Inter-Regular.unhinted.woff2 (~91 KB) ← now smaller
An OTF (CFF) font — nothing to strip
ExampleOpenType/CFF fonts hint inside their CFF charstrings, not in fpgm/prep/cvt. The tool finds none of the seven tags, so the bytes are unchanged — but the output is still renamed and re-typed as TTF.
Input: SourceSerif.otf (245.0 KB, OTTO/CFF)
Process → none of the 7 tags present → no tables removed
Output: SourceSerif.unhinted.ttf (245.0 KB, identical bytes)
Result: no Saved chip (0% reduction). File still contains CFF outlines
despite the .ttf extension — see edge cases.Compound pipeline for the smallest shippable file
ExampleThe recommended sequence for a brand site targeting modern browsers: strip hints, then subset to the glyphs you use, then WOFF2-compress.
1. hinting-stripper: brand.ttf → brand.unhinted.ttf (−12%) 2. font-subsetter (Latin Basic + Latin-1): → brand.subset.ttf (−60% glyphs) 3. ttf-to-woff2: → brand.subset.woff2 (−40%) Net: a fraction of the original, all in the browser.
Edge cases and what actually happens
Every row below was probed against the live API. Some documented requirements (alphabetical axis order, numerical tuple order) are not actually enforced in practice — useful to know if you've been blaming the wrong thing for a 400.
You uploaded a WOFF2 and got back a bigger file
By designThe tool decompresses WOFF/WOFF2 to a raw sfnt before stripping and always emits a raw .unhinted.ttf. A 96 KB WOFF2 becomes a ~300 KB TTF — larger, because the Brotli compression was undone. This is expected. Re-run TTF → WOFF2 on the result to get back below your starting size.
OTF / CFF font produces zero savings
PreservedCFF fonts (OTTO magic) store hints inside the CFF table's charstrings, not in fpgm/prep/cvt . The remover finds none of the seven tags and returns the bytes unchanged, so there's no Saved chip. Nothing is broken — there was simply nothing of this kind to remove. The output is still written as .ttf (see below).
OTF input is downloaded with a .ttf extension
ExpectedThe output filename is always {stem}.unhinted.ttf and the MIME is always font/ttf, regardless of input. An OTF/CFF font keeps its OTTO CFF -table internals but ends up named .ttf. Rename it back to .otf if a downstream tool keys off the extension; the bytes are correct OpenType either way.
The head checkSumAdjustment is left stale
PreservedRebuilding the table directory changes table offsets, but the tool does not recompute the whole-file checksum stored in head.checkSumAdjustment. Browsers, opentype.js, FreeType, DirectWrite, and CoreText all ignore it, so rendering is unaffected. Strict validators like fontbakery may emit a checksum warning — harmless, or fixable by passing the file through fonttools once.
Font already had no hinting tables
By designIf the source carries none of the seven tags (already-stripped fonts, some autohinted webfonts that ship only gasp, pure outline faces), the removal is a no-op and the tool returns a byte-identical copy with no Saved chip. Re-running the tool on its own output is therefore idempotent.
TrueType Collection (.ttc) upload
Unsupported formatA .ttc collection is detected by its ttcf magic but rejected with Unsupported font format: ttc. — the tool only flattens single TTF/OTF/WOFF/WOFF2 faces. Extract the individual face you want with a desktop tool first, then strip that single TTF.
Wrong extension on a non-font file
InvalidThe UI accepts a file if its extension is one of ttf/otf/woff/woff2, but the processor re-checks the magic bytes. A .ttf that is actually a ZIP or an image fails with an Unsupported font format error rather than producing garbage.
File exceeds your tier's size cap
413-style limitFree tops out at 5 MB, Pro at 50 MB, Developer at 1 GB. A larger file throws File "x" exceeds the <tier> tier per-job limit before any processing. A single hinted web-font weight is almost always well under 1 MB, so free covers nearly every real case.
Variable font with hinting tables
SupportedA variable TTF's fpgm/prep/cvt /gasp are removed like any other; its variation tables (fvar, gvar, STAT, etc.) are not in the strip list and survive. The font stays variable. If you instead want to pin a variable font to one instance, use variable-font-freezer.
Text looks softer at tiny sizes on Windows 7 GDI
Expected on legacyOn Windows 7/8 GDI + ClearType, stripping hints removes the grid-fitting those renderers rely on, so 10–12px text antialiases slightly softer. Windows 10+ DirectWrite, macOS/iOS CoreText, and high-DPI Linux show no difference. If your analytics still show meaningful Windows 7 traffic, keep your hinted source for that audience.
Frequently asked questions
Which exact tables does this remove?
Seven: fpgm (font program), prep (control-value program), cvt (control-value table), gasp, hdmx, VDMX, and LTSH. The list is fixed in code — there is no option to keep or drop individual tables.
Can I choose to keep cvt or strip only fpgm + prep?
No. This tool has no options panel — it always removes the same seven tables. Selective stripping (keeping cvt , for example) is a niche need; do it with a desktop tool like fonttools (ttx/subset) instead.
Why is my output bigger than the WOFF2 I uploaded?
Because the output is always a raw, uncompressed .unhinted.ttf. Uploading a WOFF2 decompresses it; the strip removes a little, but undoing Brotli adds a lot. Re-run the result through TTF → WOFF2 and you'll land below your starting size.
Will text look worse on Windows?
Only on Windows 7/8 with GDI/ClearType, which use hints for grid-fitting. Windows 10+ (DirectWrite) renders outline-first like macOS, so the difference is invisible. macOS, iOS, and high-DPI Linux never used TrueType hints to begin with.
Does it work on OTF (CFF) fonts?
It runs, but usually does nothing: CFF fonts hint inside the CFF table, not in fpgm/prep/cvt , so none of the seven tags are present and the bytes come back unchanged — just renamed to .unhinted.ttf. For CFF size reduction, subset instead.
Are the glyph shapes changed?
No. The strip only removes hint and device-metric tables; glyf/loca outlines (and CFF charstrings, for OTF) are copied through untouched. At any reasonable rendering size the shapes are identical.
Can I get the hinting back afterwards?
Not identically — the bytecode is gone from the output. You can re-generate fresh hints with ttfautohint or FontForge, but they won't match the originals. Keep the source font in version control so you always have the hinted master.
Is anything uploaded to a server?
No. The strip is binary surgery in your browser; the result panel shows a 0 bytes uploaded badge. The font, including any embedded metadata, never leaves the tab.
What's the biggest font I can process?
5 MB on Free, 50 MB on Pro, 1 GB on Developer. Since a single hinted web-font weight is typically well under 1 MB, the free tier covers nearly every realistic job.
Does it handle WOFF and WOFF2 input?
Yes. WOFF is zlib-inflated and WOFF2 is Brotli-decompressed to a flat sfnt before stripping — but remember the output is always raw TTF, so plan to re-compress.
Will validators complain about the result?
Possibly about one thing: the head.checkSumAdjustment is not recomputed after the directory is rebuilt. Every shipping renderer ignores it, but strict QA tools (fontbakery) may warn. Round-trip through fonttools once if you need a clean checksum.
What should I run next for the smallest web font?
Strip hints here, then subset to the glyphs you actually use, then compress to WOFF2. To confirm which tables ended up in the file, inspect it with font-format-identifier or font-metadata-extractor.
Privacy first
Every JAD Font tool runs entirely in your browser using opentype.js and the wawoff2 WASM Brotli encoder. Your fonts never leave your device — verified by zero outbound network requests during processing.