v147 · WebXR · AR

Compatibility Lab

Probes all five WebXR plane detection globals — XRPlane, XRPlaneSet, XRFrame.detectedPlanes, navigator.xr presence, and immersive-ar session support. Runs isSessionSupported() live and provides the graceful-degradation pattern for browsers without plane detection.

API probes

Plane Detection API compatibility matrix

API / GlobalChrome ≤146 (desktop)Chrome 147 (Android AR)Notes
navigator.xrWebXR Device API entry point
XRPlaneRepresents a detected real-world plane
XRFrame.detectedPlanesXRPlaneSet updated each frame
XRPlane.orientation"horizontal" | "vertical"
XRPlane.polygonDOMPointReadOnly[] — convex hull
immersive-ar (isSessionSupported)Device-dependent✓ with ARCoreRequires Android + ARCore
plane-detection feature stringPass in optionalFeatures array

Live session support probe

navigator.xr + plane detection globals
Click "Run probe" to check WebXR plane detection support…

Graceful degradation pattern

/* WebXR Plane Detection — feature detection + fallback */ async function startARWithPlanes() { /* 1. Check WebXR exists */ if (!navigator.xr) { showFallbackUI('WebXR not supported'); return; } /* 2. Check immersive-ar session support */ const arSupported = await navigator.xr.isSessionSupported('immersive-ar'); if (!arSupported) { showFallbackUI('Immersive AR not supported on this device'); return; } /* 3. Check plane detection globals (Chrome 147+) */ const hasPlaneDetection = 'XRPlane' in window && 'detectedPlanes' in XRFrame.prototype; /* 4. Request session — plane-detection as optional feature */ const session = await navigator.xr.requestSession('immersive-ar', { requiredFeatures: ['local'], optionalFeatures: ['plane-detection'], }); /* 5. In the frame loop, check if plane detection was granted */ session.requestAnimationFrame((time, frame) => { if (frame.detectedPlanes) { /* Plane detection available — use plane surfaces */ for (const plane of frame.detectedPlanes) { const pose = frame.getPose(plane.planeSpace, referenceSpace); renderPlaneOverlay(plane.orientation, plane.polygon, pose); } } else { /* Graceful fallback — no plane detection, place content manually */ renderWithHitTest(frame); } }); } /* Check plane detection support without requesting a session */ function supportsPlaneDetection() { return 'XRPlane' in window && typeof XRFrame !== 'undefined' && 'detectedPlanes' in XRFrame.prototype; }

see also