STEP→STL Your file stays in this tab · nothing is uploaded

How to convert STEP to STL, in order

This is the whole procedure on one screen, in the order the steps actually matter. Every number below was measured on the machine that wrote this page, and npm test re-runs each one. Nothing here is a rule of thumb.

  1. Check the extension. .step, .stp, .iges or .igs. The extension picks the reader, and STEP and IGES take different code paths.
  2. Confirm the unit is what you expect. Numbers come out in millimetres by default, the default path touches no coordinate, and the part is never rotated, aligned, centred or rescaled.
  3. Choose a quality setting. Normal for printing, Draft to check fit on an assembly, Fine for a fillet that still looks faceted. The setting costs nothing on flat parts.
  4. Predict the output before you convert. A flat cube is 12 triangles and 684 bytes at every setting. A cone is 286, 516 or 2,142. File size is 84 + 50 × triangles, so the triangle count tells you the byte size.
  5. Convert in the browser. Parsing and tessellation run on your own machine. Nothing is uploaded, and there is no queue.
  6. Verify the output. Check the file size against the triangle count, and check the mesh is closed. The verification page has all five checks with numbers.

Steps 1–4 are decisions. Steps 5–6 are the conversion itself and the proof it worked. Most bad STEP to STL results are decided in the first four, before a single triangle exists, which is why they are the ones worth being precise about.

1. The extension decides everything downstream

Two format families, four extensions, two readers. A .step or .stp file goes to the STEP reader; .iges or .igs goes to the IGES reader. Nothing else is accepted, and that is a property of the engine rather than a policy setting: the shipped WebAssembly build links readers for STEP, IGES, BREP and a generic fallback, and no importer for anything else.

If your file has any other extension, stop there rather than renaming it. Renaming does not convert anything; it just moves the problem to step 5, where the reader will fail on content that is not the format its name claims. Export from your CAD tool instead.

One difference between the two paths is worth knowing before you trust an IGES result: IGES stores surfaces rather than a solid. Surfaces that do not actually meet in the file stay separate pieces in the output, so a multi-piece result from an IGES source is not automatically a fault.

2. Units: the file’s declared unit in, millimetres out by default

Millimetres are the default output and the default path leaves every coordinate alone, so the number you see is the number the engine measured. Separately, the converter applies the unit declared inside your file before it reports anything — that is not the same as assuming millimetres, and the difference is worth proving rather than asserting.

We built a control pair for it: two geometrically identical 1,000 mm cubes, one declaring UNIT('INCH') with its coordinates written as multiples of 39.370078740157 (which is exactly 1000 ÷ 25.4), and one declaring millimetres directly. Both read back as a 1,000 × 1,000 × 1,000 mm bounding box. The declaration inside the file is what decides, and it is honoured.

What the converter does and does not change
Unit of outputMillimetres by default. The unit declared in the STEP file is applied first.
The inch optionDivides the coordinate values by 25.4 on the way out. It re-expresses numbers; it does not scale the geometry, and it does not add or remove a triangle.
Position and axesThe part is not rotated, aligned, centred or scaled. A 200 × 150 × 84 mm assembly stays 200 × 150 × 84 mm.
If the size is wrongA clean factor of 25.4 means the file was read in the wrong unit, not converted badly.

3. The quality choice, and what it costs before you spend it

Each setting is a pair of numbers: a linear deviation and an angular deviation. Draft is 0.02 and 0.5, Normal is 0.005 and 0.3, Fine is 0.001 and 0.1. These are this site’s own choices, not a CAD standard, and they are compared against the shipped worker’s values by npm test so the two copies cannot drift apart.

The important thing about that pair is that you cannot reason about the result from either number alone — you can only measure it. So here is what each setting actually produced, on real files, with this engine.

