stl to 3mf
Read the triangles out of a binary or ASCII STL, write them into a 3MF package — in this tab.
Convert .stl to .3mf — 0 B of WebAssembly, 3 parts in the ZIP, both measured in the tab.
This page converts one direction only: mesh container in, mesh container out.
Nothing is read until you press it.
model.3mf
- Triangles
- —
- Bounding box (mm)
- —
- Source STL
- —
- STL flavour read
- —
- 3MF package
- —
- Model part
- —
- ZIP method
- —
- Time
- —
- Our control STL
- 684 B
- Triangles it holds — (684 − 84) / 50
- 12
- 3MF it becomes, stored / deflated
- 2,715 / 1,318 B
- WebAssembly this page downloads
- 0 B
Every cell is measured on this page, on 2026-10-29: the 684-byte cube-10x10-reference.stl is read by the shipped STL reader in this tab, and 2,715 (stored) / 1,318 (deflated) bytes come from the writer running in the same tab. 0 B of WebAssembly holds here for a structural reason, not as a boast: an STL already is triangles and a 3MF is a ZIP of text, so neither side needs a CAD kernel. The second row is the binary-STL size identity, 84 + 50 × n, true for any triangle count — not only for these 12.
What changes is the container, not the geometry
The honest description of this stl to 3mf converter is a container swap. A binary STL is a flat list: an 84-byte header, then 50 bytes per triangle holding a normal, three vertices and a two-byte attribute count that is almost always zero. A 3MF is an OPC ZIP package whose model part stores the same triangles as XML. This page reads the first shape and writes the second, and every triangle that goes in comes out with the same three corners in the same winding order.
Everything an STL never had, the output does not invent. There is no colour, no multi-material assignment, no PrintTicket, no object name, no hierarchy and no thumbnail in the package it writes. There is exactly one object, one mesh, one build item, and a unit attribute set to millimeter. That unit is this page’s choice rather than a reading of the source, because an STL carries no unit field at all — the numbers are copied exactly, and the label is an assumption you may have to correct downstream.
| Kept | Written as | Not present at all |
|---|---|---|
| Every triangle’s three vertex positions | <vertices> plus <triangles> indices | Colour and materials |
| Triangle order and winding | one <triangle v1 v2 v3> per input facet, in file order | Print settings, plate position, layer height |
| Absolute coordinates, including any offset from the origin | numbers copied, no centring and no rescaling | Object names, parts, components, thumbnails |
| A unit declaration | <model unit="millimeter"> — this page’s choice | Anything the STL did not carry in the first place |
Two pages carry the whole 3MF footprint of this site, and there will not be a third: the 3MF to STL page reads a package, this page writes one, and STEP↔STL remains the main line here. Any further 3MF question is answered inside these two pages rather than on a page of its own.
STL to STEP is a different job, and this page does not do it
It is worth being blunt about the boundary, because “convert” covers two very different operations. Wrapping triangles in a new container is a serialisation change: no information is added, and none has to be inferred. Rebuilding a STEP file is a modelling change: it needs a boundary representation — analytic and NURBS surfaces, curves, and the topology that stitches them into a solid — and an STL has thrown that away. A STEP file produced from a mesh has to have every surface fitted, and the result is an approximation whose quality depends on the fit, not on the file it started from.
So the answer to “can I convert stl to step” is not the answer to “can I convert stl to 3mf”. The first needs reconstruction; the second needs a ZIP writer. The STL to STEP page sets out the reconstruction case in its own numbers, and nothing on this page changes it.
What the .3mf this page writes contains
Three parts, and no others. [Content_Types].xml maps the two extensions, _rels/.rels names the root model part, and 3D/3dmodel.model holds the geometry. The model element declares the core 3MF namespace and unit="millimeter", then declares one <object id="1" type="model"> whose <mesh> carries every vertex and every triangle, and closes with <build><item objectid="1"/></build>.
Vertices are not merged. A shared vertex table would make a cube eight entries instead of thirty-six, but merging costs a hash of 3n positions and changes the indexing this page can verify against the input, so each triangle keeps its own three vertex entries and points at indices 3i, 3i+1, 3i+2. That is also why the stored package is larger than the STL it came from: the same geometry written as text costs more bytes than 50 bytes per triangle, until the model part is deflated.
ZIP entries are written stored (method 0) with a CRC32 per part, which every ZIP reader accepts without negotiation. The model part is deflated instead when the runtime reports CompressionStream('deflate-raw') — probed by constructing one, not assumed — and the fallback is the stored path. The result panel prints the method that actually ran, so the byte counts you see are the ones your browser produced.
When it will not convert, or comes out wrong
- Not an STL at all. The reader accepts a binary STL only when the length is exactly
84 + 50 × nfor the count in its header, and an ASCII STL only whenfacet normalandvertexlines are both present. A file that is neither is refused with a message, and nothing is written. - A truncated or padded ASCII STL. ASCII facet blocks hold exactly three vertices, so the facet count and the vertex count are compared before anything is written. A file whose two counts disagree is reported as truncated rather than silently half-converted.
- A binary STL whose header lies. If the stated triangle count does not match the file length, the binary path is abandoned and the ASCII path is tried. Nothing is guessed from the first four letters: plenty of binary STLs have an 80-byte comment that begins with
solid. - A non-manifold or open mesh. It is written exactly as it arrived. There is no stitching, no healing and no normal fix-up, so holes stay holes and a mirrored shell stays inside out if the source was. The edge count is how you check before a slicer complains.
- A very large STL. The largest file exercised is the 68,135,384-byte STL (1,362,706 triangles) expanded from a 16,342,603-byte 3MF sample; it becomes a 284,165,434-byte stored package or 27,354,671 bytes deflated, at more than 1 GB of process memory in Node. Browser peak memory on that file is unverified, and larger files are unverified. The stored path is the expensive one: the model part is 284,164,508 bytes of text before ZIP.
- Metadata beyond the unit. A 3MF can carry far more than this writer emits. If you need colour, materials or print settings, they have to come from an authoring tool, not from an STL that never held them.
The numbers on this page, and where they come from
Published · Last updated
| Input | Bytes in | Triangles | Bounding box | Stored 3MF | Deflated 3MF | Read back |
|---|---|---|---|---|---|---|
cube-10x10-reference.stl (binary) | 684 | 12 | 10 × 10 × 10 mm | 2,715 | 1,318 | 12 triangles, same box |
| the same cube written as ASCII | 1,206 | 12 | 10 × 10 × 10 mm | 2,715 | — | 12 triangles, same box |
EDULITE_A3_robot-arm.3mf expanded to STL (upper bound) | 68,135,384 | 1,362,706 | 834.827 × 525.459 × 72.5 mm | 284,165,434 | 27,354,671 | 1,362,706 triangles, same box |
The control STL obeys the identity this site prints everywhere: 84 + 50 × 12 = 684. The upper-bound row starts from the STL that the 3MF to STL page writes out of its largest sample, so the two directions are exercised on the same 1,362,706 triangles. Both samples live in _dev/, outside the deploy tree, and never become downloadable.
npm test
That command parses both STL flavours with the shipped reader, writes the package both ways, then reads the result back with the site’s own 3MF reader and compares triangle count, byte count and bounding box — the same reader that powers the 3MF to STL page.
Questions people actually ask
What does converting an STL to 3MF actually change? The container and nothing else. An STL stores one triangle per fixed 50-byte record; a 3MF stores the same vertices as XML inside a ZIP package. The triangles, their order and their winding come out unchanged, and the 3MF this page writes has no colour, no material assignment and no print settings, because the STL had none to carry over.
Can I get an editable STEP file back from an STL this way? No. A STEP file needs a boundary representation — surfaces, curves and their topology — and an STL holds only triangles. Replacing the container does not recreate that data. The separate question of whether an STL can ever become STEP at all is answered on its own page, and wrapping an STL in 3MF changes nothing about it.
Does this STL to 3MF converter upload my file? No. The page is static, and the worker reads bytes it already has in this tab and writes the package there. No WebAssembly kernel is downloaded either: 0 bytes, because parsing 50-byte triangle records and writing a ZIP needs no CAD kernel.
Why is the 3MF bigger than the STL when stored, and smaller when deflated? Because the model part is text. Every vertex becomes an element with three quoted decimal attributes, and this writer does not merge vertices, so each triangle carries three vertex entries. Our 1,362,706-triangle upper-bound sample is 68,135,384 bytes as binary STL, 284,165,434 bytes as a stored package, and 27,354,671 bytes once the model part is deflated.
Which browser features does the writer depend on? Only standard ones for the stored path: DataView, typed arrays and a hand-rolled CRC32. The deflate path additionally asks for CompressionStream('deflate-raw') and falls back to stored output when that constructor throws, which is why the result panel prints the method that actually ran instead of assuming one. Chrome 156 is the only browser tested here; Safari, Firefox and iOS are unverified.
Is the unit in the output really millimetres? The model element says unit="millimeter", and that is this page's choice rather than a reading of the source: an STL has no unit field at all, so there is nothing to read. If your STL was authored in inches, the numbers are copied exactly and the package labels them millimetres, which is wrong by a factor of 25.4 unless you scale the mesh yourself.
This page does not claim to recover CAD features. A mesh container goes in, a mesh container comes out — the same triangles, re-serialised.
Sponsored link: Creality’s official store (3D printers, scanners, filament and parts) is an affiliate partner — clicking it may earn this site a commission. It changes nothing about the converter; see what sponsored links mean here.