Guide

How to Reduce GLB File Size: 8 Techniques That Actually Work

· 11 min read

How to reduce GLB file size

To reduce GLB file size, start with the textures: resize 4K maps to 2K or 1K and convert them to WebP or AVIF. Then compress the geometry with Draco or Meshopt and strip out unused and duplicate data. On a typical textured model those steps together make the file 60–90% smaller with little visible difference.

Which step matters most depends on what is taking up the space, so measure first. Below: how to find the problem, eight techniques with their savings and trade-offs, and the tools that apply them.

Step 1: find out what's making your GLB big

A GLB file holds three kinds of data: textures (images), geometry (vertex positions, normals, UVs and triangle indices) and animation. Each needs a different fix.

  • In the browser: drop the file into our free glTF validator. It runs the official Khronos glTF-Validator and reports vertex and triangle counts, draw calls, the extensions in use, and any errors.
  • On the command line: the open-source gltf-transform CLI prints a table of every mesh, material, texture and animation in the file.
npx @gltf-transform/cli inspect model.glb

The textures table lists each image's format, resolution, file size and estimated GPU memory; the meshes table lists vertex counts and attributes. Add up the texture sizes and compare them to the file size. The Khronos DamagedHelmet sample, for example, is a 3.8 MB GLB with five 2048×2048 JPEG textures totalling about 3.2 MB (roughly 85% of the file) and only about 14,500 vertices. That's a texture problem; compressing the geometry alone would barely help.

Rules of thumb:

  • Textures dominate in product models, characters and most PBR assets. Start with techniques 1 and 2.
  • Geometry dominates in CAD exports, 3D scans, photogrammetry and sculpts. Start with techniques 3 and 6.
  • Animation dominates in rigged characters with long, baked clips. See technique 8.

1. Resize textures

Oversized textures are the most common reason a GLB is too big, and a phone or laptop screen rarely shows the detail in a 4096×4096 map. Going from 4K to 2K leaves 25% of the pixels; 4K to 1K leaves about 6%. It also saves memory: once decoded, a 2048×2048 texture takes about 22 MB of GPU memory with mipmaps and a 4096×4096 texture about 89 MB, whether it was stored as PNG, JPEG or WebP.

  • Typical impact: often the biggest single win on texture-heavy models. Resizing DamagedHelmet's textures from 2K to 1K took the file from 3.8 MB to 1.25 MB (67% smaller) on its own.
  • Trade-off: fine detail is lost up close. Keep textures larger on hero objects people zoom into; small parts and background props can go to 1K or 512.
  • How: set a maximum texture size in our GLB compressor, or use gltf-transform resize. That command only resizes PNG and JPEG, so run it before converting to WebP.
npx @gltf-transform/cli resize model.glb resized.glb --width 1024 --height 1024

2. Convert textures to WebP or AVIF

Many exporters write PNG textures, which are lossless and large. WebP and AVIF are much smaller at similar visual quality, and glTF supports them through the EXT_texture_webp and EXT_texture_avif extensions.

  • Typical impact: large, and larger still when the sources are PNG. Even DamagedHelmet, whose textures were already JPEG, went from 3.8 MB to 1.8 MB (52% smaller) with WebP at full 2K resolution.
  • Trade-offs: the viewer must support the extension. three.js's GLTFLoader reads both; check older engines and native viewers. AVIF usually compresses further but is slower to encode and decode, so WebP is the safer default. If a normal map shows blocky shading, raise its quality.
  • How: choose WebP or AVIF and a quality setting in our compressor, or run gltf-transform webp / gltf-transform avif.
npx @gltf-transform/cli webp model.glb webp.glb --quality 80

3. Compress geometry with Draco or Meshopt

Draco (KHR_draco_mesh_compression) encodes vertex and index data far more compactly than raw floats. It only touches geometry; textures and animation are left as they are.

  • Typical impact: large on geometry-heavy files, small on texture-heavy ones. The Khronos DragonAttenuation sample (6.4 MB, about 135,000 triangles, mostly geometry) dropped to 1.17 MB with Draco alone, 82% smaller. DamagedHelmet only went from 3.8 MB to 3.3 MB (13%), because its weight is in the textures.
  • Trade-offs: the viewer needs a Draco decoder. Google's WebAssembly decoder is about 290 KB plus a 60 KB JavaScript wrapper (around 100 KB gzipped), downloaded once and cached, and decoding takes CPU time on load. Quantization is lossy, but the default 14 bits for positions is invisible on most models; precise CAD parts may need more (see our Draco settings guide).
  • How: enable Draco in our compressor and set the compression level and quantization bits, run gltf-transform draco, or tick Draco in Blender's glTF exporter.
