
What is the difference between WOFF, WOFF2, TTF and OTF?
- Sajjad
- Typography
- 11 Oct, 2026
TTF and OTF are desktop font formats, while WOFF and WOFF2 are compressed wrappers designed for delivering those same fonts over the web. TTF (TrueType) stores glyph outlines as quadratic curves, and OTF (OpenType) is a broader format that can hold either TrueType outlines or cubic CFF outlines plus advanced typographic features. WOFF packages a TrueType or OpenType font with zlib compression and extra metadata, and WOFF2 does the same job with a more advanced Brotli-based compression that typically produces noticeably smaller files. The glyphs, features and metrics inside are the same; only the packaging differs. For websites today, you should serve WOFF2 and nothing else in almost every case.
The format you choose directly affects how many bytes a visitor downloads before your text appears in the right typeface. Many sites still ship TTF files or long lists of legacy formats copied from old tutorials. In this article you'll learn what each format actually contains, how they relate to one another, which browsers support what, how to write the @font-face src descriptor correctly, and how to convert files yourself.
The Short Answer in a Table
| Format | Extension | Created for | Compression | Use on the web today? |
|---|---|---|---|---|
| TrueType | .ttf | Desktop and OS fonts | None | Only as a last resort |
| OpenType | .otf (or .ttf) | Desktop, print, advanced features | None (CFF is compact) | Only as a last resort |
| WOFF | .woff | Web delivery | zlib per table | Rarely needed now |
| WOFF2 | .woff2 | Web delivery | Brotli plus table transforms | Yes, the default |
The key idea is that TTF and OTF are font formats, while WOFF and WOFF2 are containers for those formats. A WOFF2 file decompresses back into an ordinary TrueType or OpenType font inside the browser.
TrueType (TTF)
TrueType was developed by Apple in the late 1980s and adopted by Microsoft for Windows in the early 1990s. It became the standard format for system fonts on both platforms.
Its defining characteristics are:
- Quadratic Bézier outlines: Each curve is described by two end points and one control point. Designers working in cubic curves have their outlines converted on export.
- Hinting instructions: TrueType includes a powerful bytecode language for hinting, which adjusts outlines to the pixel grid at small sizes. This mattered a great deal on low-resolution screens.
- Table-based structure: The file is a collection of tables, such as
glyffor outlines,cmapfor mapping characters to glyphs andhmtxfor horizontal metrics.
A .ttf file is uncompressed, so serving one directly on the web wastes bandwidth.
OpenType (OTF)
OpenType was developed by Microsoft and Adobe in the 1990s as an extension of TrueType. It's now an international standard (ISO/IEC 14496-22, also called the Open Font Format). OpenType added two important things:
- A choice of outlines: An OpenType font can contain TrueType outlines in a
glyftable or PostScript-style cubic outlines in aCFForCFF2table. - Advanced layout features: Tables such as
GSUBandGPOSenable ligatures, contextual alternates, small caps, old-style figures, kerning and complex script shaping.
By convention, OpenType fonts with CFF outlines use the .otf extension, while OpenType fonts with TrueType outlines usually keep .ttf. So a "TTF" you download today is very often an OpenType font with full feature support. The extension tells you about the outlines, not about whether features like ligatures are available.
Variable fonts are also part of OpenType. They add tables such as fvar and gvar (or CFF2) that describe design axes like weight and width.
WOFF
The Web Open Font Format was published as a W3C Recommendation in 2012. It was designed to solve two problems with putting desktop fonts on the web: file size and the lack of a web-specific package.
WOFF:
- Compresses each table with zlib: The same compression as gzip, applied table by table.
- Adds optional metadata and private data blocks: Foundries can embed licence information.
- Is not a different font format: Inside is an ordinary TrueType or OpenType font.
WOFF support is universal in browsers released over the past decade. It's mainly useful today as a fallback for very old browsers that support WOFF but not WOFF2.
WOFF2
WOFF 2.0 became a W3C Recommendation in 2018. It keeps the same idea as WOFF but improves compression significantly:
- Brotli compression: The whole font is compressed as one stream with Brotli, which is more efficient than zlib.
- Preprocessing transforms: Tables such as
glyfandlocaare restructured before compression so they compress better. The browser reverses these transforms after download. - Lossless output: The decoded font is functionally identical to the original.
The W3C's own evaluation reported average savings of around 30 percent compared with WOFF, though results vary with each font. Every current version of Chrome, Edge, Firefox, Safari and Opera supports WOFF2, so it's the format to serve.
How Browsers Choose a Format
In an @font-face rule, the src descriptor lists sources in order of preference. The browser picks the first one whose format it supports and only downloads that file:
@font-face {
font-family: "Brand Sans";
src:
url("/fonts/brand-sans-regular.woff2") format("woff2"),
url("/fonts/brand-sans-regular.woff") format("woff");
font-weight: 400;
font-style: normal;
font-display: swap;
}
The format() hint is important. Without it, the browser may have to download a file to discover it can't use it. The valid format strings are:
| File | format() value |
|---|---|
.woff2 | "woff2" |
.woff | "woff" |
.ttf | "truetype" |
.otf | "opentype" |
.ttc | "collection" |
Note that the value for .ttf is "truetype", not "ttf". Writing format("ttf") is a common mistake, and browsers will skip a source whose format they don't recognise.
The Modern Minimal Rule
Unless you have analytics showing meaningful traffic from very old browsers, a single WOFF2 source is enough:
@font-face {
font-family: "Brand Sans";
src: url("/fonts/brand-sans-regular.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
Visitors on a browser that can't use WOFF2 will see your fallback font, which is a reasonable outcome.
Variable Fonts and tech()
CSS Fonts Level 4 adds a tech() function so you can say what a file requires, such as variable font support:
@font-face {
font-family: "Brand Sans";
src:
url("/fonts/brand-sans-var.woff2") format("woff2") tech(variations),
url("/fonts/brand-sans-regular.woff2") format("woff2");
font-weight: 100 900;
}
Browsers that don't understand tech() treat the first source as invalid and move on to the next, so this pattern degrades safely.
Formats You Can Forget
Old "bulletproof" @font-face snippets often list five formats. Two of them are obsolete:
- EOT (Embedded OpenType): Only ever supported by Internet Explorer. There's no reason to ship it now.
- SVG fonts: Once used for early iOS Safari. Support was removed from browsers years ago. This is different from colour fonts that embed SVG glyphs in an OpenType
SVGtable.
If you inherit a stylesheet with .eot and .svg sources, you can safely delete them along with the files.
Converting Fonts to WOFF2
If a foundry or designer gives you only TTF or OTF files, convert them yourself. Always check first that the licence allows web use and conversion.
Using fonttools
The Python fonttools package can compress to WOFF2. It needs the brotli module:
pip install fonttools brotli
fonttools ttLib.woff2 compress -o brand-sans-regular.woff2 BrandSans-Regular.ttf
To go the other way, for inspecting a web font in a desktop app, decompress it:
fonttools ttLib.woff2 decompress -o BrandSans-Regular.ttf brand-sans-regular.woff2
Converting a Whole Folder
A small shell loop converts every desktop font in a directory:
mkdir -p web
for f in *.ttf *.otf; do
[ -e "$f" ] || continue
fonttools ttLib.woff2 compress -o "web/${f%.*}.woff2" "$f"
done
ls -lh web
Subset and Convert in One Step
pyftsubset, which ships with fonttools, can remove unused characters and output WOFF2 at the same time. This usually saves far more than the format change alone:
pyftsubset BrandSans-Regular.ttf \
--unicodes="U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+20AC,U+2122" \
--layout-features="*" \
--flavor=woff2 \
--output-file=brand-sans-regular-latin.woff2
The full process is covered in the guide to font subsetting.
Checking What You're Serving
It's easy to believe you're serving WOFF2 while the browser actually downloads something else. Check it:
- Open DevTools and go to the Network panel.
- Filter by Font and reload the page.
- Look at the Type column and the file names. You should see
woff2for every font.
You can also check the server sends the right content type:
curl -sI https://example.com/fonts/brand-sans-regular.woff2 | grep -i content-type
content-type: font/woff2
The registered media types are font/woff2, font/woff, font/ttf and font/otf. Older servers sometimes send application/octet-stream, which browsers generally still accept, but setting the correct type is good practice.
Should You Ever Serve TTF or OTF?
Rarely. There are a few edge cases:
- Local development and prototypes: Using a desktop file temporarily is fine before you convert it.
- Non-browser environments: Some PDF generators, image renderers and native app frameworks need TTF or OTF rather than WOFF2.
- Email clients: Web font support in email is patchy anyway, and the few clients that load fonts generally support WOFF or WOFF2.
For public web pages, the bandwidth saving from WOFF2 is too large to ignore.
FAQ: Font File Formats
No. WOFF2 compression is lossless. The browser decodes it back to a font that renders the same glyphs with the same metrics and features as the original TrueType or OpenType file.
For most sites, no. Every current major browser supports WOFF2. Add WOFF only if your analytics show real traffic from very old browsers that support WOFF but not WOFF2.
Neither is better for screen use. OTF files usually contain cubic CFF outlines and TTF files quadratic outlines, but both can include OpenType features. For the web, convert either one to WOFF2.
Technically yes, but only do it if the font's licence permits web embedding and format conversion. Many commercial desktop licences don't cover web use, so check the EULA or buy a web licence.
WOFF2 only compresses what is in the font. A file with thousands of glyphs, many languages or several variable axes will still be big. Subsetting to the characters you need usually gives the biggest reduction.
It's the format hint for a .ttf file in an @font-face src list. Browsers use it to skip sources they can't use without downloading them. The equivalent for .otf is opentype.
Conclusion
TTF and OTF are the underlying font formats, holding outlines, metrics and OpenType features, while WOFF and WOFF2 are web wrappers that compress those same fonts for delivery. WOFF2 uses Brotli and table transforms to produce the smallest files, decodes losslessly, and is supported by every current browser.
In practice that means one rule: convert your licensed fonts to WOFF2, list a single WOFF2 source with the correct format("woff2") hint, and drop EOT, SVG and usually WOFF too. Combine that with subsetting and you'll have trimmed the font payload about as far as the format allows.


