local engine

GLB → STL

Free GLB to STL Converter

Yes. Drop a GLB file, choose STL and download. glTF counts in metres and STL declares no unit at all, so check the scale on import when the part has to print true to size.

A GLB file is the binary container of glTF 2.0: one header, a JSON chunk describing scenes, nodes and accessors, and a BIN chunk holding the actual vertex and index bytes. Converting to STL strips that structure down to a flat list of triangle facets. Every mesh and primitive in the scene is merged into one geometry, node transforms are baked into vertex coordinates, and the exporter writes a binary STL with twelve floats per facet and no unit, colour or hierarchy information.

Drop a GLB file, get STL Reads GLB, writes STL here .glb → .stl Pick a GLB file, export STL
  • Full-size 3D preview before you download
  • 28 input formats and 8 output formats, four detail levels for CAD sources
  • Reads the file in your tab — nothing is uploaded
224conversions here
28mainstream formats
0 Buploaded anywhere

How to convert GLB to STL

  1. Load the GLB containerSelect a .glb file. The parser validates the magic 0x46546C67 and version 2 header, then reads the JSON and BIN chunks, trimming four-byte padding before interpreting accessors and bufferViews.
  2. Decode meshes and primitivesEach mesh primitive contributes POSITION, NORMAL and index data. Primitives with non-triangle modes are expanded into plain triangle lists; Draco- or meshopt-compressed primitives need the workspace, which loads the decoders.
  3. Bake node transformsThe scene node tree is walked once. Parent matrices multiply down to each mesh, so vertex positions land in world space and the hierarchy itself disappears from the output.
  4. Merge into one flat meshAll primitives are concatenated into a single geometry holding only position and normal attributes, with node transforms already baked into the coordinates. The merge appends vertices and offsets the indices; it does not compare them, so a corner shared between two primitives is written twice and seams stay exactly as the author left them.
  5. Write binary STLThe exporter emits an 80-byte header, a uint32 facet count and 50 bytes per facet. The result is a single .stl blob that any slicer opens.

What happens when GLB is converted to STL

What a GLB file actually contains

GLB is the binary form of glTF 2.0. After a twelve-byte header it carries a JSON chunk that declares scenes, nodes, meshes, accessors and bufferViews, and a BIN chunk that holds the raw typed arrays those accessors point into. Textures may be embedded as images in the BIN chunk, and the JSON may reference extensions such as Draco compression or KTX2 textures.

What survives the conversion

Only triangles survive. Vertex positions are kept, normals are kept or recomputed when missing, and node transforms are baked into the coordinates. Everything else the container can express has no destination in STL: PBR materials, base colour factors, texture images, texture coordinates, skins, animation channels, morph targets, cameras and lights are all dropped.

Why indexed meshes grow instead of shrinking

glTF primitives are usually indexed: a position array plus a buffer of indices, so a corner shared by four faces is stored once. Binary STL has no equivalent mechanism. Each of its 50-byte records carries three complete vertices, and there is no index table in the format for a reader to consult. Conversion therefore expands the index buffer into explicit per-facet vertices, which multiplies the stored position data by roughly the corner-reuse factor. No pass deduplicates the result and no welding hash runs anywhere in the exporter, so the facet count of the output equals the triangle count of the source scene. That is the number to watch: a modest-looking GLB of highly shared geometry can still produce an STL several times heavier in bytes than the mesh data inside the original file.

Why the result has no scale anyone can agree on

glTF documents are written in metres by convention, but STL stores plain numbers with no unit at all. The converter does not rescale coordinates, so the numeric values pass through untouched. A slicer will treat the STL in whatever unit it is configured for, so check the bounding box before printing.

The smooth normals in your GLB are recomputed, not copied

