← Back to Blog tutorials

Why your GLB won't launch in Android AR (Scene Viewer fix)

By BitSoul Team9/19/20265 min read9 views
Why your GLB won't launch in Android AR (Scene Viewer fix)

A GLB that opens clean in Blender, three.js, or Godot can still fail the moment a phone tries to place it in Android AR. There's no error dialog and nothing useful in the console — the AR button just does nothing, or the model drops in at the size of a shipping container. Nine times out of ten it's one of three causes: the file is served from a `blob:` URL instead of a real HTTPS address, the mesh was exported at the wrong real-world scale, or a spec-valid feature in the file trips up Scene Viewer's own parser even though nothing else complains about it. Here's how to tell which one you've got, and how to fix each.

Why Scene Viewer breaks even when everything else renders fine

Why Scene Viewer breaks even when everything else renders fine — illustrated

The `ar-modes` attribute on a model-viewer element is a space-separated priority list — `webxr scene-viewer quick-look fallback` by default — and the browser activates the first mode the current device supports. On most Android phones that means Scene Viewer: a separate Google app launched over an intent, rendering with its own Filament engine, never touching the DOM your inline preview ran in. That's the entire reason a model can look flawless in your page's canvas and still fail once AR takes over: you've handed the file to a different renderer with different tolerances, and your desktop preview has no way to catch that.

It used to mean a forced detour through USDZ for anything AR-adjacent, with Android GLB support inconsistent between apps. Scene Viewer's GLB route shipped natively on July 29, 2026, as the direct counterpart to the USDZ path, so Android AR no longer needs a conversion step — just a correctly hosted file. If you're still generating USDZ for the iOS half of this pipeline, that conversion tool broke differently when Apple pulled usdzconvert, which is worth checking if you support both platforms from one export.

The three real causes, and how to catch each one

| Symptom | Likely cause | Fix |
|---|---|---|
| AR button never appears, `canActivateAR` stays false | Model served from a `blob:` URL created client-side | Host the `.glb` at a real `https://` path Scene Viewer's own process can fetch independently |
| Tapping AR opens Scene Viewer, then it closes or spins forever | Plain HTTP, localhost, or a redirect chain the intent won't follow | Serve the final file over HTTPS from a stable, non-redirecting path |
| Model places but is the size of a building or a coin | Export scale wasn't 1 unit = 1 meter | Fix the scene's unit scale before export, not after |
| Loads everywhere else, Scene Viewer force-closes on this one file | A spec-valid extension or vertex layout the Filament parser doesn't like | Re-export with only core PBR materials, no exotic KHR extensions, and retest |

The scale row is the most common and the least visible during testing, because an orbit-camera preview has no concept of "real world" — a 40-meter model and a 40-centimeter one look identical until a phone tries to rest one on your kitchen table.

Walkthrough: catching it before a user does

In Blender, scale problems almost always trace back to a transform that was never applied — an object scaled up 100x in the viewport that still reports 1.0 in the file. Object menu → Apply → All Transforms resets that multiplier before export, and it's worth doing even when the model "looks right," because the glTF exporter always writes meters regardless of what you assume the scene represents. Check Scene Properties → Units too: if the scene's unit scale isn't 1.0, the physical size baked into the file is off by that same multiple, and nothing in Blender's viewport will warn you about it.

On the hosting side, check the transport before touching the model at all:

```bash
curl -sI https://yourdomain.com/models/prop.glb | head -n 1
# want: HTTP/2 200 — a redirect, 403, or plain-http origin is why Scene Viewer never loads it
```

And catch failures in the browser instead of hearing about them from a support ticket. `canActivateAR` is set after the model's `load` event fires, and the `ar-status` event reports a `failed` state you can log or surface directly:

```js
const viewer = document.querySelector('#hero-model');
viewer.addEventListener('load', () => {
console.log('AR available:', viewer.canActivateAR);
});
viewer.addEventListener('ar-status', (e) => {
if (e.detail.status === 'failed') console.warn('Scene Viewer bailed on this model');
});
```

If you'd rather isolate the hosting problem first, test against a known-good file instead of your own: BitSoul's Taco Stand is a single mesh already exported in meters, so a failure against it narrows straight down to the URL. A free account's two monthly downloads cover evaluation; commercial use is included with paid memberships — see pricing.

Gotchas that waste the most debugging time

`canActivateAR` isn't a hard guarantee — it has returned false positives inside iOS WKWebView wrappers, so don't treat it as the only signal in an embedded app context. Mode order matters more than people expect: list `webxr` ahead of `scene-viewer` and a device with in-browser WebXR AR support will never launch Scene Viewer at all, so if you're specifically chasing a Scene Viewer bug, drop `webxr` from the list temporarily or you'll spend an afternoon debugging the wrong pipeline. And `fallback` mode means silence isn't always failure — when Scene Viewer can't launch, model-viewer can quietly swap to a fullscreen non-AR view instead of throwing an error, which looks exactly like "AR is broken" when it's actually behaving as configured.

None of this is testable from a desktop browser or most emulators — Scene Viewer needs a real ARCore-capable Android device, full stop. Keep the test file small while you isolate the problem: there's no LOD chain to argue with, since Scene Viewer only ever sees the single mesh you hand it (export pipelines that silently drop LOD levels aren't the issue here), and only reach for compressed textures once you've confirmed the target device actually decodes that KTX2 variant — Scene Viewer's texture support lags behind what desktop three.js will quietly accept. To catch a scale mistake before it ever reaches a phone, the free 3D Studio editor reports a model's real bounding-box dimensions in the browser, off your own GPU, before you export anything at all.

---

*This post is part of the Ultimate Guide to Free 3D Game Assets — BitSoul's complete reference for formats, texturing, rigging, optimization, and engine integration.*

Tags: 3d-models game-assets workflow tutorials optimization blender

Skip the modelling — download it instead

A free BitSoul account gets you 2 models every month plus 25 AI Engine credits to generate one of your own, no card required. Clean topology, PBR textures, and GLB downloads that drop straight into Unreal, Unity, Godot or Blender — OBJ and 3D-printable STL export come with any purchase or paid plan.

Browse 1051 models — from $4.99 → or start free (2 downloads a month)