npx @gltf-transform/cli draco model.glb draco.glb

Meshopt (EXT_meshopt_compression) is the main alternative. Its decoder is tiny (about 25 KB) and very fast, it also compresses animation and morph targets, and its output is meant to be gzipped or Brotli-compressed again by your server. Files are usually somewhat larger: the dragon came out at 1.89 MB with Meshopt (1.59 MB gzipped) against 1.17 MB with Draco. Pick Draco when download size matters most, Meshopt for animated models or fast decoding on low-end devices. See Draco vs Meshopt for the details. Our compressor uses Draco only; for Meshopt use gltf-transform meshopt or gltfpack.

4. Remove unused and duplicate data

Exporters and repeated editing leave dead weight: materials and textures nothing uses, unread vertex attributes, empty nodes, and duplicate copies of the same texture, material or mesh.

  • Typical impact: nothing on a clean export, a lot on a messy one (for example, the same texture embedded once per material).
  • Trade-offs: effectively lossless. Pruning can remove empty nodes your code uses as anchors; gltf-transform prune has a --keep-leaves option for that.
  • How: gltf-transform prune removes anything not referenced by a scene, and gltf-transform dedup merges duplicate accessors, textures, materials, meshes and skins.

5. Weld, merge and instance

  • Weld merges identical vertices so triangles share them through the index buffer. The file gets smaller, the GPU's vertex cache works better, and simplification (technique 6) needs it.
  • Merge meshes and flatten nodes combine parts that share a material and remove empty parents. This mainly speeds up rendering by cutting draw calls; the file size change is usually small.
  • Instancing stores a repeated mesh (bolts, chairs, trees) once and draws every copy with EXT_mesh_gpu_instancing, which three.js supports. Run dedup first so identical copies are detected.

The trade-off: merging and flattening remove individual nodes, so skip them if your code moves or hides parts by name. All of these are geometry passes in our compressor, and weld, join, flatten and instance in gltf-transform.

6. Simplify (decimate) the mesh

Compression stores the same triangles more efficiently; simplification removes triangles. Scans, photogrammetry, sculpts and CAD tessellations often carry far more triangles than a web viewer can show, and fewer triangles also render faster.

  • Typical impact: depends on how dense the mesh is. Halving the dragon's triangle count before Draco gave 0.92 MB, against 1.17 MB for Draco alone.
  • Trade-offs: lossy, and visible if pushed too far. Check silhouettes, UV seams and shading up close. Weld first, or the simplifier can't collapse split vertices.
  • How: Blender's Decimate modifier, or gltf-transform simplify, where --ratio is the fraction of vertices to keep and --error caps how far the shape may drift (so it can stop short of the ratio).
npx @gltf-transform/cli weld model.glb welded.glb
npx @gltf-transform/cli simplify welded.glb simplified.glb --ratio 0.5 --error 0.001

7. Quantize vertex data

Quantization stores 32-bit float attributes as 16- or 8-bit integers (KHR_mesh_quantization). Draco and Meshopt already quantize internally, so on its own it matters mainly when you want smaller geometry without a decoder. Quantized data also stays smaller in GPU memory, not just on disk.

  • Typical impact: a moderate cut in geometry size, and gzip or Brotli on your server become more effective.
  • Trade-offs: slight precision loss (gltf-transform defaults to 14 bits for positions, 10 for normals, 12 for UVs), and the viewer must support KHR_mesh_quantization. three.js does.
  • How: gltf-transform quantize model.glb out.glb. gltfpack quantizes by default.

8. Trim and resample animation

Exporters often bake animation into a keyframe on every frame, including bones that barely move. Unused clips, control bones and redundant keyframes all end up in the file, and Draco doesn't compress any of it.

  • Typical impact: none on static models; significant on characters with long baked clips.
  • Trade-offs: resampling is nearly lossless; deleting clips or bones is only safe if nothing uses them.
  • How: gltf-transform resample removes redundant keyframes, and Meshopt compresses what's left. In Blender, delete unused actions and use the exporter's sampling and animation optimization options (see our Blender guide).

What to expect

Here are the two Khronos samples from above, processed with gltf-transform 4.5 (default settings unless noted). It's one test, not a benchmark, but it shows why the order of attack matters:

