How to Convert glTF to GLB (Single-File 3D Models)
glTF vs. GLB: What Actually Differs Between These Two Formats
Both glTF and GLB are defined by the same Khronos Group specification — they share identical data structures, support the same PBR materials, animations, morph targets, and scene hierarchies. The difference is purely about packaging. A standard glTF asset is a multi-file bundle. You get a human-readable .gltf JSON file that describes the scene graph, materials, and mesh topology, plus one or more .bin files holding binary geometry data (vertex positions, normals, UV coordinates, indices), and a folder of texture images — typically PNG or JPEG files. A moderately complex character model might ship as character.gltf, character0.bin, and a textures/ folder containing eight or ten images. All of those files must travel together; remove one .bin or one texture and the model breaks. GLB is the binary container version of the same specification. It packs the JSON chunk, the binary buffer chunk, and all embedded textures into a single .glb file with a small 12-byte header. That header stores a magic number (0x46546C67, which is 'glTF' in ASCII), a version field (currently 2), and the total file length. Everything after that is a sequence of typed chunks. The practical consequence: a GLB file is self-contained. You can email it, drop it into a product configurator, load it in a WebXR scene, or hand it to a client without worrying about broken relative paths or missing texture references. File size is usually within 1–3% of the original multi-file bundle, so there is no meaningful storage penalty for the convenience.
When You Should Convert glTF to GLB (and When You Shouldn't)
Converting to GLB makes sense in most production scenarios, but there are genuine cases where keeping the separate glTF format is the better call. Convert to GLB when: you are deploying a model to a web viewer such as model-viewer, Babylon.js, or Three.js and you want a single fetch request rather than a waterfall of network calls for each .bin and texture. A single 4 MB GLB loads noticeably faster on mobile connections than the same asset split across a 120 KB .gltf, a 2.1 MB .bin, and six textures totalling 1.8 MB, because each separate file requires its own HTTP round-trip. Also convert when distributing to clients or marketplaces — Unity's Asset Store, Sketchfab, and the Apple AR Quick Look pipeline all accept GLB directly. Stick with multi-file glTF when: artists on your team need to swap textures quickly without re-packing the whole asset. If a texture artist is iterating on a 2K roughness map, being able to drop a new PNG into the textures folder and refresh the viewer is much faster than re-running a conversion pipeline. Similarly, if your build system applies automated texture compression (generating KTX2 or Basis Universal variants), it is easier to target individual loose files than to unpack and repack a GLB on every build. Also worth noting: GLB cannot reference external textures by design. If your glTF intentionally links to textures hosted on a CDN — a pattern sometimes used to share texture atlases across multiple models — converting to GLB will embed local copies of those textures, breaking the shared-resource pattern.
How to Convert glTF to GLB Using CocoConvert
CocoConvert's browser-based converter handles the glTF-to-GLB conversion without requiring any software installation. The process works entirely client-side for files under 100 MB, meaning your geometry and texture data never leaves your machine. Step 1 — Prepare your files. Because a glTF asset is a multi-file bundle, you need to upload everything together. Zip your .gltf file, all associated .bin files, and your entire textures folder into a single archive before uploading. Keep the internal folder structure intact — the .gltf file uses relative paths like ./textures/baseColor.png, and the converter resolves those paths from the zip root. Step 2 — Open the converter. Go to /convert/gltf-to-glb and click the upload area or drag your .zip onto it. The converter will detect the glTF entry point automatically. If your zip contains multiple .gltf files (for example, LOD variants), a dropdown will appear letting you choose which one to use as the root. Step 3 — Review conversion options. CocoConvert gives you two settings worth paying attention to. 'Embed textures' is on by default and is what produces a true single-file GLB. If you turn it off, the output GLB will reference external texture URIs, which defeats most of the purpose of converting. The second option is 'Flatten buffer' — this merges multiple .bin files into one binary chunk, which is standard GLB behavior and should stay enabled. Step 4 — Download. Conversion typically completes in 5–20 seconds depending on texture count and total file size. The download is a single .glb file ready for deployment.
Command-Line Alternative: Using gltf-pipeline for Automated Workflows
If you are converting dozens of models as part of a build pipeline, running conversions one by one through any web UI is impractical. The gltf-pipeline Node.js tool from the Cesium team is the most reliable open-source option for scripted glTF-to-GLB conversion. Install it globally with npm: `npm install -g gltf-pipeline`. Then convert a single asset with: `gltf-pipeline -i scene.gltf -o scene.glb`. The -i flag specifies the input .gltf file; gltf-pipeline automatically resolves relative paths for .bin files and textures in the same directory, so you do not need to zip anything. The -b flag (short for --binary) is implied when the output filename ends in .glb. For batch processing a directory, a simple shell loop works well: `for f in models/*.gltf; do gltf-pipeline -i "$f" -o "${f%.gltf}.glb"; done`. On Windows PowerShell the equivalent is `Get-ChildItem -Filter *.gltf | ForEach-Object { gltf-pipeline -i $_.FullName -o ($_.FullName -replace '.gltf','.glb') }`. gltf-pipeline also supports Draco mesh compression via the --draco.compressionLevel flag (values 0–10, default 7), which can reduce geometry size by 60–80% at the cost of slightly longer decode time in the browser. This is worth enabling for models with dense meshes — a 500,000-polygon scan that is 18 MB uncompressed can drop to around 4 MB with Draco level 7. One limitation to be aware of: gltf-pipeline does not perform texture compression (KTX2/Basis). For that you need a separate step using toktx or basisu before or after the GLB packaging.
Validating Your GLB Output Before Deployment
A GLB file that opens in one viewer can silently fail in another if it contains non-conformant data. Validation should be a standard step before you ship any converted asset. The Khronos glTF Validator is the authoritative tool. You can run it online at validator.khronos.org — drag your .glb onto the page and it returns a structured JSON report listing errors, warnings, infos, and hints. Errors are blockers: things like accessor componentType mismatches or buffer views that exceed the declared buffer length will cause loaders to reject the file outright. Warnings are worth reading but not always critical — a common one is 'MESH_PRIMITIVE_UNUSED_TEXCOORD' which just means you have a UV set that no material references. For local validation in a pipeline, install the validator as a Node package: `npm install -g gltf-validator`. Then run: `gltf-validator scene.glb --stdout > report.json`. Pipe that report into a CI check and fail the build if the error count is greater than zero. Beyond spec compliance, do a visual check in at least two different renderers. model-viewer (modelviewer.dev) and the Babylon.js Sandbox (sandbox.babylonjs.com) use different WebGL implementations and expose different material interpretation edge cases. A normal map that looks correct in one may appear inverted in the other if the Y-channel convention is wrong — glTF specifies OpenGL-style normals (Y-up), while some DCC tools export DirectX-style (Y-down) by default. If you see a lighting artifact that looks like inverted bumps, flip the green channel of your normal map texture and reconvert.
Common Conversion Errors and How to Fix Them
A few problems come up repeatedly when converting glTF to GLB, and most have straightforward fixes. Missing textures in output: This almost always means the .gltf file's texture URI paths did not resolve during conversion. Open the .gltf in a text editor and check the images array — you will see entries like `"uri": "textures/Material_baseColor.png"`. Make sure those files exist at exactly those relative paths in your zip or working directory. Path separators matter on case-sensitive file systems (Linux servers): `Textures/BaseColor.png` and `textures/baseColor.png` are different paths. Oversized output file: If your GLB is unexpectedly large, the most common culprit is uncompressed 4K textures. A single 4096×4096 RGBA PNG can be 64 MB uncompressed in memory, and while PNG itself is lossless-compressed, the embedded binary data in a GLB stores the raw PNG file bytes — so a 12 MB PNG texture stays 12 MB inside the GLB. Consider downsampling textures to 2048×2048 for web use (rarely visible difference on screen) or applying KTX2 compression before packing. Animations not playing: If a model has skeletal animations in the source glTF but they do not play in the GLB output, check that the skin and animation accessors are within the same buffer. Some DCC exporters write animation data to a separate .bin file; if that file was missing from the conversion input, the animation data is simply absent from the GLB. Re-export from your DCC tool making sure all binary data is written to a single .bin, then reconvert. CocoConvert will report a warning in the conversion log if it detects referenced files that could not be found in the uploaded archive. Always read the log before downloading.
File Size, Performance, and What to Expect in Real Projects
Concrete expectations help more than vague promises. Here is what the conversion process actually produces across a range of typical assets. A simple furniture model — one mesh, two materials, four 1K textures — typically converts from a ~3.2 MB multi-file glTF bundle to a ~3.1 MB GLB. The slight size reduction comes from eliminating JSON whitespace and merging buffer headers. Load time difference in a browser: negligible on desktop, but on a 4G mobile connection the single-file GLB will start rendering roughly 300–500 ms earlier because it avoids the parallel-request overhead. A character with skeletal animation, 12 materials, and 2K textures might be a 28 MB glTF bundle. As a GLB without any additional compression: 27.4 MB. With Draco compression on geometry (but not textures): around 22 MB. With KTX2 Basis Universal texture compression applied first: potentially 9–11 MB. CocoConvert handles the glTF-to-GLB packaging step cleanly, but it does not currently apply Draco or KTX2 compression — for those you need gltf-pipeline and toktx respectively as separate pipeline stages. For AR use cases specifically, Apple's AR Quick Look and Google's Scene Viewer both have documented file size limits. Apple recommends keeping GLB files under 20 MB for reliable over-the-air AR loading; Google's Scene Viewer has a hard limit of 200 MB but recommends under 15 MB for good mobile performance. If your converted GLB exceeds these thresholds, texture compression is almost always the highest-leverage optimization before geometry simplification. The conversion itself at /convert/gltf-to-glb is lossless with respect to the 3D data — geometry, materials, animations, and scene hierarchy are preserved exactly. What you put in is what you get out, just repackaged.