STL comes in two encodings that describe exactly the same thing. Choosing between them is usually trivial, but the details matter when you are parsing files, diffing them in version control, or debugging one that will not open.
Binary STL, byte by byte
80 bytes header (free-form, usually the exporter's name)
4 bytes uint32: number of triangles
per triangle, 50 bytes:
12 bytes normal vector (3 × float32)
12 bytes vertex 1 (3 × float32)
12 bytes vertex 2 (3 × float32)
12 bytes vertex 3 (3 × float32)
2 bytes attribute byte count (almost always zero)
So a valid binary STL is exactly 84 + 50 × N bytes. That identity is useful:
it lets you verify a file is complete without parsing it, and it means file
size predicts triangle count precisely. A one-million-triangle model is 50 MB,
always.
The two-byte attribute field at the end of each triangle is nominally unused. Some software repurposes it to store a per-triangle colour, in at least two mutually incompatible conventions. Nothing in the standard sanctions this, and most tools ignore the field entirely, so do not rely on colour surviving an STL round trip.
ASCII STL
The same mesh as readable text:
solid name
facet normal 0.0 0.0 -1.0
outer loop
vertex 0.0 0.0 0.0
vertex 20.0 20.0 0.0
vertex 20.0 0.0 0.0
endloop
endfacet
...
endsolid name
Each triangle takes roughly 250–300 bytes depending on how many digits the exporter writes, against 50 bytes in binary — so ASCII files run about five to six times larger. The precision is not better; the numbers are the same float32 values printed in decimal, sometimes with rounding that makes them slightly worse.
The 'solid' trap
The obvious way to detect the format is to check whether the file starts with
solid. This fails, because the 80-byte binary header is free-form and several
exporters write descriptions into it that begin with that exact word.
A parser that only checks the first five bytes will try to read a binary file
as text, find no facet lines, and report an empty or corrupt mesh. The robust
check is arithmetic: read the triangle count at byte 80 and test whether the
file is 84 + 50 × N bytes long. If it is, the file is binary regardless of
what the header says.
This is worth knowing because it explains a specific failure mode — a file that opens fine in one program and appears empty in another is often hitting exactly this.
Which one to use
Binary, unless you have a reason. It is smaller, parses faster, and every tool written in the last thirty years reads it.
ASCII earns its place in narrow cases:
- Inspecting a file by hand when you suspect bad geometry or a broken exporter.
- Diffing in version control, where a text file produces a meaningful diff and a binary one does not. Note that triangle order is not stable across exports, so even here the diffs are often unhelpful.
- Legacy tooling that only accepts text.
Converting is trivial in either direction: open the file in Blender, MeshLab, FreeCAD or any slicer and export again with the encoding you want. The geometry does not change.
Neither variant fixes STL's real limitations
The encoding choice does not address what STL fundamentally lacks: no units, no reliable colour, no shared vertices, no object structure. If those matter, the answer is a different format rather than a different encoding — see the format comparison and why STL has no units.
Mes3D reads both encodings and detects which one it is given automatically, using the size check rather than the header text.