glTF stores a normal per vertex, which is why a low-poly sphere can shade as if it were round. STL stores a normal per facet, and the exporter does not read the attribute at all: for every triangle it takes the three corner positions, subtracts to get two edge vectors, crosses them and writes the unit result into the record. So the shading information is discarded twice over, once because the format cannot hold a different normal per corner, and once because the code never looks at the source normals. The geometry is untouched, but a viewer that trusts the stored normals shows the mesh as faceted, and a slicer that uses them to decide inside from outside sees a hard direction change at every seam that used to be smooth. This is why a converted GLB often looks rougher than it did in the browser.

The up axis is carried across unchanged

glTF is defined as right-handed with +Y up, and the loader keeps the scene exactly that way. STL has no field for an up axis at all; the three floats in a facet record are simply x, y, z, and the convention among slicers and CAD tools is that +Z is up. Nothing in this pipeline rotates the model to compensate. A GLB authored for a game engine therefore arrives lying on its back, and the fix belongs in the slicer: rotate ninety degrees about X, or use the import transform, before scaling to fit the plate. The same absence of metadata is what makes the next problem harder to see, because an import dialog that shows a plausible orientation says nothing about whether the numbers are metres or millimetres.

Animations, skins and morph targets have nowhere to go

A GLB is often more than a mesh: the JSON chunk may declare animation channels that sample node transforms over time, a joint hierarchy driven by a skin, and morph targets with weights. A facet record has three vertices, a normal and two unused bytes, so there is no slot for a time, a joint index or a weight. The loader hands the scene to the converter and the animation list is dropped with it; the triangles that survive come from the base geometry, which for a rigged character is the bind pose. The output is therefore one static mesh in whatever pose the file stores by default. If the export needs a specific frame, pose it and bake it in the modelling tool first, then convert the baked result.

GLB vs STL

GLB sourceSTL output
FeatureGLB sourceSTL output
ContainerBinary glTF 2.0: JSON chunk plus BIN chunk80-byte header plus flat facet records
Scene structurescenes, nodes, meshes, primitivesOne merged triangle soup
TransformsNode matrices and TRS valuesBaked into vertex coordinates
MaterialspbrMetallicRoughness and texturesNone
Texture coordinatesTEXCOORD_0 accessorsNot representable
AnimationSkins and animation channelsNot representable
CompressionOptional Draco or meshopt extensionsUncompressed binary
UnitsMetres by convention, undeclaredNo unit
Output filesOne self-contained binaryOne .stl file

Supported formats

FormatReadWriteNotes
STEP (.step .stp)Yes–ISO 10303 B-rep, AP203 / AP214 / AP242
IGES (.iges .igs)Yes–Entity-based surfaces, up to 5.3
BREP (.brep)Yes–OpenCascade native B-rep
STL (.stl)YesYesBinary and ASCII triangles, no units
OBJ (.obj)YesYesv / vn / f records; .mtl references ignored
PLY (.ply)YesYesBinary position and normal arrays
GLB / glTF (.glb .gltf)YesYesglTF 2.0, binary or JSON with data URI
3MF (.3mf)YesYesOPC/ZIP package, declares millimetres
FBX (.fbx)Yes–Binary and ASCII, static mesh only
DAE (.dae)YesYesCollada scene graph is flattened
3DS (.3ds)Yes–Legacy chunk-based 3D Studio format
AMF (.amf)Yes–XML, ZIP-compressed packages supported
USDZ (.usdz)YesYesZIP containing a USD stage

Known limitations and why a conversion can fail

Draco and meshopt compression is decoded on the fly

A GLB whose primitives declare KHR_draco_mesh_compression or EXT_meshopt_compression stores its vertices compressed, so no triangle exists until the matching decoder has run. The workspace wires both decoders and loads them lazily from files served by this site, which means a compressed primitive is decoded first and then flattened like any other, and a Draco cube with a thousand triangles converts and exports normally. Compression changes how the container stores its vertices, not the facet list an STL can hold, so the downloaded file is the same one an uncompressed GLB of the same mesh produces.

Very large scenes expand, and memory is the ceiling