What each setting produced on each test file, measured with this engine in Node.js; npm test re-runs every cell and fails on a mismatch. Bytes are binary STL size.
Test fileShapeDraft triNormal triFine triFine ÷ DraftNormal bytesFine bytes
simple-cube.stpFlat cube1212121.0×684 B684 B
cube-10x10.stpFlat cube1212121.0×684 B684 B
cube-10x10.igs (IGES)Flat cube1212121.0×684 B684 B
rounded-cube.stepRounded edges40561403.5×2,884 B7,084 B
conical-surface.stepCurved surface2865162,1427.5×25,884 B107,184 B
as1_pe_203.stp (18 parts)Assembly3,8486,08817,8484.6×304,484 B892,484 B
as1-oc-214.stp (18 parts)Assembly4,9007,37221,1164.3×368,684 B1,055,884 B

Read that table as a cost, not a menu. Going Draft to Fine multiplies the cone by 7.5 and the assemblies by roughly 4.3–4.6, while leaving the flat cubes untouched. If your part is mostly flat, Fine is free; if it is mostly curved, Fine is a real cost and you should look at the preview before accepting it.

Predicting the count before you convert

For a flat part you can predict the answer exactly: a cube is 12 triangles, because six flat faces need exactly two each, and no closed solid can use fewer. 684 bytes, every time, at every setting.

For a curved part you can predict the byte size from any triangle count, because the binary STL layout is fixed at 84 bytes of header plus 50 bytes per triangle. What you cannot do is look at a STEP file and derive its triangle count from its byte size — the two are unrelated, and the table above shows a 9,640-byte cone producing a 107,184-byte STL at Fine. Curvature, not file size, drives the count.

4. Scaling the part up does not give you a finer mesh

This is the most useful thing we measured, and it is not what the setting names suggest. The presets are expressed as a ratio of the part’s own size, which reads like “bigger part, same relative accuracy, more triangles”. We tested that directly instead of assuming it.

We took one curved solid and scaled the entire solid to 100× its size. Measured at Normal, the bounding box went from 27.033 mm to 2,703.298 mm — a clean 100× on all three axes — and the triangle counts did not move at all:

The same curved solid at 1× and at 100× its size, converted with this engine at all three shipped settings.
SettingTriangles at 1×Triangles at 100×Bytes at 1×Bytes at 100×
Draft28628614,384 B14,384 B
Normal51651625,884 B25,884 B
Fine2,1422,142107,184 B107,184 B

Same triangles, same bytes, hundred times the physical size. Enlarging a model is not a way to get a better mesh in this engine. If your mesh looks faceted, the fix is the quality setting, not a bigger model.

The same curved solid converted at its original size and at 100 times that size, at Draft, Normal and Fine Two rows of three bars. The top row is the curved solid at its original size, the bottom row is the same solid scaled to 100 times its size, with a bounding box of 2,703.298 mm instead of 27.033 mm. Every bar in the lower row is exactly the same length as the bar above it in the top row: 20, 36 and 150 pixels, which is 286, 516 and 2,142 triangles. One hundred times the physical size produces an identical mesh. Same curved solid, 1× and 100× its size — the bars are identical Draft Normal Fine At 1× 286 516 2,142 At 100× 286 516 2,142 At Normal: bounding box 7.000 × 27.033 × 26.957 mm at 1×, 700.000 × 2,703.298 × 2,695.739 mm at 100×. Bar length = triangles ÷ 286 × 20 px, one shared scale across both rows. The bounding box grew 100×. Not one triangle was added.
A hundred times the size, an identical mesh. Both rows are drawn to one shared scale, so the bars are not merely close — they are the same length, because the triangle counts are the same: 286 at Draft, 516 at Normal, 2,142 at Fine, with identical byte sizes. The bounding box underneath grew from 27.033 mm to 2,703.298 mm. Scaling a model up buys nothing here.

