Binary STL is what slicers and CAD tools save by default — packed, fast, opaque. ASCII STL is the same geometry written as plain text: a solid name header, seven lines per triangle, and an endsolid name footer. Converting binary to ASCII trades a 4–6× size penalty for something you can grep, diff, commit to Git with meaningful line history, or paste into a bug report. This is the reference for what the converter actually does — the bytes it reads, the text it writes, the things that get rebuilt on the way out, and the realistic uses (and misuses) of ASCII STL as a long-term format. Drop a file above to convert it; everything below is the documentation.
grep vertex returns every coordinate; wc -l counts lines per triangle (7) plus the two header linesgit diff shows added / moved triangles instead of an opaque binary blob changesolid name line carries your original filename stem so you can identify the file from inside a long logsolid — caught by the 84 + 50 × triCount size check, never misidentifiedDrop a binary STL file onto the tool. The detector reads bytes 80–83 as a little-endian Uint32 triangle count, checks file_size === 84 + 50 × triCount, and confirms the file is binary even if its header text starts with solid.
three.js STLLoader parses every 50-byte triangle record (12 bytes of normal + 36 bytes of vertices + 2 bytes of attribute) into a BufferGeometry.
The geometry is flattened so each triangle has its own three vertex positions — exactly how ASCII STL expects to see them.
The ASCII writer emits one facet normal block per triangle (7 lines each), with face normals **recomputed** from the vertex order rather than copied from the source. Lines are joined with \n (LF) — not CRLF.
The file downloads as <original-name>.ascii.stl. The solid / endsolid names use the source filename's stem.
Every triangle expands to exactly seven lines. The indentation, casing, and spacing below are what gets written. The solid / endsolid names are the source filename without its extension; this lets you identify the source from the file body alone.
| Line | Pattern | Notes |
|---|---|---|
| 1 | solid <name> | One per file. <name> is the source filename stem. |
| 2 | facet normal <nx> <ny> <nz> | Two-space indent. Normal recomputed from vertices, not copied from the binary record. |
| 3 | outer loop | Four-space indent. STL has no other loop type but the keyword is mandatory. |
| 4 | vertex <x> <y> <z> | Six-space indent. Coordinates in JavaScript's default number-to-string format — no fixed precision. |
| 5 | vertex <x> <y> <z> | Second vertex. |
| 6 | vertex <x> <y> <z> | Third vertex. |
| 7 | endloop | Four-space indent. |
| 8 | endfacet | Two-space indent. Closes the facet block. |
| … | (lines 2–8 repeat per triangle) | |
| last | endsolid <name> | Matches the opening solid line. |
The numbers the parser uses to decide a file is actually binary. Same equation in both directions: the converter writes binary files that conform to it, and reads binary files by checking it.
| Bytes | Field | Value the detector cares about |
|---|---|---|
| 0–79 | Header (ASCII text) | Sniffed for the literal token solid. If absent, file is binary regardless of size. |
| 80–83 | Triangle count | Read as little-endian Uint32. Used to compute expected file size. |
| 84–… | Triangle records | 50 bytes each: 12-byte normal + 36-byte vertices + 2-byte attribute. |
| Total | File size | Must equal 84 + 50 × triCount for the file to be classified binary. Mismatch → treated as ASCII. |
ASCII STL is a *workflow* format, not a *storage* format. Use this table to decide whether to keep the ASCII output or convert it straight back to binary.
| Use case | Recommendation | Why |
|---|---|---|
| Slicing for 3D print | Convert back to binary | Slicers parse binary roughly an order of magnitude faster. ASCII can stall the UI on multi-MB files. |
| Git-tracked geometry source | ASCII | Line-based diffs surface real changes; binary is one opaque blob to Git. |
| Code review of a generated mesh | ASCII | Reviewer can read the file like a text artefact; PR diff highlights moved or added triangles. |
| Sharing a 30k-triangle bug repro | ASCII | Pastable into an issue tracker / gist. Compressed (gzip), the size penalty narrows to ~2×. |
| Archival of a model library | Binary | Smaller, parsed faster, and the format is well-supported indefinitely. |
| Sending to a CAM operator or print bureau | Binary | Universally the expected input. ASCII works but adds processing time on their side. |
Concrete uses for the ASCII output. The first two assume the file is small enough to open in a text editor; the third is the recommended Git workflow.
ASCII STL with default JavaScript number formatting: integers print without decimal points (1, 0, -1), so unit-cube vertices look unusually clean. The two triangles below tile the cube's bottom face; vertex winding is set so the recomputed cross product gives an outward (downward) normal of (0, 0, -1). Real meshes have floats like 2.3456789 taking ~8–10 chars each.
solid cube
facet normal 0 0 -1
outer loop
vertex 0 0 0
vertex 1 1 0
vertex 1 0 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 0 0 0
vertex 0 1 0
vertex 1 1 0
endloop
endfacet
endsolid cubeBecause the writer indents vertex lines with exactly six spaces, a fixed grep picks them out cleanly. Pipe through sort -u to deduplicate. This works for any file the converter produces — there are no ambiguous indentation cases.
grep -E '^ vertex ' model.ascii.stl | sort -u | head -n 5
Commit ASCII to the repo so git log -p shows actual geometry edits. Generate binary at build time with the STL ASCII → Binary Converter and ship that to the slicer.
.gitignore build/ src/ bracket.ascii.stl # committed, human-readable housing.ascii.stl build/ bracket.binary.stl # generated, faster to load housing.binary.stl # diff sample line: # - vertex 12.5 0 4.2 # + vertex 12.5 0 4.7
Once you're done inspecting, feed the ASCII file into the STL ASCII → Binary Converter. Triangle count is preserved; geometry is preserved; only the header text and (recomputed) normals differ between original-binary and round-tripped-binary.
# Inspect: # binary -> ASCII (this tool) # Edit / diff / commit # Slice: # ASCII -> binary (the reverse tool)
Some CAD exporters write the literal word solid as the first five bytes of the 80-byte header. The detector cross-checks the size: if file_size === 84 + 50 × triCount for the triangle count it finds at offset 80, the file is treated as binary even when the header text says otherwise. The conversion proceeds normally.
If the detector decides the file is already ASCII (starts with solid *and* its size doesn't match the binary equation), the converter refuses with the message This file is already ASCII STL. No partial work — the upload is rejected client-side before parsing begins.
A non-standard convention some tools (Materialise Magics, certain hobby exporters) use to encode RGB colour into the attribute Uint16 at the end of each binary record. ASCII STL has no place to put that value — the converter drops it, and the round-trip back to binary writes 0x0000 for every face. If you need to preserve per-face colour, convert to GLB instead via the STL to GLB tool.
A 5 MB binary STL typically writes ~25 MB of ASCII, which can push you over the 25 MB free tier on download. Note that the tier limit gates the *input* size, not the output — so a 5 MB binary always converts; a 10 MB binary on Free works (input fits) but produces a 40–60 MB output you'll need bandwidth to keep.
The ASCII writer recomputes every face normal from (b - a) × (c - a) and normalises it, regardless of what the binary source stored. If the source had deliberately flipped normals, the ASCII output won't preserve them — but the vertex order (and therefore the geometry) is unchanged.
The cross product is the zero vector; the writer outputs facet normal 0 0 0. Slicers usually load this without complaint but flag it as a non-manifold face. Most ASCII STL parsers tolerate the (0,0,0) normal — the geometry is intact, only the normal is degenerate.
If file_size > 84 + 50 × triCount and the first 80 bytes start with the literal word solid, the detector picks ASCII and the converter refuses with This file is already ASCII STL. If the header doesn't start with solid, three.js STLLoader reads the declared triangle count at offset 80 and stops there — trailing bytes are silently ignored, and the ASCII output contains exactly those triangles. Run Mesh Metadata Inspector if you want to confirm whether a suspect file has unexpected tail data.
Most slicers parse binary roughly an order of magnitude faster than ASCII because they can memcpy 50-byte records directly into a vertex buffer. ASCII forces a text tokenizer to walk every line and parse every coordinate. Use ASCII for inspection and version control; flip back to binary with the STL ASCII → Binary tool before slicing.
0 bytes uploaded. STL Binary → ASCII Converter runs entirely in your browser using three.js and WebGL. Your meshes never leave your device.
Three reasons: **diffs** (Git shows line-level changes instead of an opaque blob), **inspection** (open in any text editor, no specialised tool needed), and **debugging** (paste a problematic triangle into an issue tracker or shared with a teammate). For slicing and archival, stick with binary.
Typically 4–6× the binary size. The exact ratio depends on how many decimal digits each coordinate needs in JavaScript's default number-to-string format. Models full of long fractional coordinates (photogrammetry, terrain) skew toward 6×; CAD output with clean axis-aligned faces skews toward 4×. The byte-cost table above shows the per-triangle math.
Yes — every vertex coordinate is round-tripped as a JavaScript number (64-bit double internally) through the writer, which prints them at full default precision. The original binary file stored these as Float32, so the ASCII output is no less precise than the source. The face normal is recomputed (not copied), but the vertex order — and therefore the geometry — is identical.
Many binary STL exporters write a normal that doesn't actually equal the cross product of the triangle's vertex order. Sometimes this is benign — slicers don't trust stored normals anyway — but it makes ASCII output confusing when reading it as a diff. Recomputing guarantees that every facet normal line agrees with the right-hand rule applied to the three vertex lines below it.
The <name> uses the source filename stem. Upload bracket.stl and the output's header is solid bracket / footer is endsolid bracket. Binary STL has no name field of its own (only the freeform 80-byte header), so this is reconstructed, not copied. If you need to preserve a richer name, edit the line directly in your text editor afterwards.
LF (\n) only. The writer joins lines with \n and never emits \r. If you need CRLF for a tool that requires Windows line endings, convert with unix2dos after download.
No. Triangle count and vertex coordinates round-trip exactly; the 80-byte binary header is rewritten with our exporter signature; face normals are recomputed (and will generally differ from whatever the original binary file had stored); the 2-byte attribute field is zeroed (any per-face colour the original encoded there is dropped). Geometry is preserved, identity bytes are not.
STL doesn't share vertices across triangles. Every triangle stores its own three vertex coordinates, so an edge shared between two faces appears twice in the file (once per face). A model with 8 distinct vertex positions but 12 triangles will print 36 vertex lines. If you want a format that deduplicates shared vertices, convert to OBJ (STL to OBJ) or GLB (STL to GLB).
Yes — every major slicer (Cura, PrusaSlicer, Bambu Studio, OrcaSlicer, SuperSlicer) accepts ASCII STL, as do Blender, Fusion 360, SolidWorks, MeshLab, and 3D Builder. The output is fully spec-compliant: lowercase keywords, mandatory outer loop line, three vertex lines per facet, and a matching solid / endsolid name pair. Loading speed is the only practical difference vs binary.
Yes, as a side effect. The 80-byte binary header (which often contains exporter / authoring-tool names, build dates, or copyrights) is read for detection but never written into the ASCII output — only the filename stem appears in the solid line. If you specifically need to scrub binary STL metadata, this round trip works as a de facto privacy step. The Mesh Metadata Inspector shows what was in the original header before you convert.
Yes. As long as the file follows the spec — solid <name> header, every facet block has the keywords above in order, three vertex lines per facet, matching endsolid <name> — the STL ASCII → Binary Converter will accept it. Common manual edits that work: renaming the solid, deleting a stray triangle, scaling all coordinates with sed. Common edits that don't: changing the number of vertex lines per facet (must be 3), dropping the outer loop line, mismatched facet / endfacet pairs.
No. The converter runs entirely in your browser via three.js — the binary input, the ASCII output, and every coordinate in between stays on the page. When signed in, the dashboard records an anonymous tool_run event with the file size and a download event on save; neither carries any of the file's contents. You can verify this in the DevTools Network tab: the only fetch during conversion is the event endpoint, with a JSON body of ~100 bytes.
Convert ASCII STL files to compact binary STL — typically 4–6× smaller, every byte verifiable. Lossless, free, runs in your browser. Documented byte layout, edge cases, and slicer compatibility below.
Open toolReveal the 80-byte STL header, GLB JSON chunk, software origin, vertex/face stats, and authoring tool from any 3D file. Browser-based, zero upload.
Open toolConvert STL meshes to Wavefront OBJ in your browser. Open the result in Blender, Maya, Cinema 4D, or any 3D tool. Privacy-first — zero upload.
Open toolConvert STL files to GLB (binary glTF) directly in your browser. Smaller, faster, and AR-ready. Zero upload — your meshes never leave your device.
Open tool