Shape Detection Api

BarcodeDetector, FaceDetector, and TextDetector use OS-native vision frameworks to analyze images. BarcodeDetector ships by default in Chrome. The other two are experimental. No JavaScript library needed.

June 10, 20264 min read14 / 17

There is a JavaScript API that decodes a QR code from a video frame in a single async call, using the OS's native vision framework instead of a 200kb library. It has been in Chrome since 2019.

It is called BarcodeDetector, and most developers still reach for jsQR instead.

Three Detectors, Three Tiers

The Shape Detection API has three interfaces:

DetectorWhat It DetectsTier
BarcodeDetectorQR codes, EAN barcodes, Data Matrix, etc.Light-green (Chrome by default)
FaceDetectorFace bounding boxes and landmarksYellow (developer trial)
TextDetectorArbitrary text / OCRYellow (developer trial, Android only)

BarcodeDetector is the one you can ship today. The other two are experimental and require origin trials.

BarcodeDetector

JavaScript
if (!('BarcodeDetector' in window)) { // Not supported -- load jsQR or ZXing as fallback } const detector = new BarcodeDetector({ formats: ['qr_code', 'ean_13', 'code_128'] // optional filter }) const barcodes = await detector.detect(imageSource) // imageSource: HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, Blob, or ImageBitmap for (const barcode of barcodes) { console.log(barcode.rawValue) // decoded string: "https://example.com" console.log(barcode.format) // "qr_code", "ean_13", etc. console.log(barcode.boundingBox) // DOMRectReadOnly -- position in the image }

detect() takes any image-like source -- a video element, a canvas, a Blob from fetch(), or an ImageBitmap. The input does not have to be live video.

formats is optional. An empty constructor detects everything the OS supports. Specifying formats is faster because it narrows what the detector checks for.

boundingBox and cornerPoints give the exact location of the barcode in the image -- useful for drawing an overlay frame around it.

FaceDetector

JavaScript
const faceDetector = new FaceDetector() const faces = await faceDetector.detect(imageSource) for (const face of faces) { console.log(face.boundingBox) // position of the face rectangle console.log(face.landmarks) // [{ type: 'eye', locations }, ...] }

landmarks are structured facial features: 'eye', 'nose', 'mouth'. This is a detection and location API, not a recognition one -- it tells you where faces are, not who they belong to.

FaceDetector is behind an origin trial. It is not available by default in any browser in 2026.

TextDetector

JavaScript
const textDetector = new TextDetector() const textBlocks = await textDetector.detect(imageSource) for (const block of textBlocks) { console.log(block.rawValue) // the OCR text console.log(block.boundingBox) }

OCR in the browser. A photo of a sign, a menu, or a whiteboard -- it extracts the text. Available in developer trials on Android Chrome, not elsewhere.

Shape Detection API: three detectors and their availability tiers ExpandShape Detection API: three detectors and their availability tiers

Why the OS Does the Work

All three detectors delegate the actual computer vision to the operating system.

On macOS, BarcodeDetector calls Apple's Core Image framework. On Android, it uses Google Play Services' ML Kit. The browser passes the image to the OS and receives structured results back. This is why the API is fast and battery-efficient: no heavy JavaScript on the main thread, no WebAssembly computation.

It also explains the fragmented support: the feature exists only where the OS exposes the capability to the web. Safari has not shipped the API -- not because Apple lacks the vision framework, but because they have not chosen to expose it through the web platform.

Feature Detection

JavaScript
if ('BarcodeDetector' in window) { // Use native detection } else { // Fall back to jsQR or ZXing (WebAssembly-based libraries) }

The light-green tier on api-maturity-levels covers the Chrome-dominant support pattern this API follows.

The natural pairing is the MediaDevices API: get a live camera stream, pull frames to a canvas, and pass each frame to BarcodeDetector.detect(). That is how real QR code scanners work in the browser.

The Essentials

  1. Three detectors: BarcodeDetector (default in Chrome), FaceDetector (origin trial), TextDetector (origin trial, Android only).
  2. detector.detect(imageSource) -- async, returns an array. Takes video, canvas, blob, or ImageBitmap.
  3. The OS does the vision work (Core Image on macOS, ML Kit on Android). The browser is a thin pass-through.
  4. Feature-detect with 'BarcodeDetector' in window. Fall back to jsQR or ZXing when absent.
  5. Safari does not implement this API. Chrome on desktop and Android Chrome are the primary targets.

Further Reading