How to Convert TTF to WOFF2 — Web Font Guide for Developers (2026)
Table of Contents
WOFF2 is the web font format that belongs in production. It wraps the same glyph outlines as your TTF or OTF, but compresses them with Brotli, cutting bytes on the critical rendering path and improving how fast your text paints. This guide shows the quickest browser method, the real CLI commands developers actually use, the exact @font-face block to reference the file, and how the three formats compare on size and browser support.
1. Quick Answer
The direct answer: To convert TTF (or OTF) to WOFF2, the fastest no-install route is a browser tool like Convertlo's font converter — drop the file and it produces a real Brotli-compressed WOFF2 entirely in your browser via WebAssembly, nothing uploaded. On the command line, use Google's woff2_compress font.ttf, or with Python run pip install fonttools brotli then fonttools ttLib.woff2 compress -o font.woff2 font.ttf. In Node, ttf2woff2 streams a TTF in and a WOFF2 out. All produce the same WOFF2 that every modern browser supports.
2. Why WOFF2 Is the Format to Ship
WOFF and WOFF2 are not new outline formats — they are containers. A WOFF file wraps an existing sfnt font (TrueType/glyf or OpenType/CFF) plus compression. WOFF 1.0 used zlib/DEFLATE. WOFF2 replaced that with Brotli, plus a font-specific glyph and table transform, which is why it consistently beats WOFF by roughly 30% and an uncompressed TTF by 50% or more.
Those saved bytes matter because a web font sits on the critical path for rendering text. A smaller font file downloads sooner, the browser can swap in your typeface faster, and your Largest Contentful Paint — usually a heading or body text block — resolves earlier. On mobile connections the difference between a 120 KB TTF and a 45 KB WOFF2 is measurable in Core Web Vitals field data.
Browser support is no longer a reason to hesitate: WOFF2 is supported in every current version of Chrome, Edge, Firefox, and Safari, plus their mobile counterparts. The practical rule for 2026 is ship WOFF2 as the primary format and only add a WOFF or TTF fallback if your analytics still show a meaningful share of legacy browsers.
3. TTF vs WOFF vs WOFF2 — Size & Support
Exact bytes depend on the typeface, its glyph count, and hinting, but the relative ordering is consistent across virtually every font. Using a typical Latin text face as the baseline:
| Format | Compression | Relative size | Browser support | Use as |
|---|---|---|---|---|
| TTF / OTF | None (raw sfnt) | 100% (baseline) | Universal, but not web-optimized | Source / last-resort fallback |
| WOFF | zlib / DEFLATE | ~60–70% of TTF | All browsers incl. IE 9+ | Legacy fallback |
| WOFF2 | Brotli + transform | ~40–50% of TTF | All modern browsers | Primary — ship this |
In other words, WOFF2 is commonly cited at around 30% smaller than WOFF and roughly half the size of a raw TTF. If you only serve one format, serve WOFF2.
4. Method 1: Browser Converter (No Install)
When you just need a WOFF2 without touching a terminal — or you are on a locked-down machine — the fastest path is Convertlo's font converter. It converts TTF, OTF, WOFF, and WOFF2 between each other and produces a genuine Brotli-compressed WOFF2. The conversion runs 100% in the browser using WebAssembly, so the font file never leaves your device.
Works in any modern browser on Windows, Mac, or Linux. No account, no upload, no install.
Drag the font onto the converter or browse for it. Select WOFF2 as the target format. You can queue several files at once for a whole family.
Conversion completes in a second or two locally. Download the .woff2 and drop it into your /fonts directory. Nothing was sent to a server.
Convert TTF/OTF to WOFF2 — free, in-browser, nothing uploaded
Real Brotli WOFF2 generated locally with WebAssembly. Works both directions between TTF, OTF, WOFF, and WOFF2.
5. Method 2: CLI — woff2_compress, fonttools, ttf2woff2
For build pipelines and repeatable automation, generate WOFF2 on the command line. Three well-established tools cover every environment.
Google's woff2_compress (reference encoder)
The woff2 project from Google is the reference implementation. After building it (or installing via your package manager, e.g. brew install woff2 or apt install woff2), it is a single command per file:
bash
# produces font.woff2 next to the input
woff2_compress font.ttf
# OTF works exactly the same
woff2_compress font.otf
There is also woff2_decompress font.woff2 to go back to sfnt, which is handy for verifying a round-trip.
fonttools (Python — most flexible)
If you already have Python, fonttools with the Brotli backend is the most script-friendly option and integrates with subsetting in the same toolchain:
bash
pip install fonttools brotli
# compress TTF or OTF to WOFF2
fonttools ttLib.woff2 compress -o font.woff2 font.ttf
# decompress back to sfnt to verify
fonttools ttLib.woff2 decompress -o font.ttf font.woff2
ttf2woff2 (Node)
For JavaScript/Node build steps, ttf2woff2 reads a TTF on stdin and writes WOFF2 on stdout, so it drops into any pipe or npm script:
bash
npm install -g ttf2woff2
# stream a TTF in, get WOFF2 out
ttf2woff2 < font.ttf > font.woff2
Tip: All three encoders are lossless — they repackage and Brotli-compress the existing outlines and tables. The WOFF2 you get from the browser tool, woff2_compress, fonttools, and ttf2woff2 are byte-comparable in size and identical in what browsers render. Pick whichever fits your workflow.
6. The @font-face Snippet
Once the .woff2 is in place, reference it with an @font-face rule. List WOFF2 first so modern browsers download only that; add a WOFF (or TTF) fallback if you still support legacy browsers. Always set font-display: swap so text stays visible while the font loads:
css
@font-face {
font-family: 'MyFont';
src: url('/fonts/myfont.woff2') format('woff2'),
url('/fonts/myfont.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
body {
font-family: 'MyFont', system-ui, sans-serif;
}
The browser walks the src list in order and uses the first format it supports, so a modern browser never downloads the WOFF fallback. For faster start-of-render, also preload the primary file in your <head>:
html
<link rel="preload" href="/fonts/myfont.woff2" as="font"
type="font/woff2" crossorigin>
The crossorigin attribute is required on font preloads even for same-origin fonts — omit it and the browser fetches the font twice, wasting the preload. Match the preloaded file to the one your primary @font-face actually serves.
7. Going Further: Subsetting
Converting to WOFF2 shrinks the file, but the biggest wins often come from subsetting — stripping glyphs you never use. A full Latin + Cyrillic + Greek font carries thousands of glyphs; an English-only site may use a few hundred. Subset first, then compress to WOFF2, and the file can drop dramatically further.
bash
# pyftsubset (ships with fonttools) — subset AND output WOFF2 in one step
pyftsubset font.ttf \
--unicodes=U+0000-00FF \
--flavor=woff2 \
--output-file=font.subset.woff2
glyphhanger is a companion tool that crawls your live pages and reports exactly which Unicode code points you actually render, then hands that set to pyftsubset automatically — so you subset to precisely what your site uses rather than guessing a range.
Subsetting is the one step that is lossy by design: removed glyphs are gone. Keep the original TTF/OTF in source control, and be careful with dynamic or user-generated text (names, other languages) that may need code points outside your subset.
8. Frequently Asked Questions
How do I convert TTF to WOFF2?
Why use WOFF2 instead of TTF or WOFF for the web?
Can I convert OTF to WOFF2 the same way?
Is WOFF2 conversion lossless?
How do I reference a WOFF2 file in CSS?
Generate WOFF2 in your browser — free and private
Convert TTF or OTF to a real Brotli-compressed WOFF2 with no install and no upload, then drop it straight into your @font-face rule.
Ship WOFF2 as your primary web font, keep a WOFF/TTF fallback only if your traffic needs it, subset when you can, and preload the file that matters. That combination gives you the smallest possible font payload and the fastest text render.