Because expansion is unavoidable, the triangle count drives everything downstream. Positions and normals are held as 32-bit float arrays in the tab, the scene graph keeps a geometry per primitive until the merge finishes, and the serialised STL is then built as one contiguous block, so peak use sits well above the size of the file you eventually download. WebAssembly linear memory cannot grow past roughly four gigabytes in a 32-bit module, and a browser tab rarely gets that much in practice. Very dense scans therefore fail with a memory or script error rather than producing a truncated file. Splitting the scene, or converting a decimated copy, is the practical remedy.

Colour never reaches STL

STL has no material system beyond an optional attribute word that slicers ignore. A coloured or textured GLB converts to a colourless mesh; paint it in your slicer or slicer-side tools instead.

Frequently asked questions

Can I convert on this page itself?

No. This page is the reference for the GLB to STL path, and the conversion itself runs in the workspace that the button above opens, with both formats already selected. Your file is read in that browser tab and the download is written locally, so there is no upload stage in either place. Keeping the documentation and the engine on separate addresses lets file support and detail levels change behind one workspace without breaking the page you are reading.

Will my textures survive?

No. STL stores triangles only. Base colour textures, PBR parameters and texture coordinates have no place in the format, so the converter drops them rather than pretending to keep them.

Why is my model the wrong size in the slicer?

glTF is metres by convention; STL has no unit. The numbers are not rescaled during conversion, so import the STL at the unit your slicer expects and verify the bounding box before printing.

Can I convert a whole animated scene?

The static geometry converts; animation does not. Skins, joints and animation channels are skipped, and each mesh is frozen at its current node transform.

Does the converter merge duplicate vertices?

No, and binary STL is the reason. A glTF primitive can be indexed, storing each shared corner once and referring to it from an index buffer, while a binary STL facet carries its own three complete vertices and the format has no index table at all. So the exporter walks the indices and writes one 50-byte record per triangle, which inflates the vertex data by roughly the corner-reuse factor instead of compacting it. Nothing is deleted and no coordinate is moved, which is why the triangle count reported after loading predicts the size of the download.

Do Draco or meshopt compressed GLB files convert?

Yes. Both decoders are wired into the workspace and loaded lazily from files served by this site, so a primitive declaring KHR_draco_mesh_compression or EXT_meshopt_compression is decoded before any triangle is written. The flattened facet list that reaches the STL is the same one an uncompressed GLB of the same mesh produces, because a facet record has no field for a quantised position either way.

What happens to a GLB with several meshes and materials?

Every drawable mesh is transformed into world space and appended into one flat triangle list. Materials are the first casualty: glTF associates primitives with metallic-roughness or specular-glossiness descriptions, and a facet record has no field for any of it. Skinned rigs, morph target weights, node names, cameras and lights are dropped with them. If the model needs to keep its appearance, converting to OBJ or GLB preserves geometry with material references, whereas STL cannot represent them even in principle.

Is the exported STL watertight?

Nothing in the pipeline certifies it. A glTF mesh is a rendering asset, and authors routinely build a cube from six independent quads with duplicated corners, or leave hairline gaps between parts that a game engine would never notice. Because the format stores no topology, a slicer has to weld near-identical vertices itself before it can decide whether the shell closes. A model that looks seamless in a viewer can therefore arrive in a slicer as an open or self-intersecting volume, and that is a property of the source mesh rather than of the conversion.

Why does my model look faceted after conversion?

Because smoothing information cannot be stored. glTF gives each vertex its own normal, so a coarse sphere shades as if it were round, while binary STL gives each facet one normal computed from the three corner positions. The exporter performs that cross product itself and never reads the source normals, so every shared smooth direction is replaced by a flat per-triangle one. The vertices stay exactly where they were and the silhouette is unchanged, which is why the mesh still measures the same size; only the shading is harsher. A slicer ignores normals entirely, so this is a viewing artefact rather than a loss of geometry.

References

Related converters

All converters

Last updated: