Repackage a font between the bare TTF/OTF container, WOFF and WOFF2, with the result read back and checked before it is offered, plus a live preview and a correct @font-face rule
Initializing in your browser…
Convert between the formats a browser can really write, then open the output and name the format its first bytes say it is. AVIF, BMP and GIF are disabled because a canvas returns a PNG for all three.
Convert between Unix timestamps and dates in any of 400+ time zones, in seconds, milliseconds, microseconds or nanoseconds
Convert between MP3, WAV, OGG, AAC, M4A and FLAC with a bitrate, sample rate, channel count and bit depth that all reach the encoder, and a panel that reports what was actually written.
A desktop TTF needs to become the WOFF2 a site should serve. The numbers below are the ones the project's own end-to-end test prints for Liberation Sans, and every output is read back with fontTools before it is counted.
Input
sans.ttf, 139,512 bytes, 19 tables, 681 glyphs, TrueType outlines
What each target actually produces
WOFF2 sans.woff2 72,024 bytes 51.6% first four bytes wOF2 19 tables, 681 glyphs WOFF sans.woff 90,040 bytes 64.5% first four bytes wOFF 19 tables, 681 glyphs TTF already this format, nothing to do OTF sans.otf 139,512 bytes 100.0% the bytes are unchanged, and the page says so Each file was then loaded as a real FontFace before the Download button appeared.
TTF and OTF are the same container: which extension is right is decided by the glyph outlines, so a TrueType font saved as .otf is a rename and is labelled one rather than counted as a conversion. A font with PostScript outlines is refused a .ttf outright, because writing cubic curves as quadratics moves the shapes and is a job for a font editor. WOFF compresses each table with zlib and WOFF2 uses Brotli plus a transform of the glyph tables, which is why WOFF2 is the smaller of the two. Nothing is offered for download until it has been parsed again from its own bytes, loaded as a FontFace, and (for a bare font) checked table by table against the checksums it carries.
Load a TTF, OTF, WOFF or WOFF2 and this tool tells you what it actually is: the container, the outline format, the table list, the glyph count and the extension the file should be carrying. Then it repackages it into any of the three containers, reads the result back from its own bytes, loads it as a real font, and only then offers the download. WOFF2 is produced and read with Google's own woff2 code compiled to WebAssembly, so the format everybody actually wants is a real conversion rather than a renamed file.
Almost every confusion about font conversion comes from treating TTF, OTF, WOFF and WOFF2 as four formats. They are not. There are two independent things going on.
The first is the CONTAINER. A bare font is an sfnt: a twelve-byte header, a directory of tables, and the tables. WOFF 1.0 wraps exactly that with each table compressed by zlib, per the W3C WOFF File Format 1.0 Recommendation. WOFF 2.0 wraps it with Brotli and additionally transforms the glyf and loca tables, which is why it is the smallest of the three. Those are three containers holding the same font.
The second is the OUTLINE FORMAT. The glyph shapes are either TrueType quadratic curves in a glyf table, or PostScript cubic curves in a CFF or CFF2 table. And this is the part that matters: .ttf and .otf are the SAME container, and which extension is correct is decided by the outlines, not by you. A font with TrueType curves is a .ttf whatever it is called. That is why this tool reports the outline format it found and names the correct extension for it, and why choosing OTF for a TrueType font is labelled on screen as a rename that changes nothing about the file, rather than being presented as a conversion. Choosing TTF for a font with CFF outlines is refused outright, with the reason: turning cubic curves into quadratics moves the outlines and is a job for a font editor such as fontTools, not for a repackager.
Measured on Liberation Sans, 139,512 bytes with 19 tables and 681 glyphs, the four targets give 72,024 bytes as WOFF2 (51.6 percent), 90,040 as WOFF (64.5 percent), nothing to do for TTF, and the same 139,512 bytes under a .otf name. Going the other way, a 22,704-byte WOFF2 unpacks to a 93,500-byte bare font and repackages as a 32,164-byte WOFF, which is the honest picture of what WOFF costs next to WOFF2 and is why WOFF is a fallback rather than a target.
The check at the end is the point of the tool. The converted bytes are parsed again from scratch, the container they turned out to be is compared with the one you asked for, the file is loaded as a real FontFace, and a bare font has every table checksum and its whole-file checkSumAdjustment verified against the OpenType rules. If any of that disagrees, nothing is offered. The reason for being strict is that a browser will not catch this for you: measured on 2026-09-03 across Chromium, Firefox and WebKit, all three happily load a TTF that has merely been renamed .woff and served as font/woff with format('woff'), because the format hint is advisory and every engine sniffs the bytes. A renamed file therefore looks like it works, right up until it reaches a build pipeline, a font validator or a CDN that expects the format the name claims, and meanwhile it is twice the size of the WOFF it was supposed to be.
Everything runs in the page. The font is never uploaded, which matters when it is an unreleased brand face under licence.
A foundry ships a TTF or OTF for desktop use. WOFF2 is what a site should serve, and here that is a real Brotli conversion at around half the size rather than a renamed file.
A font that arrived named .woff may not be one. The container, the outline format and the table list are read from the bytes, so a mislabelled file is obvious immediately.
A WOFF or WOFF2 pulled off a site can be unwrapped back to the bare font it holds, with the extension named from its outlines rather than guessed.
A WOFF made from the same source gives older browsers something to load. The size comparison on screen shows exactly what that fallback costs against the WOFF2.
All of them between the three containers: bare font to WOFF and WOFF2, WOFF to bare and to WOFF2, WOFF2 to bare and to WOFF. The one thing refused is changing the outline format, which is what TTF to OTF would mean for a font with PostScript curves. Saving a TrueType font under a .otf name is allowed and is labelled a rename, because that is all it is.
Because that is not a container change. A .otf normally holds PostScript cubic curves and a .ttf holds TrueType quadratics, and converting between them approximates every curve with a different kind of curve. The result is a different set of outlines, and doing it well needs a font editor such as fontTools' otf2ttf. Renaming the file instead would be dishonest, so the tool says so rather than doing it.
On Liberation Sans, 139,512 bytes becomes 72,024, which is 51.6 percent. On the CFF-outline STIXGeneral, 369,156 becomes 212,864, which is 57.7 percent. WOFF from the same fonts is 64.5 and 69.7 percent, so WOFF2 wins by a clear margin on both.
No. EOT was an Internet Explorer format and is not supported as input or output. WOFF2 with WOFF as a fallback covers every browser still in use.
Because it is read back before you get it. The output is parsed again from its own bytes, the container is compared with the one you asked for, it is loaded as a real FontFace, and a bare font has every table checksum and its whole-file checkSumAdjustment verified. If any of that fails, no download is offered. This matters because browsers will not catch it for you: Chromium, Firefox and WebKit all load a TTF that has merely been renamed .woff.
No. The parsing, the zlib compression and the WebAssembly WOFF2 coder all run in your browser, so a font under licence never leaves your machine.
Conversions run on your device in JavaScript. The values you enter are never sent over the network.