How to extract web fonts to ttf for licensing audits
- Step 1Inventory every production WOFF2 — Pull each distinct font from your CDN and product builds. Most teams have 10–50 unique WOFF2 files across app, marketing, and email. Record each file's source URL so the evidence packet ties a binary to where it actually ships.
- Step 2Decompress each WOFF2 to sfnt — Drop each file onto this tool. It verifies the `wOF2` magic and decompresses to TTF (TrueType) or OTF (CFF) — the extension follows the wrapped outline type. Every metadata table, including `name`, is reconstructed exactly. There are no options to set.
- Step 3Watch for the .otf flavour — CFF-flavoured fonts decompress to `.otf`, not `.ttf`. This is correct and does not affect the audit — the `name` table is identical either way. Note the format per file; some foundries only ship CFF.
- Step 4Extract the name-table licence records — Feed each decompressed TTF/OTF to [font-metadata-extractor](/font-tools/font-metadata-extractor). Capture name ID 0 (copyright), 7 (trademark), 8 (manufacturer), 13 (licence), and 14 (licence URL). These are the foundry's own declarations embedded in the name table.
- Step 5Cross-reference against your EULA pool — Match each extracted manufacturer / vendor / licence string to your purchased-licence records. Flag any font whose declaration has no matching EULA, or whose licence text restricts the use it is deployed in (e.g. desktop-only licence used as a web font).
- Step 6Assemble the evidence packet — For each font, retain the source URL, the decompressed sfnt, and the extracted name records. For dispute resolution also keep the original purchase records and any EULA documents the foundry shipped — the binary metadata is a declaration, not a substitute for the contract.
Name-table records that matter for an audit
These records survive the WOFF2 round-trip exactly. Read them from the decompressed sfnt with the metadata extractor.
| Record | Name ID | Audit relevance |
|---|---|---|
| Copyright notice | 0 | Identifies the rights holder and often the year/foundry |
| Manufacturer | 8 | The foundry — your first key for matching against the EULA pool |
| Licence description | 13 | The licence terms embedded in the binary (e.g. SIL OFL, or a commercial EULA summary) |
| Licence info URL | 14 | Link to the foundry's full licence — your evidence anchor |
| Trademark | 7 | Sometimes carries the foundry name when copyright is generic |
Per-font audit checklist
One row per production font. The decompress + extract workflow fills the middle columns; you supply the EULA match.
| Step | Tool / source | Output captured |
|---|---|---|
| Locate | CDN / build artifacts | Source URL + WOFF2 file |
| Decompress | woff2-to-ttf (this tool) | TTF/OTF sfnt + flavour (TTF or OTF) |
| Extract | font-metadata-extractor | Name IDs 0/7/8/13/14 |
| Match | Your EULA / purchase pool | Licence covers this use? (Y/N + reference) |
| Retain | Evidence store | URL + sfnt + records + purchase docs |
Cookbook
Real audit scenarios and what the decompress + extract steps surface. PII and confidential names are illustrative.
Inherited webfont with no paperwork
ExampleMarketing shipped a foundry font years ago; nobody can find the EULA. The binary's own name table tells you who to chase.
Production file: HeadlineGrotesk.woff2 (from CDN) 1. woff2-to-ttf -> HeadlineGrotesk.otf (CFF) 2. font-metadata-extractor reads: nameID 0 : (c) 2019 Acme Type Foundry nameID 7 : Acme Grotesk is a trademark of Acme nameID 8 : Acme Type Foundry nameID 13 : Licensed for web use, single domain nameID 14 : https://acmetype.example/license -> Match 'Acme Type Foundry' against purchase records.
Confirming a Google Fonts SIL OFL licence
ExampleGoogle Fonts ship under the SIL Open Font License, but the binary's name table should still declare it. Verify rather than assume.
Production file: inter-v13-latin-regular.woff2
1. woff2-to-ttf -> Inter-Regular.ttf
2. font-metadata-extractor reads:
nameID 13 : This Font Software is licensed under
the SIL Open Font License, Version 1.1
nameID 14 : https://openfontlicense.org
-> OFL permits web embedding. Cleared.Desktop-licensed font used as a web font
ExampleThe dangerous case: a font purchased under a desktop EULA was deployed as a web font. The licence text in nameID 13 reveals the restriction.
Production file: DisplaySerif.woff2
1. woff2-to-ttf -> DisplaySerif.otf
2. font-metadata-extractor reads:
nameID 13 : Desktop license. Web embedding and
@font-face hosting are NOT permitted.
-> FLAG: deployed use exceeds the licence. Escalate.Empty licence string — binary isn't definitive
ExampleSome foundries leave nameID 13/14 blank and ship the licence as a separate file. The absence of a string is not the absence of a licence.
Production file: brand-icons.woff2 1. woff2-to-ttf -> brand-icons.ttf 2. font-metadata-extractor reads: nameID 13 : (empty) nameID 14 : (empty) nameID 8 : Internal Design Team -> Check the upstream distribution for LICENSE.txt; the binary alone cannot clear or flag it.
CFF font decompresses to .otf mid-audit
ExampleDon't treat the .otf extension as an anomaly. The audit reads the same name records regardless of outline type.
Batch of 30 production WOFF2 files -> 22 decompress to .ttf (TrueType) 8 decompress to .otf (CFF/PostScript) All 30 feed into font-metadata-extractor identically. The extension reflects outline type, not metadata completeness. nameID 13/14 read the same way.
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.
Licence string (name ID 13) is empty
InconclusiveSome foundries — and many open-source fonts — leave name IDs 13 and 14 blank and ship the licence as a separate LICENSE.txt or OFL.txt in the distribution. An empty string is not proof the font is unlicensed; it means the binary is not self-describing. Check the upstream package and your purchase records before flagging or clearing it.
Font decompresses to .otf, not .ttf
By designCFF/PostScript fonts produce an OTTO-magic .otf on decompression. This is correct and does not affect the audit — the name table is identical to a TrueType font's, and the metadata extractor reads it the same way. Record the format per file but do not treat .otf as suspicious.
WOFF2 was subset before deployment
Preserved (what is there)If a production font was subset, the decompressed sfnt contains only the kept glyphs — decompression cannot restore glyphs that were never in the WOFF2. The name table (and thus the licence) almost always survives subsetting, so the audit is unaffected, but note that glyph coverage reflects the deployed subset, not the original family.
Manufacturer and copyright name different foundries
InvestigateA mismatch between name ID 8 (manufacturer) and the foundry named in name ID 0 (copyright) or name ID 7 (trademark) can indicate a relicensed, re-badged, or modified font. It is not automatically a violation, but it warrants checking the chain of custody — read all three with font-metadata-extractor and reconcile against your EULA pool.
File is not actually a WOFF2
Rejected — detected <FORMAT>A production asset mislabelled .woff2 that is really WOFF, TTF, or OTF is rejected by the magic gate (Expected a WOFF2 file but detected <FORMAT>). If it is already a TTF/OTF, skip decompression and feed it straight to the metadata extractor; if it is WOFF, treat it as the WOFF it is. Confirm with font-format-identifier.
Corrupt production WOFF2
Decompression failedA truncated or damaged CDN asset throws wawoff2 decompress failed. For an audit, that is itself a finding — your production font is corrupt — but it blocks metadata extraction. Re-fetch a clean copy from the source of record before drawing licensing conclusions.
Licence text is non-Latin or uses an unusual encoding
PreservedThe name table can store records in multiple platform/encoding/language combinations (e.g. a Japanese foundry's licence in Shift-JIS or UTF-16). Decompression preserves all of them exactly. The metadata extractor surfaces the records; have someone who reads the language verify the terms rather than relying on a machine summary.
Same font, multiple weights — audit each binary
By designLicences sometimes differ by weight or were purchased piecemeal. Decompress and extract every distinct WOFF2 (Regular, Bold, Italic…) rather than assuming the family shares one licence. The workflow is identical per file; the EULA match is per binary.
Very large CJK font on the free tier
Rejected — over limitA multi-megabyte CJK WOFF2 may exceed the 5 MB free-tier ceiling and be blocked before decompression. Use Pro (50 MB) or Developer (1 GB), or run the batch via the local @jadapps/runner on a paid tier. The size gate is a quota, not a format problem.
Decompressed hash differs from a known-good master
Preserved (functionally)Because WOFF2 normalises table ordering, the decompressed sfnt may not hash-match a TTF master you hold even when it is the same font. For audit purposes, compare the name/licence records and glyph coverage, not raw hashes — the metadata is what establishes licensing, and it is preserved exactly.
Frequently asked questions
Do WOFF2 files contain the same licence as the source TTF?
Yes — the name table records, including name ID 13 (licence) and 14 (licence URL), survive the WOFF2 round-trip exactly. The decompressed TTF/OTF carries identical licence strings to the source. WOFF2 is a lossless wrapper; it does not strip or alter metadata, which is precisely why decompressing is a reliable first audit step.
What if the licence string is empty?
Some foundries — and most open-source fonts — leave name IDs 13/14 blank and ship the licence as a separate file (LICENSE.txt, OFL.txt) in the distribution. An empty string is not evidence the font is unlicensed; it means the binary is not self-describing. Check the upstream package and your purchase records before clearing or flagging the font.
Why decompress at all — can't I read the metadata from the WOFF2?
Most font inspectors and editors cannot open the wOF2 container — they expect raw sfnt. Decompressing to TTF/OTF first gives every downstream tool, including font-metadata-extractor and any font editor your legal reviewer uses, a file it can actually read. The decompression preserves the name table exactly, so nothing is lost.
Is the audit data exposed to a server?
No. Both steps — decompression and metadata extraction — run entirely in your browser. The font binary never leaves the auditor's machine, which matters when the assets are unreleased or confidential. Only an anonymous run counter is recorded. On a paid tier you can run the whole batch through a local @jadapps/runner, which is also on your own machine.
Can I batch-process the whole production font set?
The browser UI handles one file per run, which is fine for the typical 10–50 distinct fonts. For larger estates, script it: the Node wawoff2 package uses the same WASM module, and on a paid tier you can POST each file to the local runner. See automate WOFF2 to TTF extraction at scale.
Which name-table records should I capture?
For a licensing audit, capture name ID 0 (copyright), 7 (trademark), 8 (manufacturer), 13 (licence description), and 14 (licence URL). The manufacturer (name ID 8) is your matching key against the EULA pool; name IDs 13/14 carry the actual terms. The metadata extractor surfaces all of these name-table records.
A font decompressed to .otf — does that change the audit?
No. The .otf extension just means the font has CFF/PostScript outlines. The name table and all licence records are identical to a TrueType font's, and the metadata extractor reads them the same way. Note the format for completeness, but treat .ttf and .otf results identically for licensing.
Is the binary metadata legally definitive?
It is the foundry's embedded declaration of licence, which is strong corroborating evidence — but not a substitute for the contract. For dispute resolution, retain the original purchase records and any EULA documents the foundry shipped alongside the binary. Use the extracted metadata to build the evidence packet, not to render the final legal verdict.
What if a font's manufacturer and copyright disagree?
That can indicate a re-badged, relicensed, or modified font and warrants investigating the chain of custody. It is not automatically a violation — fonts are sometimes legitimately licensed under a different name — but reconcile the manufacturer (name ID 8), copyright (name ID 0), and trademark (name ID 7) records against your purchase pool before clearing it.
Can I tell if a production font was subset?
Indirectly. A deployed font is often subset for size, so the decompressed sfnt may contain only a slice of the original glyph set. The licence (name table) survives subsetting, so the audit is unaffected, but if you also need to verify glyph coverage, inspect the decompressed file with glyph-inspector or character-coverage-map.
What size fonts can I audit?
Up to 5 MB on the free tier, 50 MB on Pro, and 1 GB on Developer per file. Because WOFF2 is heavily compressed, even large multi-script families usually fit under Pro. Only very large CJK fonts risk the free-tier ceiling — upgrade or use the runner for those.
How do I keep the audit reproducible?
Decompression is deterministic: the same WOFF2 always produces the same sfnt, and the same sfnt always yields the same name records. Store each file's source URL alongside its decompressed sfnt and extracted records so any reviewer can re-run the two steps and arrive at identical evidence.
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.