W3docs

Tools

Browser Feature Detection

Quick check of which web platform features your browser exposes — storage, networking, graphics, media, and modern UX APIs. Probes run live in your browser; nothing is sent over the network.

0 of 34 features supported.

Storage

  • Web Storage

    localStorage + sessionStorage

  • IndexedDB
  • Cookies enabled

Networking

  • Fetch API
  • WebSockets
  • WebRTC
  • Service Workers
  • Beacon API
  • Push API
  • Background Sync

Device

  • Geolocation
  • Vibration API
  • Battery APIDeprecated

    Deprecated — removed from Firefox & Safari.

  • Clipboard API
  • Web Share API
  • Pointer Lock
  • Screen Orientation
  • WebMIDI

Graphics

  • WebGL
  • WebGL 2
  • WebGPU

    Chromium + Safari Tech Preview.

  • Web Animations API
  • Full Screen API

Media

  • Web Audio API
  • Media Capture

    getUserMedia

  • Notifications API

UX

  • Intersection Observer
  • Resize Observer
  • Mutation Observer
  • Web Authentication

    WebAuthn / passkeys

  • Payment Request API

Misc

  • File API
  • WebVRDeprecated

    Replaced by WebXR.

  • WebXR

About browser feature detection

This tool runs 34 live checks against the browser you’re using right now, grouped into seven categories — Storage, Networking, Device, Graphics, Media, UX, and Misc — and marks each one Supported or Not supported, with a running count of how many are supported at the top. A search box filters the list by feature name or note (try clipboard or webgl), since scrolling through all 34 by hand isn’t always what you want. Every result describes only the browser rendering this page — there’s no server-side lookup, device database, or comparison against other browsers involved.

Most checks are a single presence test — key in object, run against window, navigator, or document (Service Workers, for instance, is 'serviceWorker' in navigator). That’s the standard feature-detection idiom: ask the runtime directly, rather than parse navigator.userAgent, which browsers increasingly freeze or strip down. Two checks go further — WebGL and WebGL 2 try to actually create a canvas rendering context, since the constructor can exist while context creation still fails, wrapped in a try/catch so a failure doesn’t crash the page. All probing runs once inside a useEffect after mount, so server-rendered markup starts as unknown and hydration doesn’t mismatch.

Feature detection is how you build progressive enhancement: guard a call to a modern API with the same check the API relies on, and fall back when it’s missing, instead of shipping a polyfill blindly or trusting a browser-version cutoff. It also helps with diagnosis — if a script silently fails, checking whether this page reports that API as supported in the same browser tells you where to look next. The tool flags what’s deprecated (Battery API, WebVR) so you don’t build against something already being removed. Since it only checks the browser rendering this page, results differ across desktop, mobile, and in-app webviews — that’s expected, not a bug.

Examples

The presence-check pattern behind every rowjs
// Simplified from the tool's own probes (src/lib/tools/features.ts)
const has = (obj, key) => key in obj;

has(window, 'fetch');                 // Fetch API
has(window, 'indexedDB');             // IndexedDB
has(navigator, 'serviceWorker');      // Service Workers
has(navigator, 'clipboard');          // Clipboard API
has(window, 'IntersectionObserver');  // Intersection Observer

Every Supported / Not supported badge in the widget above reduces to one of these — a synchronous property check with no permission prompt, network request, or side effect.

Guarding a real call with the same checkjs
if ('clipboard' in navigator) {
  await navigator.clipboard.writeText('copied!');
} else {
  document.execCommand('copy'); // legacy fallback
}

This is the same check the tool’s Clipboard API row uses. Branch on it in your own code instead of wrapping the call in a bare try/catch and hoping it doesn’t throw.

Why WebGL needs more than a presence checkjs
function hasWebGL() {
  try {
    if (!('WebGLRenderingContext' in window)) return false;
    const ctx =
      document.createElement('canvas').getContext('webgl') ||
      document.createElement('canvas').getContext('experimental-webgl');
    return ctx !== null;
  } catch {
    return false;
  }
}

This mirrors the tool’s actual WebGL check in src/lib/tools/features.ts: the global constructor can exist while getContext still returns null (or throws), so only an actual non-null context counts as supported.

Frequently asked questions

What’s the difference between feature detection and browser sniffing?

Feature detection checks whether a specific API exists on the current runtime — for example, whether 'fetch' in window is true — and gets a direct answer for that one feature. Browser (user-agent) sniffing instead tries to infer capabilities by parsing the navigator.userAgent string, which is unreliable because browsers spoof, freeze, or shorten it, and a matching string still doesn’t guarantee a given API is actually present.

Does this tool send my browser data anywhere?

No. Every check runs client-side against window, navigator, and document in your own browser, and nothing is transmitted over the network, logged, or stored.

Why does this tool say a feature isn’t supported when I know my browser has it?

Most checks only confirm a property exists, such as 'clipboard' in navigator, which is normally accurate. A couple go further: WebGL and WebGL 2 actually attempt to create a canvas rendering context, which can fail — and get reported as unsupported — even when the underlying constructor exists, for example when a GPU is blocklisted or hardware acceleration is disabled.

Why do the results take a moment to appear?

The checks touch browser-only globals, so they can’t run while the page is server-rendered. The page first renders every feature as unknown, then runs all the probes once inside the browser right after the component mounts, and real results replace the placeholders a fraction of a second later.

How do I use feature detection like this in my own code?

Guard the API call with the same presence check the tool uses, then branch on it — for example, only call navigator.clipboard.writeText() inside if ('clipboard' in navigator), with a fallback in the else branch. That’s the standard progressive-enhancement pattern: use the modern API where it exists, degrade gracefully where it doesn’t.