loading
Note:
This table is about the web platform, not about Butil Every wrapper on this site works in WebAssembly, Server and Hybrid alike. The limits below belong to the browser: an API that Firefox has not shipped is missing whether you reach it from C# or from JavaScript. The engine columns are a summary of the current state of the major engines - the live column is the only one that is authoritative for a particular visitor.

Check this browser

IsSupported

72 of the 136 classes here expose IsSupported(), a cheap feature detection that asks the runtime whether the underlying API object exists. Pressing the button runs all of them and fills the last column of the table below. This is exactly the check you should be making in your own app before offering a feature - never a user-agent string.

C#
if (await wakeLock.IsSupported())
{
    await wakeLock.Request();
}
else
{
    // offer the experience without it, rather than failing
}
Live sample
feature detection output
Results will appear here when you interact with the samples.

# The matrix

136 APIs

Filter by name, or by what an API demands of the page. "All engines" means every current Chromium, Firefox and WebKit release implements it; "varies by engine" means it is there everywhere but some members or behaviours are not.

Filter
Requires
Support
API
Engines
Requires
This browser
All engines
nothing
-
All engines
gesture
-
All engines
nothing
-
All engines
nothing
not checked
All engines
nothing
-
Varies by engine
HTTPSgesture
-
Varies by engine
nothing
not checked
Varies by engine
nothing
-
Varies by engine
nothing
-
Chromium only
nothing
-
Varies by engine
nothing
-
Chromium desktop
HTTPSpermissiongesture
not checked
Varies by engine
nothing
not checked
All engines
nothing
not checked
Varies by engine
nothing
-
Chromium only
nothing
not checked
All engines
nothing
-
All engines
nothing
-
All engines
nothing
-
Varies by engine
nothing
not checked
All engines
nothing
not checked
All engines
nothing
not checked
All engines
nothing
not checked
All engines
gesture
not checked
Chromium only
HTTPSgesture
-
Varies by engine
nothing
not checked
All engines
nothing
-
All engines
nothing
-
All engines
nothing
-
All engines
nothing
-
Chromium only
gesture
-
Varies by engine
nothing
-
Chromium only
nothing
-
Varies by engine
nothing
-
Chromium desktop
HTTPSgesture
-
Chromium on Android
nothing
-
All engines
nothing
-
All engines
nothing
-
Chromium only
nothing
-
Chromium only
experimental
-
All engines
nothing
-
All engines
nothing
-
Chromium only
HTTPS
not checked
All engines
nothing
not checked
All engines
HTTPS
not checked
All engines
HTTPS
not checked
Chromium only
HTTPS
-
All engines
gesture
not checked
Chromium only
HTTPSexperimental
-
All engines
nothing
-
All engines
nothing
-
Varies by engine
HTTPSpermissiongesture
not checked
All engines
HTTPS
not checked
All engines
nothing
-
Chromium only
gesture
not checked
All engines
HTTPS
-
All engines
nothing
not checked
All engines
nothing
not checked
All engines
nothing
-
All engines
nothing
-
Chromium desktop
HTTPSpermissiongesture
not checked
All engines
HTTPS
not checked
Chromium only
HTTPS
not checked
Chromium only
HTTPSpermission
-
Chromium only
HTTPS
-
Varies by engine
HTTPS
-
Varies by engine
HTTPSpermission
not checked
Chromium only
nothing
not checked
All engines
nothing
not checked
All engines
HTTPS
not checked
All engines
nothing
not checked
Varies by engine
nothing
not checked
All engines
nothing
not checked
All engines
nothing
not checked
All engines
HTTPS
not checked
All engines
nothing
not checked
All engines
nothing
not checked
Varies by engine
nothing
not checked
Varies by engine
nothing
not checked
Chromium only
HTTPSgesture
-
Chromium only
HTTPS
-
Chromium desktop
HTTPS
-
Chromium only
HTTPS
not checked
All engines
HTTPSpermission
not checked
All engines
HTTPSpermissiongesture
not checked
All engines
nothing
not checked
Varies by engine
HTTPSpermissiongesture
not checked
Chromium on Android
HTTPSpermissiongestureexperimental
not checked
Chromium only
HTTPSpermission
not checked
Chromium only
HTTPSpermissiongesture
not checked
Chromium only
HTTPSpermissiongesture
not checked
Chromium only
HTTPSpermissiongesture
not checked
Chromium only
HTTPSpermissiongesture
not checked
Chromium only
HTTPSpermission
not checked
Chromium only
HTTPSexperimental
not checked
Chromium only
HTTPSexperimental
not checked
Varies by engine
HTTPS
not checked
Chromium only
HTTPSpermissiongestureexperimental
not checked
Chromium on Android
HTTPSgestureexperimental
not checked
Chromium desktop
gestureexperimental
not checked
Chromium only
experimental
not checked
Chromium only
experimental
-
Chromium only
experimental
-
All engines
HTTPSgesture
not checked
Chromium only
HTTPS
not checked
Chromium only
HTTPSgesture
not checked
Chromium on Android
HTTPSpermission
not checked
Chromium on Android
HTTPSgestureexperimental
not checked
Varies by engine
nothing
not checked
All engines
HTTPSpermissiongesture
not checked
Chromium only
nothing
-
Chromium only
nothing
-
Chromium only
HTTPSexperimental
-
Varies by engine
HTTPSgesture
not checked
Chromium only
HTTPSexperimental
not checked
All engines
gesture
not checked
Varies by engine
HTTPSpermission
not checked
All engines
gesture
not checked
All engines
HTTPSpermission
not checked
Varies by engine
nothing
not checked
Chromium only
HTTPSgesture
-
All engines
nothing
-
Varies by engine
nothing
-
All engines
HTTPS
-
Varies by engine
HTTPS
-
Varies by engine
gesture
-
Chromium only
HTTPSgesture
-
Chromium only
HTTPSgesture
-
Varies by engine
HTTPSgesture
not checked
Chromium only
experimental
-
Chromium only
HTTPSgestureexperimental
-
Chromium only
HTTPSgestureexperimental
-
Chromium only
HTTPSgestureexperimental
-
Chromium only
HTTPSgestureexperimental
-
Chromium only
HTTPSgestureexperimental
-
Chromium only
HTTPSexperimental
-

