What is the difference between STEP and STL?
This is the most-asked question on this site's subject and there is a short honest answer: STEP describes surfaces, STL describes triangles. Every number below was measured on the machine that wrote this page and is re-checked by npm test. Nothing here is a rule of thumb.
The short version
A STEP file stores geometry as exact mathematical surfaces. A cylinder in a STEP file is a radius, a height and a position — no approximation involved, and the file is often human-readable text you could open in a text editor. An STL file stores a flat list of triangles, each one three points and a normal. The cylinder is gone. What remains is whatever number of flat facets the tessellator chose to approximate it with.
So the difference is not quality, not precision settings, not file format generation. It is what kind of thing the file knows about the part. One knows the exact shape; the other knows a finite set of flat panels that come close.
Where the difference shows up as a number
Since the two formats describe different kinds of thing, their file sizes are not comparable and a ratio between them means very little on its own. But side by side over the same seven test files, the sizes tell you something concrete: the direction of the size change depends on the shape, not on the quality of the conversion. Flat geometry shrinks dramatically, because a plane costs the same few bytes whether the file describes it as a surface or as two triangles. Curved geometry grows, because describing it as triangles costs more bytes than describing it as a radius.
| Test file | Source bytes | Normal tri | Output STL | Output ÷ source |
|---|---|---|---|---|
| simple-cube.stp | 8,247 | 12 | 684 B | 0.08× |
| cube-10x10.stp | 9,404 | 12 | 684 B | 0.07× |
| cube-10x10.igs (IGES) | 11,562 | 12 | 684 B | 0.06× |
| rounded-cube.step | 21,070 | 56 | 2,884 B | 0.14× |
| conical-surface.step | 9,640 | 516 | 25,884 B | 2.69× |
| as1_pe_203.stp (18 parts) | 139,752 | 6,088 | 304,484 B | 2.18× |
| as1-oc-214.stp (18 parts) | 441,968 | 7,372 | 368,684 B | 0.83× |
Read the first three rows and the last two rows as two different phenomena. The cubes are 8–12 KB of exact geometry that collapses into 684 bytes of triangles, because a box has six planes and each plane is two triangles. The cone and the assemblies run the other way: an output larger than its input, because the exact surface was cheap to describe and the triangles are not. The 18-part assembly is the clearest case. Its STEP file is 139,752 bytes and the STL that comes out is 304,484 bytes, a factor of 2.18, and the same part through a different AP protocol lands at 441,968 bytes of STEP for 368,684 bytes of STL. Neither number says anything about whether the conversion was good.
The number that actually matters: triangle count
If you keep one idea from this page, keep this one. An STL is a triangle count. A binary STL stores an 80-byte header, a 4-byte triangle count, and then exactly 50 bytes per triangle, so the whole file size is decided by the triangle count and nothing else:
| Identity | bytes = 84 + 50 × triangles |
|---|---|
| Inverted | triangles = (bytes − 84) ÷ 50 |
| Worked example | A 10 mm cube converts to 12 triangles, so 84 + 50 × 12 = 684 bytes. The IGES file describing the same solid also comes to 684 bytes, from the same 12 triangles. |
| Why it is trustworthy | The engine vendor ships a reference cube-10x10.stl next to the cube-10x10.stp it converts from. Our run of that STEP gives 12 triangles, and the vendor’s own file is 684 bytes on disk. Two independent artefacts, one identity. |
This is also why a bigger STL is not a better one. If two files of the same part differ in size, they differ in triangle count, which means a finer setting ran — not that the conversion was more correct.
Why the triangle count is a choice, not a fact
Because surfaces are being sampled, the number of triangles is set by how finely you asked. This converter offers three settings, and they diverge exactly where you would expect: on curvature.
| Test file | Shape | Draft tri | Normal tri | Fine tri | Fine ÷ Draft |
|---|---|---|---|---|---|
| simple-cube.stp | Flat cube | 12 | 12 | 12 | 1.0× |
| cube-10x10.stp | Flat cube | 12 | 12 | 12 | 1.0× |
| cube-10x10.igs (IGES) | Flat cube | 12 | 12 | 12 | 1.0× |
| rounded-cube.step | Rounded edges | 40 | 56 | 140 | 3.5× |
| conical-surface.step | Curved surface | 286 | 516 | 2,142 | 7.5× |
| as1_pe_203.stp (18 parts) | Assembly | 3,848 | 6,088 | 17,848 | 4.6× |
| as1-oc-214.stp (18 parts) | Assembly | 4,900 | 7,372 | 21,116 | 4.3× |
Two things to take from it. A flat part cannot identify the setting — all three cubes read 12 across every quality, because a flat face needs exactly two triangles no matter how precisely you ask. And the settings separate fastest on the hardest geometry: Draft to Fine multiplies the cone by 7.5 and the rounded cube by 3.5, while leaving the flat cubes untouched. If you want to know which setting actually ran, convert something curved.
Why there is no way back
Reading the question “can I convert STL to STEP?” as a request for a missing feature would be a mistake, so here is the actual reason it is not a feature.
STEP to STL is sampling: the exact surfaces already exist and you are deciding how finely to walk them. STL to STEP is reconstruction: you have a list of flat triangles and you would have to work out which surfaces a human author originally intended. Many different surfaces fit the same triangles. A tessellator that chose 12 panels around a curve and one that chose 2,142 produce triangles that differ slightly, and both are perfectly good tessellations of the same cone. Nothing in the STL file records which one happened, so there is no correct answer to recover.
What that means in practice is a housekeeping point rather than a limitation to work around: keep the STEP file. The STL is disposable, because you can regenerate it from the STEP in seconds with the converter on the front page. The reverse is not true of the STEP file, and it never was.
- This converter reads STEP and IGES and writes STL. Extensions
.step,.stp,.igesand.igsgo in; STL comes out. An STL cannot be dropped back in, and we would rather say so than pretend. - The loss is real and worth naming. Exact radii, the feature tree your CAD tool attached, part names, colours and materials all stop existing at the boundary. Faces and edges survive only as triangle boundaries.
- The reverse conversion is a different kind of tool. One exists, and it is a legitimate thing to want — it reconstructs a surface by fitting, and the fit is an interpretation rather than a recovery. That is a decision to make deliberately with a tool built for it, not a checkbox here.
The unit surprise, which is really the format talking
An STL record is 50 bytes of coordinates and a normal. There is nowhere in that record to say whether a coordinate of 10 means 10 mm or 10 inches. That is not an oversight in your file; it is the format. Which is why unit errors are recognisable when they happen: they arrive as a clean factor of 25.4, the number of millimetres in an inch, rather than as a vague drift.
| Unit here | Everything is measured in millimetres, the engine default. The unit declared inside your STEP file is applied before you see a number. |
|---|---|
| Proof pair | Two geometrically identical cubes: one declares UNIT('INCH') and writes its coordinates as multiples of 39.370078740157 (= 1000 ÷ 25.4), the other declares millimetres and writes 1000. Both measure 1000 × 1000 × 1000 mm after the declared unit is applied. |
| Orientation | Nothing is rotated, aligned, centred or re-scaled. Coordinates land in the STL in the system the model already used, so laying the part flat for printing is your slicer’s job. |
| Large assemblies | The 18-part AP203 model measures 5080 × 2209.8 × 3810 mm and the AP214 model 200 × 150 × 84 mm. Both declare millimetres and neither is rescaled on the way out. |
One more difference worth knowing: the mesh can be open
A STEP file can describe a solid that is not actually closed, and this converter triangulates rather than repairs. So a gap in the source leaves as the same gap in the STL, and a file that looks fine can still be unprintable. There is a number that settles it: count the mesh edges. A closed shell has every edge shared by exactly two triangles.
Our IGES test cube is a solid, so it should close, and it does — 18 distinct edges across 12 triangles, every one of them used exactly twice, forming one connected piece. The arithmetic generalises: 12 triangles carry 12 × 3 = 36 edge-uses, and a closed mesh uses each edge twice, so 36 ÷ 2 = 18. Any edge used exactly once is a hole, and it arrived that way in the STEP file rather than being introduced by the conversion. The verification page walks through this check and the other four in detail.
What this converter reads, stated plainly
Many converters that advertise STEP to STL also advertise a much longer list of formats. This one does not. It reads STEP and IGES, meaning .step, .stp, .iges and .igs, and writes STL. It does not read OBJ, PLY, 3MF, GLB, FBX, DWG or OFF, and it cannot be made to without replacing the engine.
- The measurement has a control group. A negative result means nothing unless the same harness can produce a positive one, so the probe always converts a known-good STEP file first:
cube-10x10.stpcomes back as 1 mesh and 12 triangles through the same dispatch, and no unsupported verdict is reported unless that control passed. - The reason is the engine, not the website. The shipped WebAssembly build exports four readers — STEP, IGES, BREP and a generic fallback — and no importer for OBJ, 3MF, GLB, FBX or DWG is linked into it at all. Adding them means recompiling with those importers, which is a different engine rather than a setting.
- The generic fallback is not a format detector. The engine’s own output,
cube-10x10-reference.stl, does not read back in. So the fallback will not rescue an unexpected extension; it is scoped to what it was built for. - This is an inference, not a formal proof. The chain is: the engine exports four readers and no importers for those formats, and probes for each returned nothing usable while the control succeeded. The fixtures are minimum-size structurally valid files constructed in memory, not complete production files. To hold “a full, real DWG is also unsupported” as hard evidence, a real sample would have to be converted too.
The whole difference on one screen
| STEP stores | Exact surfaces — a cylinder as a radius. Readable text, editable in a CAD tool, carries units and a feature tree. |
|---|---|
| STL stores | Triangles. A flat list of three points each, with no units, no colour, no material and no part names. |
| The conversion | One-way and lossy. Surfaces are sampled into triangles, and the exact definition does not survive. |
| Size relationship | No fixed direction. Flat parts shrink (9,404 B → 684 B), curved parts grow (9,640 B → 25,884 B). Size follows triangle count, nothing else. |
| Triangle count | Chosen, not discovered: 12 on a cube at every setting, 286–2,142 on a cone. Output bytes = 84 + 50 × triangles. |
| Going back | Not a conversion but a reconstruction. Keep the STEP file; the STL is disposable and regenerable. |
| Units | Millimetres, with the STEP file’s declared unit applied first. The STL does not record the unit, so a misread shows up as a clean 25.4× error. |
If you arrived with an STL and a question about turning it back into something editable, the honest answer is that the tessellation is the best available record of that shape and the surfaces are gone. Keep the STEP file next time, and this conversion stops being a one-way door.
Where these numbers come from
- Every source byte count, triangle count and output size — produced by running the shipped engine (occt-import-js 0.0.23, a WebAssembly build of OpenCASCADE) in Node.js over the project’s own test files.
npm testre-runs every row of both tables on this page, diffs each figure, and re-checks the 12-triangle cube end-to-end in a headless browser. The output ÷ source column and the Fine ÷ Draft column are recomputed from the raw numbers rather than trusted. - 84 + 50 × triangles — the published binary STL record layout, cross-checked against the reference STL shipped with the engine vendor’s own test set.
- 25.4, and the inch/mm proof pair — 25.4 is the exact number of millimetres in an inch. The pair is two geometrically identical cubes, one declaring
UNIT('INCH')and one declaring millimetres;npm testasserts both bounding boxes and the inch declaration. - The 18-edge closed shell — computed from the merged triangle list the shipped writer produces, by counting each undirected edge and how many triangles use it.
- The unsupported-format list — from
node tests/format-support.js, which probes each format against the same reader dispatch behind a known-good STEP control. Labelled as inference above, with the reasoning chain given.
The converter on the front page reports the bounding box, triangle count and solid-part count for your own file after every run, so you can check any of this against your own part. Its about page states who runs it and what it will not do.