How to verify a STEP to STL conversion
Every number below was measured on the machine that wrote this page, and all of them are re-checked by npm test. Nothing here is an estimate or a rule of thumb.
Five checks, in the order they are worth doing. A conversion can look finished and still be wrong, because “it produced an STL” is not the same claim as “the STL matches the model”. The checks below separate those two claims. Each one uses a number you can compute yourself from the file you already have — no reference model, no CAD licence, no second tool.
- Recover the triangle count from the file size. A binary STL stores each triangle in a fixed 50 bytes behind an 84-byte header. Divide the byte count by 50, subtract 84, and you have the triangle count the converter must have produced.
- Count the edges to prove the mesh is closed. A watertight mesh has every edge shared by exactly two triangles. One edge used once is a hole.
- Compare the bounding box against the size you know. A wrong number here is almost always a unit mismatch, and it announces itself as a factor of 25.4.
- Sanity-check the triangle count against curvature. Flat faces always cost 12 triangles on a cube. If a curved part produced very few, the preset that ran was coarser than you expected.
- Confirm the reader that ran matched your format. A STEP file and an IGES file take different code paths and can land on different results for the same solid.
1. The file size tells you the triangle count
This is the most useful check and the cheapest, because it needs nothing but the file size and a calculator. The binary STL layout is fixed: an 80-byte header, a 4-byte triangle count, then 50 bytes per triangle, so the whole file size is determined by the triangle count alone.
| Identity | bytes = 84 + 50 × triangles |
|---|---|
| Inverted | triangles = (bytes − 84) ÷ 50 |
| Worked example | A 10 mm cube converts to 12 triangles: 84 + 50 × 12 = 684 bytes. Our IGES cube of 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 alongside the cube-10x10.stp it converts from. Our run of that STEP file produces 12 triangles, and the vendor’s own reference file is 684 bytes on disk. Two independent artefacts, one identity. |
The practical consequence is worth stating plainly: a larger STL is not a better conversion. File size carries no quality information beyond triangle count. If you get two files of the same part and one is bigger, it has more triangles, which usually means a finer preset ran — not that the conversion was more correct. And because the identity is exact, it doubles as an integrity check. If your file is 684 bytes but the converter reported 6,088 triangles, the download was truncated. There is no rounding in this formula, so any mismatch is a real fault.
The measurement only works on binary STL, which is why that is the default here. An ASCII STL is a text file with no fixed record size, so the identity does not apply to it — see check 3’s neighbour below for what ASCII costs.
2. Count the edges to prove the mesh is closed
A solid model that a slicer can work with has no boundary: every triangle edge is shared with exactly one other triangle. That gives you a number you can check without rendering anything. Our IGES test cube — a solid, so it should close — measures 18 edges across its 12 triangles, every one of them used exactly twice, forming one connected piece. The arithmetic is worth doing once, because it tells you what to expect from any closed solid: 12 triangles carry 12 × 3 = 36 edge-uses, and since a closed mesh uses each edge exactly twice, that is 36 ÷ 2 = 18 distinct edges. Twelve triangles is the floor here — a cube has 6 faces of 2 triangles each, and no closed solid can be built from fewer.
What the check catches: a count where some edges are used once means the shell is open, and an open shell is not printable because the slicer cannot tell inside from outside. That failure is almost never introduced by the conversion. It arrives in the source file as a gap or a self-intersection and leaves as the same gap, because this page triangulates and does not repair. The count is how you tell which it was.
3. Compare the bounding box against the size you know
Converters report the bounding box — the smallest box containing the part — and that number is worth checking against reality, because a scale error that is almost right is hard to notice and a unit error is easy to recognise. The tell is that unit errors are not approximate. They are a clean factor of 25.4, because that is the number of millimetres in an inch.
If your slicer shows the part at 1/25.4 or 25.4 times the reported box, the file was interpreted in the wrong unit. The conversion is fine; the reading of it is not. Any other ratio — a part that is simply the wrong size — is a modelling question, not a conversion question.
| Units 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 identical cubes, one declaring UNIT('INCH') with coordinates written as multiples of 39.370078740157 (= 1000 ÷ 25.4), one declaring millimetres with coordinates of 1000. Both measure 1000 × 1000 × 1000 mm after the declared unit is applied. Same solid, same result, opposite declarations. |
| Larger assemblies | The 18-part AP203 model measures 5080 × 2209.8 × 3810 mm; the AP214 model measures 200 × 150 × 84 mm. Both files declare millimetres and neither is re-scaled on the way out. |
| Orientation | Nothing is rotated, aligned, centred or scaled. Coordinates land in the STL in the system the model already used. Flat-bottom orientation is your slicer’s job. |
4. Read the triangle count against curvature
Triangle count is driven by how much curved surface the part has, and by how finely you asked for it to be sampled. Flat faces cost nothing extra, which is why the presets are invisible on a cube and obvious on a cone. These are measured counts, one part per row, all three presets:
| 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 that table. A flat part cannot identify the preset — every cube reads 12 across all three, so if you were expecting the quality control to change a cube, nothing broke. And the presets diverge fastest on the hardest geometry: going from 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 preset actually ran, convert a curved part.
This is also where the quality choice stops being a preference. Normal is right for printing. Draft is for checking fit and orientation on an assembly you only need to eyeball. Fine is for a fillet or a cylindrical face that looks faceted in the preview. The preset values themselves are this site’s own choices, not a CAD standard: Draft 0.02 bounding-box ratio and 0.5 angular, Normal 0.005 and 0.3, Fine 0.001 and 0.1, with npm test diffing them against the shipped worker’s values.
5. Confirm which reader ran, and what it will not read
STEP and IGES are different formats with different internal structures, and this page dispatches to a different reader for each. The dispatch is by extension: .step and .stp go to the STEP reader, .iges and .igs to the IGES reader. For our test cube the two paths agree exactly — 12 triangles, 18 edges each shared twice, one piece, 684 bytes — which is a useful baseline, but it is a property of this particular solid rather than a general guarantee.
There is a difference worth knowing about that is specific to IGES: it stores surfaces rather than a solid. This page writes every mesh it receives into one STL without stitching surfaces together, so surfaces that do not actually meet in the file stay separate pieces in the output. A multi-piece result from an IGES source is not necessarily a fault in the source — inspect it.
The formats this converter does not accept are worth stating plainly, because many converters that advertise STEP-to-STL also advertise a much longer list. It reads STEP and IGES only. 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. It refuses to report any unsupported verdict unless that control passed. - The reason is the engine, not the website. The shipped build exports four readers — STEP, IGES, BREP and a generic fallback — and no OBJ, 3MF, GLB, FBX or DWG importer is linked into the WebAssembly binary 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. A control worth knowing: the engine’s own output, the
cube-10x10-reference.stl, does not read back in. So the fallback reader will not rescue an unexpected extension; it is scoped to what it was built for. - This is an inference, not a formal proof. The reasoning chain: the engine exports four readers and no importers for those formats, and probes for each of them 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 as well.
The one format choice that changes the numbers: ASCII
If you need a text STL, know what it costs before you pick it. Same geometry, same triangles, more bytes — across all 27 sample-and-quality combinations we measured, ASCII runs 3.3 to 4.0 times the binary size (exact spread 3.276–4.030). The 18-part assembly at Normal is 304,484 bytes binary against 1,226,556 ASCII for the same 6,088 triangles. The flat cube is the cheapest case at 3.28× and the assembly the dearest at 4.03×, because ASCII pays a fixed per-triangle text cost that a large triangle count amplifies.
Choose it when a tool explicitly asks for a text STL you can open in an editor. Otherwise binary — it is what slicers expect, and it is the format the size identity in check 1 applies to.
The whole thing on one screen
| Byte size | 84 + 50 × triangles. Recovers the triangle count, and a mismatch against the reported count means a truncated download. |
|---|---|
| Edge count | Every edge used exactly twice means a closed shell. Used once means a hole, and it came from the source file. |
| Bounding box | Off by exactly 25.4× means a unit mismatch, not a bad conversion. Everything here is millimetres. |
| Triangle count | Driven by curvature and preset, never by file size. Flat cubes read 12 at every setting. |
| Reader path | STEP and IGES take different readers and can differ. Only STEP and IGES are read at all. |
If a conversion passes all five, the mesh matches the model it came from as closely as a triangle format allows. It does not mean the model itself was sound — a bad part converts to a faithfully bad STL. Fix that in the CAD tool that made it.
Where these numbers come from
- Every triangle count, byte size, edge count and bounding box — produced by running the shipped engine version (occt-import-js 0.0.23, a WebAssembly build of OpenCASCADE) in Node.js over the project’s own test files on this machine.
npm testre-runs all of them, diffs each figure, and re-checks the 12-triangle cube end-to-end in a headless browser. - 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 3.3–4.0× ASCII range and the 27-combination count — measured by writing both formats through the same shipped STL writers the page uses, once per sample per preset.
- The unsupported-format list — from
node tests/format-support.js, which probes each format against the same reader dispatch with 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 apply checks 1, 3 and 4 without leaving the tab. Its about page states who runs it and what it will not do.