Secure context

Powerful APIs are only exposed to pages served over HTTPS - or from localhost, which browsers treat as trusted so that development works. On an insecure origin the API object is simply absent, so IsSupported() returns false and there is nothing to catch. Window.IsSecureContext tells you which side of that line the page is on.

C#
if (await window.IsSecureContext() is false)
{
    // Clipboard, Crypto, Geolocation, ServiceWorker, WebAuthn and friends
    // do not exist here. Do not offer them.
}

Permission prompts

A permission-gated API shows the user a prompt the first time it is used, and the answer sticks for the origin. Query the current state before prompting so you can explain what you are about to ask for - a prompt that arrives out of nowhere is the one users deny. A denial is permanent until the user clears it in browser settings, so treat 'denied' as a stable state and not a retry opportunity.

C#
var state = await permissions.Query("geolocation");

if (state == PermissionState.Denied)
{
    // Do not call the API - it will fail without re-prompting.
    // Explain how to re-enable it in site settings instead.
}

User gesture

Opening a picker, entering fullscreen, playing audio, requesting a permission, writing to the clipboard - all of these require the call to originate from a real user interaction. The window is short and does not survive an arbitrary await, so do the gesture-bound call first and the slow work afterwards, not the other way around.

C#
private async Task OnClick()
{
    // First, while the gesture is still live:
    var color = await eyeDropper.Open();

    // Then everything else.
    await SaveToServer(color);
}

Experimental APIs

A handful of the APIs here are still being designed. They ship in one engine, sometimes behind a flag or an origin trial, and their shape can change. Butil wraps them because they are genuinely useful where they exist - but build them as enhancements you can withdraw, never as the only path through a flow.

C#
// The pattern for anything on this list: detect, use, degrade.
_canPickContacts = await contactPicker.IsSupported();
Warning:
Feature-detect, never user-agent-sniff The UserAgent API exists to tell you about the visitor, not to decide what your code may call. Engines ship features on their own schedule, browsers lie about their identity, and the string you match today breaks on the next release. IsSupported() asks the runtime the actual question and costs one interop call.
An unhandled error has occurred. Reload 🗙