How to ttf vs otf: what the magic bytes tell you
- Step 1Identify the magic — Drop the font into the identifier. `00 01 00 00` (or the Apple `true` magic) → `ttf`, quadratic outlines. `OTTO` (`4F 54 54 4F`) → `otf`, cubic CFF outlines. Both report a `Tables` count from the sfnt directory.
- Step 2Note what the magic does not say — The magic distinguishes outline format only. It does not tell you whether hinting is present, how many glyphs there are, or whether it is a variable font. Use /font-tools/font-metadata-extractor and /font-tools/glyph-count-analyzer for those facts.
- Step 3Check the extension match — If `extension_matches_format` is false, the filename is wrong. An `.otf` reporting `ttf`, or vice versa, is a rename, not a corruption — the bytes are still a valid sfnt.
- Step 4Decide if it matters for your target — For the web it does not: both wrap into WOFF2 identically. For a desktop installer or a print workflow that prefers PostScript outlines, the CFF/TrueType distinction can matter — keep the extension honest.
- Step 5Fix a mismatch — If only the extension is wrong, rename it to match the detected format. If you actually need the other outline format, that is a real conversion (FontForge / fonttools on the desktop), not a rename — the outlines themselves differ.
- Step 6Ship to the web — Whichever you have, convert with /font-tools/ttf-to-woff2 (CFF and TrueType both wrap fine). The browser renders both via the system text engine; the inner format is invisible at typical sizes.
TTF vs OTF at the byte and table level
Both are sfnt containers; the magic at offset zero and the glyph-outline table are what differ. The detector reads the magic and the table count only.
| Property | TTF | OTF (CFF) |
|---|---|---|
| Magic at offset 0 | 00 01 00 00 (also Apple true / 74 72 75 65) | 4F 54 54 4F (OTTO) |
Reported format | ttf | otf |
| Glyph outline table | glyf (quadratic Béziers) | CFF (cubic Béziers, PostScript) |
| Hinting | Optional TrueType hinting (fpgm/prep/cvt) | No native TrueType hinting; PS hints only |
| Container | sfnt | sfnt (identical structure) |
| Shared tables | cmap, head, hhea, hmtx, maxp, name, OS/2, post, GSUB/GPOS … | same set |
Myth vs reality
Common claims about TTF vs OTF, checked against what the format actually guarantees.
| Claim | Reality |
|---|---|
| "OTF is always smaller" | Often true for Latin (cubic outlines need fewer points), but not guaranteed; depends on the design and glyph count. |
| "TTF has hinting, OTF doesn't" | TTF can carry TrueType hinting but may ship with none. OTF has PostScript hints, just not the TrueType bytecode kind. |
| "OTF supports OpenType features, TTF doesn't" | False. GSUB/GPOS (ligatures, kerning, alternates) live in both. See /font-tools/opentype-features-inspector. |
| "You must convert OTF→TTF for the web" | False. Convert either directly to WOFF2; the inner outline format is irrelevant to the browser. |
| "The extension tells you the format" | False — that is the entire reason this tool exists. Only the magic bytes are authoritative. |
Cookbook
Worked outputs from the identifier so you can see exactly how TTF and OTF differ in the report. The action column points at the right sibling tool when you need to do something about it.
TrueType — quadratic outlines
ExampleMagic 0x00010000. The font stores glyphs in a glyf table; it may or may not be hinted.
{
"format": "ttf",
"magic": "0x00010000",
"description": "TrueType outline font (sfnt with TrueType glyphs).",
"extension_matches_format": true,
"Tables": 17
}OpenType/CFF — cubic outlines
ExampleMagic OTTO. The font stores glyphs in a CFF table; cubic Béziers, PostScript hinting.
{
"format": "otf",
"magic": "0x4F54544F",
"description": "OpenType / CFF outline font (sfnt with PostScript glyphs).",
"extension_matches_format": true,
"Tables": 12
}OTF mislabelled as .ttf
ExampleThe most common real-world mismatch. The bytes are OTTO; only the extension is wrong.
Input: DisplayFace.ttf
{
"format": "otf",
"magic": "0x4F54544F",
"extension_matches_format": false,
"Tables": 11
}
Action: rename to .otf (no conversion needed — it is already valid OpenType).Apple 'true' magic is still TTF
ExampleLegacy Mac TrueType uses the 'true' magic. The tool reports ttf so you don't mistake it for an unknown format.
{
"format": "ttf",
"magic": "0x74727565",
"description": "TrueType (Apple variant — \"true\" magic).",
"extension_matches_format": true,
"Tables": 14
}Both wrap into WOFF2 the same way
ExampleWhen you take either to the web, the wrapper records the inner flavor — but the browser doesn't care which it is.
TTF → WOFF2: Wrapped flavor 0x00010000 OTF → WOFF2: Wrapped flavor 0x4F54544F (OTTO) Both load identically via the system text engine. (Convert with /font-tools/ttf-to-woff2 .)
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.
A variable TTF
Still reports ttfVariable fonts are sfnt files too. A variable TrueType keeps the 00 01 00 00 magic and reports ttf — the magic says nothing about the presence of an fvar table. To detect variability, use /font-tools/font-metadata-extractor (it reads fvar) or freeze an instance with /font-tools/variable-font-freezer.
OTF magic but a .ttf extension
Mismatch (file valid)extension_matches_format: false with format: otf. The file is a legitimate OpenType/CFF font; only the name is wrong. Rename to .otf. Converting outlines TTF↔OTF is a real, lossy operation (quadratic↔cubic), so don't do it just to satisfy an extension.
A .ttc renamed to .ttf
Reports ttc, not ttfIf the magic is ttcf, the tool reports format: ttc regardless of extension. A collection is neither plain TTF nor OTF — it bundles multiple faces. Split a face out on the desktop before treating it as a single TTF/OTF.
Tables count looks tiny (e.g. 2–3)
SuspectA real text font has roughly 9–20 sfnt tables. A magic that matches but a Tables value of 2 or 3 suggests a truncated or hand-crafted file. The detector still reports the format from the magic — pair with /font-tools/font-metadata-extractor to confirm the font actually opens.
Expecting hinting info from the magic
Not available hereThe magic cannot tell you whether TrueType hinting is present — that requires reading the fpgm/prep/cvt tables. If hinting matters (small-size screen rendering), inspect the font; or strip it deliberately with /font-tools/hinting-stripper to compare.
CFF2 (CFF version 2) variable OTF
Reports otfA modern variable OpenType with a CFF2 table still carries the OTTO magic and reports otf. The magic does not distinguish CFF from CFF2 — both are PostScript outlines under the OTTO flavor.
Web wrapper hides the inner flavor
Use Wrapped flavorIf you drop a .woff2, the top-level format is woff2, not ttf/otf. To learn whether the wrapped font is TrueType or CFF, read the Wrapped flavor extra: 0x00010000 = TrueType, 0x4F54544F = CFF/OpenType.
Believing OTF can't do ligatures
MythLigatures, kerning, and alternates live in GSUB/GPOS, which both TTF and OTF carry. The outline format is unrelated to OpenType layout features. Inspect them with /font-tools/opentype-features-inspector.
Frequently asked questions
What is the single difference the magic encodes?
Outline format. 00 01 00 00 means quadratic TrueType outlines in a glyf table; OTTO means cubic PostScript outlines in a CFF table. Everything else about the container is shared.
Does the browser render TTF and OTF differently?
Functionally no. Both render via the OS/browser text engine. CFF and TrueType can rasterise marginally differently on a subpixel grid, but at typical reading sizes the difference is invisible.
Is OTF really smaller than TTF?
Often for Latin scripts, because cubic outlines need fewer control points. But it is not guaranteed — glyph count, design complexity, and hinting all affect the total. The magic doesn't tell you the size; the file does.
Why does OTF have no TrueType hinting?
CFF outlines were designed for high-resolution PostScript printers, where pixel-level hinting was unnecessary. They carry PostScript hints instead. TrueType hinting is a different mechanism that only the glyf/fpgm family supports.
Can I convert OTF to TTF just by renaming?
No. The outline math differs (cubic vs quadratic), so a real conversion re-fits the curves and is slightly lossy. Renaming only fixes the extension when the bytes already match the target format.
For the web, should I pick TTF or OTF?
Neither — pick WOFF2. Convert whichever source you have with /font-tools/ttf-to-woff2. The inner outline format is recorded in the wrapper but has no practical effect on web rendering.
Does the magic tell me if it's a variable font?
No. Variable TrueType keeps 00 01 00 00 and variable OpenType keeps OTTO. Detect variability by reading the fvar table with /font-tools/font-metadata-extractor.
What's the 'true' magic I sometimes see?
Apple's legacy TrueType magic (74 72 75 65). It is functionally TrueType, so the identifier folds it into the ttf format.
Do both formats support kerning and ligatures?
Yes. Those features live in GPOS/GSUB, which both TTF and OTF carry. Inspect them with /font-tools/opentype-features-inspector.
What does the Tables number tell me?
It's the count of tables in the sfnt directory (uint16 at offset 4). It's a quick structural sanity check — a real text font has roughly 9–20 — but it doesn't validate the contents.
Is one format more accessible than the other?
No. Accessibility comes from the typeface design (x-height, weight contrast, glyph clarity), not the outline format. A well-made OTF and a well-made TTF are equally accessible.
My .otf reports otf and matches — anything to do?
Nothing. The extension is honest and the file is a valid OpenType font. If you're shipping to the web, convert to WOFF2; otherwise leave it as is.
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.