The basics
What is a WOFF file?
A WOFF file is a desktop font repackaged for websites. Inside is a complete TrueType or OpenType font: every table, every glyph. WOFF compresses each table with zlib, the same compression used in ZIP and PNG files, and adds two optional blocks for metadata. A browser unpacks it and uses the font exactly as the original.
WOFF was the first font format that every major browser agreed on. Before it, Internet Explorer used EOT, other browsers took raw TTF and OTF files, and font makers were reluctant to license fonts for the web as ordinary desktop files anyone could install. WOFF gave them a web-only package with room for licence information, and browsers a single format.
Today WOFF2 does the same job with better compression, and is what most sites serve. WOFF files are still common in older projects, theme packages and icon fonts, and every browser still reads them.
Anatomy
What's inside a WOFF file
A WOFF file is a 44-byte header, a directory with 20 bytes per table, the tables themselves (each compressed on its own), and optionally a metadata block and a private block at the end. Below is our sample-regular.woff. All numbers are big-endian: 00 00 17 CC is 0x17CC, which is 6,092.
offset bytes meaning
000000 77 4F 46 46 signature "wOFF"
000004 00 01 00 00 flavor: TrueType outlines
000008 00 00 17 CC length: 6,092 bytes
00000C 00 0A 10 tables
00000E 00 00 reserved
000010 00 00 2D 4C decoded font size: 11,596
000014 00 01 00 00 font version 1.0
000018 00 00 00 00 … (20 bytes) no metadata, no private data
table directory, 20 bytes per table:
tag offset compressed original checksum
00002C 4F 53 2F 32 00 00 01 64 00 00 00 42 00 00 00 60 5A 99 5C 1A
000040 63 6D 61 70 00 00 02 A8 00 00 00 C4 00 00 01 06 0F A9 0E 75
000054 67 6C 79 66 00 00 04 34 00 00 0F FA 00 00 1E E0 49 2B 66 13
000068 68 65 61 64 00 00 00 F4 00 00 00 36 00 00 00 36 30 8D 4A AA
00007C 68 68 65 61 … hhea 30 of 36 bytes
000090 68 6D 74 78 … hmtx 254 of 396 bytes
0000A4 6C 6F 63 61 … loca 200 of 200 bytes (stored)
0000B8 6D 61 78 70 … maxp 24 of 32 bytes
0000CC 6E 61 6D 65 … name 752 of 2,208 bytes
0000E0 70 6F 73 74 … post 171 of 232 bytes
0000F4 00 01 00 00 00 01 00 00 … head table, stored as is
00012C 78 9C 63 60 … hhea table, zlib-compressed
0017CC end of file: 6,092 bytes- 1
77 4F 46 46The signature
The ASCII letters
wOFF. A WOFF 2.0 file starts withwOF2instead, so the two are easy to tell apart. - 2
00 01 00 00The flavor
The first four bytes of the font inside:
00 01 00 00for TrueType outlines,OTTOfor CFF outlines, as in oursample-cff.woff. - 3
00 00 2D 4CThe decoded size
How big the font will be after unpacking: 11,596 bytes, which is the original 11,588-byte TTF plus padding between tables.
- 4
00 01 00 00The version
A major and minor version number for the font, here 1.0. It's informational: browsers don't use it.
- 5
00 00 00 00 … (20 bytes)Metadata and private data
Offset and both lengths of the XML metadata block, then offset and length of the private block. All zero in this file;
sample-metadata.wofffills them in. - 6
4F 53 2F 32 00 00 01 64 …A directory entry
The table name
OS/2, where its data starts (356), its compressed length (0x42, 66 bytes), its original length (0x60, 96 bytes) and the original table's checksum. Entries are sorted by tag. - 7
67 6C 79 66 … 00 00 0F FA 00 00 1E E0The glyph outlines
glyfshrinks from 7,904 to 4,090 bytes. Outlines are most of a font's size, so they decide how big the WOFF file is. - 8
68 65 61 64 … 00 00 00 36 00 00 00 36A table stored as is
headhas a compressed length equal to its original length, 54 bytes: compressing it wouldn't have made it smaller, so the encoder stored it raw.locais stored the same way. - 9
78 9C 63 60 …The table data
The tables follow the directory, each padded to a 4-byte boundary.
headcomes first here, raw;hheaafter it is a zlib stream, recognisable by its first bytes78 9C. A reader can unpack just the tables it needs.
Under the hood
How a WOFF file is built
Converting a font to WOFF is simple, which is part of why the format caught on:
- 1Take each table of the font (
cmap,glyf,head,nameand so on) and compress it separately with zlib. - 2Keep the compressed version only if it's smaller. Otherwise store the table as it was, like
headandlocain our sample. - 3Write a directory listing each table's position, compressed and original length, and original checksum, so a decoder can check its work.
- 4Optionally add a metadata block: UTF-8 XML, compressed with zlib, describing the font's vendor, credits, licence and copyright.
- 5Optionally add a private block at the very end, for the font maker's own data. Its format is undefined, and browsers ignore it.
Decoding reverses these steps and gives back a working font with the same tables. Because every table is compressed on its own, a tool can read one table, such as name to show the font's name, without unpacking the whole file.
The metadata block in practice
The specification says metadata must not affect how a font loads or renders, and browsers don't show it to visitors. It's for people and tools inspecting the file. Our sample-metadata.woff includes one: a <metadata> document with uniqueid, vendor, credits, description, license and copyright elements.
Related formats
WOFF vs WOFF2 vs TTF and OTF
| WOFF | WOFF2 | TTF / OTF | |
|---|---|---|---|
| Made for | The web | The web | Installing on computers; also accepted by browsers |
| Compression | zlib, table by table | Brotli, all tables together, after reshaping the outlines | None |
| Our regular sample | 6,092 bytes | 4,428 bytes | 11,588 bytes (TTF) |
| Browser support | All current browsers, IE 9+ | All current browsers, not IE | All current browsers |
| Install on Windows or macOS | No, convert first | No, convert first | Yes |
| Metadata block | Yes, zlib-compressed XML | Yes, Brotli-compressed XML | No; licence text lives in the name table |
| MIME type | font/woff | font/woff2 | font/ttf, font/otf |
For a site that only supports current browsers, serve WOFF2 alone. A WOFF fallback after it costs nothing for modern visitors, because a browser stops at the first source it can use:
@font-face {
font-family: "99helpers Sample";
src: url("/fonts/sample-regular.woff2") format("woff2"),
url("/fonts/sample-regular.woff") format("woff");
font-weight: 400;
font-display: swap;
}Troubleshooting
Why isn't my WOFF font working?
- CORS errors. Browsers fetch fonts in CORS mode, so a WOFF file on another domain or CDN needs an
Access-Control-Allow-Originheader from that server. Without it the font is blocked and the console shows why. - Old MIME type. Servers set up years ago often send
application/font-wofforapplication/x-font-woff. Browsers still accept the font, butfont/woffis the registered type. - Order of sources. If WOFF comes before WOFF2 in
src, every browser takes the larger WOFF file. List WOFF2 first. - Double-clicking it does nothing useful. Desktop systems don't install WOFF. Convert it to TTF or OTF, with fontTools or FontForge, if the licence allows desktop use.
- Icon fonts showing letters or boxes. Icon fonts map pictures to private-use code points. If the WOFF file fails to load, the browser shows those code points in a fallback font, usually as empty boxes.
How to
How to open and convert a WOFF file
- Preview it: use it in a page with
@font-face, or open it in FontForge. The specimen on this page draws our sample with the file itself. - Convert to TTF or OTF: in Python with fontTools, open the file with
TTFont('font.woff'), setfont.flavor = Noneand save it asfont.ttf(or.otfif the flavor isOTTO). FontForge can do the same through File, Generate Fonts. - Convert to WOFF2: set
font.flavor = 'woff2'in fontTools (it needs thebrotlipackage), or decode to TTF and run Google'swoff2_compress. - Read the metadata block: fontTools keeps it in
font.flavorData.metaData; any zlib tool can decompress it from the offset in the header. - List the tables:
ttx -l font.woffshows each table with its length and checksum.
Rights
Licences and fonts on the web
Two of WOFF's three authors are type designers, and the format's metadata block gives font makers a place to say who made the font and under which terms, travelling with the file. It isn't copy protection: WOFF is not encrypted and has no DRM. What protects a font is its licence, helped a little by the fact that WOFF files can't be installed as they are.
- Check the licence before converting. A desktop licence often doesn't cover web use. Open-source licences such as the SIL Open Font License allow it.
- Look inside the font. The
nametable holds the copyright and licence text, and theOS/2table'sfsTypefield records embedding permissions. Browsers generally don't enforcefsType, but it tells you what the maker intended. - Fonts are software, and font parsers have had security bugs. Chrome and Firefox check every web font with the OpenType Sanitizer before using it, which also rejects damaged files.
Free downloads
Sample WOFF files to download
Free sample WOFF fonts for testing @font-face set-ups, font loaders, converters and upload filters. They use 99helpers Sample, an original geometric typeface we drew for these pages, with Latin letters, digits, common punctuation and a few accented letters.
Aa Gg 99
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789 .,:;!?&@#()
14pxThe quick brown fox jumps over the lazy dog
20pxThe quick brown fox jumps over the lazy dog
32pxThe quick brown fox jumps over the lazy dog
48pxThe quick brown fox jumps over the lazy dog
What's inside sample-regular.woff
The regular weight with TrueType outlines, encoded with fontTools. The specimen above is drawn with this exact file.
Header
The
wOFFsignature, the TrueType flavor00 01 00 00, a length of 6,092 bytes and 10 tables.Table directory
Ten 20-byte entries sorted by tag, each with offset, compressed length, original length and checksum.
Compressed tables
Eight tables are zlib streams;
headandlocaare stored uncompressed because compression wouldn't have helped.Glyphs
99 glyphs: A to Z, a to z, 0 to 9, space,
.,:;!?&@#()-'"/, and á à â ä é è ê ë í ï ó ô ö ú ü ñ É Ü Ñ.Names and licence
Family
99helpers Sample, styleRegular, weight class 400, with the licence and a link back to this page in thenametable.
All sample WOFF files
Regular weight
sample-regular.woff · 5.9 KB (6,092 bytes)
99helpers Sample Regular (weight 400) with TrueType outlines, 99 glyphs. No metadata block.
- Testing `@font-face` and fallbacks
- Checking a server sends `font/woff`
Bold weight
sample-bold.woff · 5.9 KB (6,056 bytes)
The same family at weight 700, drawn with a heavier stroke. Declare it with the regular file under one family name.
- Testing weight matching
- Comparing real bold with the browser's synthetic bold
WOFF with CFF outlines
sample-cff.woff · 6.4 KB (6,512 bytes)
The regular font with PostScript-style CFF outlines (cubic curves) instead of TrueType ones. The header's flavor field is
OTTO.- Testing decoders and converters with both kinds of outlines
- Checking that tools keep `.otf` output for CFF fonts
WOFF with metadata and private data
sample-metadata.woff · 6.4 KB (6,517 bytes)
The regular font plus an extended metadata block (366 bytes of zlib-compressed XML: vendor, credits, description, licence, copyright) and a 57-byte private data block at the end.
- Testing tools that read or strip WOFF metadata
- Checking browsers ignore the extra blocks
Ways to test with them
- Fallback order: list
sample-regular.woffafter a WOFF2 file insrcand check in the network panel that only the WOFF2 file downloads. - MIME type: request the file with
curl -Iand look forContent-Type: font/woff. - Outline types: convert
sample-regular.woffandsample-cff.woffback to desktop fonts; the first should give a TTF, the second an OTF with aCFFtable. - Metadata: open
sample-metadata.woffin fontTools and printfont.flavorData.metaData; a converter that drops the block is losing licence information.
Free to use for testing, teaching and demos, commercially or not, with no attribution needed. A link back to this page is always appreciated.
Put it online
Have a WOFF file? Give it a link.
Drop a WOFF file on 99helpers and it gets its own address in seconds. Opening the link downloads the font, since browsers don't display font files on their own, and a page or site you host on 99helpers can load it with @font-face.
Questions
WOFF files, frequently asked
What is a WOFF file?
A font packaged for websites: a TrueType or OpenType font with its tables compressed with zlib. Browsers load it through CSS @font-face.
How do I open a WOFF file?
Use it in a web page with @font-face, or open it in a font editor such as FontForge. Browsers don't display font files on their own when you open them directly.
Can I install a WOFF font on my computer?
Not as it is. Convert it to TTF or OTF with fontTools or FontForge, then install that, if the font's licence allows desktop use.
Should I use WOFF or WOFF2?
WOFF2 for any current site: it is smaller and supported by every current browser. WOFF is only needed as a fallback for browsers from before about 2016.
What is the MIME type for WOFF?
font/woff, registered in RFC 8081 in 2017. The older application/font-woff is deprecated but still works in browsers.
Is a WOFF file the same font as the TTF?
Yes, in what matters: the same glyphs, metrics and features. Only the packaging differs, and converting back gives a working TTF or OTF.
Does WOFF protect a font from being copied?
No. It isn't encrypted and has no DRM. Anyone can save and convert a WOFF file; what you may do with it is set by the font's licence.
Related formats
Other file types explained
Keep going
Related
Sources
- W3C: WOFF File Format 1.0
- W3C: WOFF File Format 2.0
- RFC 8081: The font top-level media type
- MDN: @font-face src
- Wikipedia: Web Open Font Format
Last reviewed 27 October 2026.