v147 · web api · shipped
WebXR Plane Detection
A WebXR module that exposes flat surfaces (floors, walls, tables) detected by the underlying AR system. Each XRPlane has a coordinate space, a polygon boundary, an optional semantic label ("floor", "wall", "table", …), and an orientation. Requires a WebXR AR session with the "plane-detection" feature descriptor.
at a glance
| Feature descriptor | "plane-detection" — pass in requiredFeatures or optionalFeatures |
|---|---|
| Session type | "immersive-ar" |
| Planes accessed via | XRFrame.detectedPlanes — a XRPlaneSet of XRPlane objects |
| Platform requirement | Android with ARCore support; desktop with compatible AR hardware |
| Shipped in | Chrome 147 (desktop + Android) |
| ChromeStatus | 5732397976911872 — WebXR Plane Detection API |
| Spec | WebXR Plane Detection Module — Immersive Web WG |
why it exists
Depth sensing gives per-pixel distance data but doesn't classify surfaces or provide boundaries. Plane detection is a higher-level API: the platform's AR engine segments the environment into flat surfaces and provides structured data (position, orientation, polygon, semantic label) that AR experiences can use directly — for placing virtual objects on floors, aligning content to walls, or occluding virtual objects behind physical furniture. Occluded planes (walls behind objects) can still be represented if the AR system knows their extent.
Source: blink-dev ITS — WebXR Plane Detection, May 2026.XRPlane object
| Property | Type | Description |
|---|---|---|
planeSpace | XRSpace | Coordinate system for the plane; native origin at the plane's centre |
polygon | FrozenArray<DOMPointReadOnly> | Vertices of the plane boundary in planeSpace coordinates, expressed as a loop |
orientation | "horizontal" | "vertical" | null | Plane classification; null if the AR system can't classify it |
semanticLabel | DOMString | null | Human-readable label when available — e.g. "floor", "wall", "ceiling", "table" |
lastChangedTime | DOMHighResTimeStamp | Timestamp of the last update to this plane's data |
example
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['plane-detection']
});
// In the render loop:
function onXRFrame(time, frame) {
const planes = frame.detectedPlanes;
planes.forEach(plane => {
const pose = frame.getPose(plane.planeSpace, referenceSpace);
if (!pose) return;
console.log('Plane:', {
orientation: plane.orientation, // "horizontal" or "vertical"
label: plane.semanticLabel, // e.g. "floor"
vertices: plane.polygon.length, // number of boundary points
});
// Use pose.transform.matrix to position content on this plane
});
session.requestAnimationFrame(onXRFrame);
}
Source: WebXR Plane Detection Module spec and chromestatus, May 2026.
browser support
| Browser | Support |
|---|---|
| Chrome 147+ (Android/ARCore) | Enabled by default |
| Chrome 147+ (desktop, AR hardware) | Enabled by default |
| Firefox | No support |
| Safari | No support |