Persistent anchors in WebXR let virtual objects survive session reloads. Learn to implement XRAnchor, hit-test, and restore AR content. Full breakdown.
Why Anchors Matter for Spatial Web Apps
In an AR session, the browser tracks the physical world and gives you a coordinate system to place virtual content. The problem is that this coordinate system is temporary: it exists only while the session runs, and its origin can drift or reset when tracking is interrupted. If you place a virtual object relative to a fixed pose and the user walks away, turns off the headset, or reloads the page, that object rarely reappears in the same physical spot.
An XRAnchor solves the drift problem within a session. Instead of storing a static transform, you ask the system to track a point in the real world, and it continuously corrects that point's pose as it learns more about the environment. Persistent anchors extend this idea across sessions, so content placed today can be restored in the same location tomorrow.
Placing Content with Hit-Test
Before you can anchor anything, you need a real-world surface to attach it to. The hit-test API casts a ray from a screen point or controller into the detected geometry and returns poses where that ray meets a surface. A typical loop requests a hit-test source once, then reads results each frame to show a reticle where the user is aiming.
When the user confirms placement, create an anchor from the hit-test result rather than caching the raw pose. Calling createAnchor hands tracking responsibility to the system, and on each frame you read the anchor's current pose from the frame and update your object's transform to match. This keeps the object visually locked to the surface even as tracking refines.
Persisting and Restoring Anchors
To make anchors survive a reload, you need two things: a way to save an anchor and a stable handle to look it up later. On platforms that support persistence, you request a handle for an anchor and store that identifier, then use it in a future session to restore the same tracked point. The virtual content itself lives in your own storage, keyed by the handle.
- Save: when the user places an object, persist the anchor to get a handle, then store the handle alongside the object's data.
- Restore: on the next session, read your stored records and ask the system to resolve each handle back into a live anchor.
- Reconcile: an anchor may fail to restore if the environment changed too much, so handle the missing case and let users re-place.
Restoration is not instant. The device needs to recognize enough of the surroundings to relocate the anchor, so your content should appear only once the anchor resolves, not before. Design the loading state so users understand the app is still finding its place.
Practical Guidance and Fallbacks
Anchor and persistence support varies across devices, so treat both as optional features you detect at runtime. Request the relevant session features when you start the session, and branch your logic based on what the session actually grants rather than assuming availability.
Keep anchor counts modest, since each one carries tracking cost, and prefer anchoring groups of related objects to a shared anchor instead of one anchor per item. When persistence is unavailable, fall back to session-only placement so users can still position content, and be clear that it will not return after a reload. That graceful degradation keeps the core experience usable everywhere.