We are deliberately not going further than that, and here is the honest reason. The presets name their linear deviation as a bounding_box_ratio, which implies a physical tolerance of “ratio × the part’s size”. We could not confirm that arithmetic: passing the same value as absolute instead produces identical triangle counts, so the wrapper does not visibly distinguish the two modes on our test files. The scale invariance above is measured; any formula behind it is not, so we do not print one.

Which of the two numbers actually binds

Because the two numbers interact, one of them can stop mattering entirely. Holding the cone at each angular value and varying only the linear value gives:

Triangle counts for the cone at three angular values and three linear values
Angular valuelinear 0.02linear 0.005linear 0.001
0.1 (Fine)2,1422,1422,142
0.3 (Normal)5045161,318
1.0 (relaxed)1864081,318

Read the top row. At the angular value Fine uses, the linear value makes no difference at all — 0.02, 0.005 and 0.001 all give 2,142 triangles, because the angular constraint is already the tighter one. Drop it to 0.3 and linear starts to matter; relax it to 1.0 and linear takes over completely and the counts fall to 186 and 408.

The practical consequence: you cannot predict the output by arithmetic on the two numbers, which is exactly why step 4 exists. Convert, look at the count, and only then decide whether to pay for a finer setting.

5. The conversion itself

Drop the file on the converter. Parsing and tessellation run in your tab as occt-import-js 0.0.23, a WebAssembly build of the OpenCASCADE kernel. The file is read on your machine and is never uploaded; there is no server-side step and no queue. That also means the result comes from your own hardware rather than from a remote service, which is a fair trade for a file that never leaves the tab.

The two ends of this step are fixed, whatever you choose in between: what goes in is one of the four extensions from step 1, and what comes out is one .stl file — binary by default, ASCII if you switch it. A .stl file is an output here, never an input. The format page explains why that direction cannot be reversed, so this page does not restate it.

The page reports three numbers after every run, and they are the ones to look at before you download: the bounding box in millimetres (compare it to the size you know), the triangle count, and the solid-part count. For an assembly the part count is the useful one — our two 18-part test files both report 18, and every part lands in the single STL you download.

If your file is refused, it is not a quality problem. No setting will make an unreadable file readable, and no setting will repair a broken model: this triangulates, it does not fix geometry that arrived with holes or self-intersections.

6. Verify, because finished is not the same as correct

The single cheapest check costs nothing: a binary STL is 84 + 50 × triangles bytes, so subtract 84 from the file size and divide what is left by 50. If that recovers the triangle count the converter reported, the download is intact. There is no rounding in that identity, so any mismatch is a real fault rather than a rounding artefact.

Then check the mesh is closed by counting edges: every edge shared by exactly two triangles means a watertight solid, and an edge used once is a hole. A cube gives 12 triangles across 18 distinct edges, and that arithmetic generalises to any closed solid: 12 × 3 = 36 edge-uses, divided by two, is 18.

Both checks, plus the unit check, the curvature check and the reader check, are laid out with their numbers on the STEP to STL verification page.

The whole thing on one screen

The six steps and the number each one produces
1. Extension.step, .stp, .iges, .igs. Decides the reader. Nothing else is read.
2. UnitsMillimetres out by default, axes unchanged. A 25.4× error means a unit mismatch, not a bad conversion.
3. QualityDraft 0.02/0.5, Normal 0.005/0.3, Fine 0.001/0.1. Costs nothing on flat parts, 7.5× on a cone.
4. Expected outputFlat cube 12 tri / 684 B at every setting. Cone 286–2,142 tri. Bytes = 84 + 50 × triangles.
5. ConvertRuns in your tab. Reports bounding box, triangle count and part count. Nothing uploaded.
6. Verify(size − 84) ÷ 50 recovers the triangle count. Every edge used twice means closed.

Scaling the model up does not belong in that list, because it changes nothing: 100× the size returned identical counts and identical bytes at all three settings.

Where these numbers come from

The verification page covers step 6 in full, and STEP vs STL covers what the two formats actually store. This page is the order of operations and the numbers each step produces.