Model and stepsSizeChange
DamagedHelmet, original (textures ≈ 85% of file)3.77 MB
Draco only3.29 MB−13%
WebP only, textures kept at 2K1.82 MB−52%
Resize to 1K + WebP0.93 MB−75%
Resize to 1K + WebP + Draco0.45 MB−88%
DragonAttenuation, original (mostly geometry)6.40 MB
Meshopt only1.89 MB−70%
Draco only1.17 MB−82%
Simplify to 50% + Draco0.92 MB−86%

By model type, roughly:

Model typeUsually dominated byBiggest winsWhat to expect
CAD exports, 3D scans, photogrammetry, sculptsGeometryDraco or Meshopt, weld, simplifyLarge: often 70–90% from geometry compression alone
Game assets and charactersA mix, plus animationResize + WebP, Draco or Meshopt, resamplingModerate to large, depending on texture sizes
Product models with 2K–4K PBR texturesTexturesResize + WebP or AVIFLarge once textures are handled; small with Draco alone
Files already using Draco, Meshopt or KTX2VariesTexture resizing, if still largeLittle to gain; re-compressing costs quality

Tools compared

ToolBest forGeometryTexturesCost
compress-glb.comNo install, batch uploads, presets, REST APIDraco, weld, duplicate-vertex removal, simplify, instancing, mergeResize; WebP, AVIF, JPEG, PNG1 free credit, then credit packs
gltf-transform CLIFull control and scriptingDraco, Meshopt, quantize, every pass aboveResize; WebP, AVIF; KTX2 with KTX-SoftwareFree, open source; needs Node.js
gltfpackFast native Meshopt pipelinesMeshopt, quantization, simplification (no Draco)KTX2 (-tc), WebP (-tw)Free, open source
Blender glTF exporterFixing the model at the sourceDraco; Meshopt from 5.2; Decimate before exportJPEG or WebP, no resizingFree; one file at a time

Our online GLB compressor runs gltf-transform on our servers and applies Draco, texture resizing and conversion, and the geometry passes in one upload. The web app takes files up to 500 MB, a REST API covers pipelines and larger files, and every output is checked with the Khronos glTF validator. Typical results are 60–90% smaller.

On the command line, gltf-transform's optimize runs most of these techniques at once. By default it uses Meshopt, caps textures at 2048 px and simplifies with a very small error tolerance (turn that off with --simplify false). Our gltf-transform optimize guide explains the flags, and our Blender guide covers fixing the model before export.

npx @gltf-transform/cli optimize model.glb optimized.glb \
  --compress draco --texture-compress webp --texture-size 1024

Checklist

  1. Measure first: textures, geometry or animation?
  2. Resize textures to what the viewer actually shows (2K or 1K for most web use).
  3. Convert textures to WebP (or AVIF) and check the result up close.
  4. Prune and dedup unused and duplicate data.
  5. Weld, then simplify dense meshes if the silhouette holds up.
  6. Resample animation and drop clips and bones you don't use.
  7. Apply Draco or Meshopt as the last step.
  8. Validate the result in the glTF validator and test it in your real viewer, making sure it loads the decoders it needs (see loading GLB in three.js or our Shopify 3D model guide).

FAQ

Why is my GLB file so big?

Usually large, uncompressed textures: a few 4K PNG maps can add up to tens of megabytes. The other common causes are very dense meshes (scans, CAD, sculpts) and animation baked on every frame. gltf-transform inspect shows which one it is.

How do I reduce GLB file size without losing quality?

Start with the lossless steps: prune, dedup, weld and resample. Then apply the lossy ones moderately: WebP at quality 80 or higher, textures no larger than the viewer shows, and Draco at default quantization. Compare before and after up close.

Does Draco compression reduce quality?

Slightly, because it quantizes positions, normals and UVs. At default settings the difference is invisible on most models; raise the position bits for precise CAD parts or very large scenes.

Is GLB smaller than glTF?

A GLB is about the same size as a .gltf with separate .bin and image files, and roughly a quarter smaller than a .gltf with base64-embedded data. Our free glTF to GLB converter packs a .gltf and its files into one GLB; see glTF vs GLB for more.

Can I compress a GLB file online?

Yes. Our GLB compressor resizes and converts textures, applies Draco and cleans up geometry in one upload; it needs a free account, which includes one free compression. gltf-transform and gltfpack are free if you're comfortable with the command line.

Related articles