Back to Knowledge Hub
Platform

Browser API Compatibility Data and Feature Fallbacks

Use public browser compatibility data, runtime checks, and privacy-aware fallbacks to keep web tasks usable.

BotBrowser Team

Documentation

Want the structured docs for Platform?

This article lives in the editorial library. For step-by-step setup, reference material, and ongoing updates, jump into the docs section.

Compatibility tables answer “which releases should we test?” They do not answer whether a page is secure, a permission was granted, a device policy allows the call, or a server completed the operation. Combine public data with a just-in-time capability check and a visible alternative that preserves the user's work. BotBrowser can repeat this declared browser observation in an authorized controlled context, but it cannot grant permission or prove the remote result. The fixture below runs without collecting profile or account data.

A neutral flow from compatibility evidence through a runtime capability check to a primary or fallback action

TL;DR

  • Use MDN Browser Compatibility Data and the relevant W3C or WHATWG specification to choose a test matrix; record the revision date.
  • Detect the operation immediately before use. “The property exists” is permission to try, not proof of success.
  • Keep a keyboard-accessible fallback, preserve entered data, and explain changed fidelity or security properties.
  • Report browser capability, permission, application acknowledgement, and server outcome as separate observations.
  • BotBrowser can repeat an authorized synthetic journey in controlled contexts; it cannot grant permissions, change origin policy, or prove a remote transaction.

Contents

Read compatibility data as evidence

MDN Browser Compatibility Data records release ranges, notes, flags, secure-context requirements, and partial support. Read the notes with the green cells. The WHATWG HTML Standard and W3C WebAuthn specification define normative conditions for browser APIs. MDN's feature-detection guidance explains why a runtime check is more reliable than a user-agent branch.

For each feature, record the origin and secure-context requirement, method to check, permission and exception states, visible success signal, and fallback owner. A support table selects candidate releases, while the page decides its actual branch. A method can exist and still reject because of permission, policy, cancellation, or missing activation. A resolved browser promise can still precede a server error. Keep those facts in separate columns.

Design a capability decision

ObservationDecisionUser-visible resultBoundary
Method and context availableTry onceShow progress and cancelBrowser capability
Method missing or context blocks itUse fallbackKeep task and explain differenceCompatibility/context
Permission denied or cancelledOffer fallback without loopingPreserve control and entered dataPermission result
Call throws or rejectsClassify and stopShow recoverable error and next actionRuntime behavior
Call resolvesVerify application acknowledgementConfirm only observable resultBrowser plus application

Check immediately before the action because permissions, focus, and page state can change. Do not parse a user-agent string or infer a person's device. A fallback is correct when it preserves the task, labels lower fidelity or different security properties, and remains keyboard and assistive-technology accessible.

Exercise the fallback with a fixture

This deterministic fixture covers a missing method and a rejected call. In a test page, stub only navigator.share (or inject a wrapper), reset the DOM per attempt, and assert the visible status and fallback control. The expected result is completed with no fallback after a resolved call, or missing/denied/failed with an enabled “Copy link” action. It demonstrates application branching; it does not prove production support or service availability.

async function shareOrCopy() {
  const host = document.createElement('div');
  host.innerHTML = '<p id="status" role="status"></p><button id="fallback" hidden>Copy link</button>';
  document.body.append(host);
  const status = host.querySelector('#status');
  const fallback = host.querySelector('#fallback');
  if (typeof navigator.share !== 'function') {
    fallback.hidden = false;
    status.textContent = 'Use the available alternative';
    const result = { state: 'missing', action: 'copy-link' };
    host.remove();
    return result;
  }
  try {
    await navigator.share({ title: 'Synthetic item', url: '/fixture' });
    status.textContent = 'Shared';
    const result = { state: 'completed', action: 'none' };
    host.remove();
    return result;
  } catch (error) {
    fallback.hidden = false;
    status.textContent = 'Use the available alternative';
    const result = { state: error?.name === 'NotAllowedError' ? 'denied' : 'failed', action: 'copy-link' };
    host.remove();
    return result;
  }
}

Add a bounded timeout when the real operation can hang, and clean up in finally. Assert the message, focus target, and preserved input. Do not patch unrelated browser properties, capture credentials, or turn a synthetic rejection into a claim that a production service is down.

Progressive enhancement and privacy

Start with the core task: a normal file input, selectable URL, typed address, semantic form, or text summary often works without an optional API. Keep enhancement additive. If a share prompt is denied, expose copy or email without a hidden second prompt. If a file picker is unavailable, keep the ordinary input. If a credential ceremony is cancelled, leave the password route available and explain the choice.

Accessibility is part of compatibility. Give status text an appropriate live-region role, move focus to the available control, and make its label describe the action. Preserve drafts when changing paths. Store only feature, source revision, context, detected state, visible result, fallback, and review date. Do not retain raw profile attributes, credentials, location, or page captures when a short assertion is enough.

BotBrowser capability and limits

BotBrowser can run an authorized fixture in an isolated, declared browser context and compare visible branches across a chosen release set. This helps repeat checks of secure-context setup, permission-denied handling, rejected promises, and keyboard-reachable fallback controls. Keep the profile, release, origin assumptions, fixture revision, and visible assertion in the run record.

BotBrowser does not make an insecure origin secure, grant permission, override operating-system or embedding policy, or guarantee an API on every origin. A passing browser call does not prove that a server stored a record, sent a message, or completed a business transaction. Keep BotBrowser's observation beside an application acknowledgement. Never use an unavailable capability as a reason to alter a browser profile or infer a person's identity.

For adjacent examples, see WebDriver BiDi events and browser automation and Credential Management API sign-in.

Apply the rule to common APIs.

The same state vocabulary works across APIs, but the useful fallback differs. For Web Share, the primary action hands a title and URL to an operating-system share sheet. Copying a link or opening a mail composer can preserve the task when the method is missing, the document lacks transient activation, or the person cancels. The fallback should not silently copy private content; announce exactly which URL is being copied and let the person confirm the destination.

For the Clipboard API, check both the method and the document context before calling writeText. A rejected promise may mean permission policy, focus, or a user decision. Keep the text selectable in the page and provide a visible “Copy” button that can be tried again from a deliberate click. A successful write is a browser observation. It does not prove that the person pasted the value or that a server accepted it.

For Geolocation, the alternative is usually a typed address or a map search, not a fabricated position. Distinguish an insecure context from a permission denial and from a timeout. A returned position can still be stale or rejected by the application's business rule. State which timestamp and accuracy the application accepts, and do not retain coordinates in a compatibility log when a state and visible message are sufficient.

For File System Access, retain an ordinary <input type="file"> path. The picker may be absent, blocked by policy, or limited to a different directory scope. Explain whether the fallback uploads a copy rather than granting ongoing file access. Test cancellation as a normal outcome: the form should remain usable and the selected values should not disappear.

For WebAuthn, a missing PublicKeyCredential, an unsupported authenticator, a cancelled ceremony, and a server rejection are distinct states. Offer a password or recovery route that is clearly labelled and protected by the application's normal controls. Never turn an exception name into an identity claim. The browser can report that a ceremony ended; only the relying party can confirm that an account session was established.

Make fixtures deterministic.

A useful fixture has one declared purpose, one synthetic origin, and one expected visible result. Stub the smallest owned surface and reset it before every attempt. Use a deterministic title and URL such as /fixture, avoid real account names, and keep a timeout shorter than the test runner's global limit. The test should report whether it observed missing, denied, failed, or completed; it should not collapse a timeout into “unsupported.”

Assert both sides of a branch. When the primary API is unavailable, assert that the fallback is visible, focusable, labelled, and still has the original input. When the primary call resolves, assert the status message and then, if the product requires it, query an owned test endpoint for an application acknowledgement. Keep those assertions separate so a browser-only pass cannot mask a service failure.

Permission prompts deserve their own fixture state. A test can start with a permission policy that denies the feature, or inject a rejection with NotAllowedError, but it should record which method was used. Do not claim that an injected error reproduces every browser's prompt wording. The value is in verifying that the page gives control back to the person and does not spin, reprompt, or lose a draft.

Maintain a compatibility ledger.

Store one row per feature and review date. Include the public source URL and revision, supported release range, secure-context requirement, expected permission behavior, declared fixture, observed state, visible fallback, and owner. Add a note when an API is intentionally optional so a future change does not make it mandatory by accident. Remove a release only after the product owner confirms that the environment is no longer served.

Review the ledger after browser releases, framework upgrades, policy changes, and accessibility fixes. When a result changes, add a fixture for the new state before changing production branching. Compare the visible outcome at the same boundary for every release. A screenshot can show that a button appeared; it cannot show that a remote record exists. A resolved promise can show that the browser accepted a request; it cannot show that the person saw or trusted the result.

Keep records small. A feature name, source revision, browser release, context, state, visible message, fallback, and owner usually suffice. Do not combine those fields with a durable profile identifier. If support needs a screenshot, crop it to the control under test and redact names, tokens, balances, and unrelated page content before storing it. Set an expiry date for diagnostic artifacts.

Separate authorities during review.

The browser owns capability and permission observations. The transport layer owns whether a response reached the page. The application owns validation, authorization, and the meaning of a committed record. The storage system owns retention and deletion of its artifacts. A compatibility review should name the authority for each claim rather than putting every result under “browser support.”

This separation makes incidents easier to classify. A missing method points to release or context data. A NotAllowedError points to permission messaging and policy. A rejected fetch may point to transport, while a successful response with an error body points to application validation. A page that stays pending after a resolved browser call points to event handling or server acknowledgement. Each case has a different safe next action. Writing the authority beside the observation keeps a support note useful months later, when browser releases and permission policies have changed.

Accessibility as a fallback requirement.

Use semantic buttons and labels for primary and alternative actions. Make status text available to assistive technology without stealing focus from a person's current field. When focus must move, move it to the newly available control and preserve a route back to the original input. Do not encode the only distinction between “denied” and “failed” in color. The same message should be understandable at high zoom, with reduced motion, and when the optional API is disabled.

Keyboard testing belongs in the fixture, not only in a manual checklist. Tab to the primary control, activate it, trigger the missing or denied state, and confirm that the fallback receives a visible focus indicator. If the fallback opens a new page or downloads a file, announce that outcome and provide a stable return path. A feature that works only with a pointer is not a complete compatibility result.

Privacy boundary for compatibility evidence.

Capability testing describes what the current page can attempt. It does not describe who is operating the page, which hardware they own, or what they intend to do. Keep browser release, origin class, permission state, and fixture version; omit raw navigator dumps, credential values, location, file names, and page screenshots unless a narrowly scoped visual assertion requires them. A normalized state is easier to compare and less likely to become a second identity record.

When a test uses a controlled profile, document that it is a test context and keep its scope explicit. Do not mix compatibility rows with customer analytics or a long-lived account identifier. BotBrowser's isolated context helps make the observation repeatable, but the application still decides retention, authorization, and whether a server-side event is meaningful.

Review checklist with decision rules.

Before release, answer five questions in the record: Which public source and revision selected this case? Which exact capability and context are being exercised? What does each permission or exception state show to the user? Which fallback preserves the task and input? Which separate authority confirms an application result? If any answer is unknown, mark the case pending rather than converting uncertainty into “unsupported.”

For a new browser release, begin with the product's declared support range and one partial-support case. For a policy change, run the denied-permission fixture and verify the copy. For an accessibility change, run the keyboard path and inspect focus. For a server change, keep the browser fixture unchanged and update the application acknowledgement assertion. This keeps each change attributable and avoids broad user-agent branches.

The decision record should also state what happens when the primary capability disappears after page load. A person may switch tabs, revoke a permission, lose transient activation, or move from a secure to an embedded context. The control must fail into the same labelled alternative without clearing the draft. A support note that names this transition helps distinguish a regression from an expected policy branch and keeps the task finishable with the information already entered.

Final thoughts

Use compatibility data to choose what to test, runtime detection to choose the actual path, and a visible fallback to preserve the task. The next safe action is one synthetic fixture with an explicit context, a denied or missing branch, a keyboard assertion, and a separate application acknowledgement check.

FAQ

Is a green compatibility cell a guarantee?

No. It is release-level evidence. Secure context, permission, policy, activation, and partial-support notes can still change the result.

Should every rejected promise be retried?

No. Classify cancellation and denial, show the alternative, and use at most a bounded retry for an operation with a clear idempotency rule.

Does BotBrowser prove a remote operation completed?

No. It proves only the declared browser observation. Confirm commits, messages, or account changes through the owning service.

What belongs in a compatibility record?

Feature and source revision, browser release and context assumptions, detected state, original exception name, visible result, fallback action, and review owner. Exclude private page content.

Sources

#Browser APIs#Compatibility Data#Feature Detection#Progressive Enhancement#Fallbacks

Take BotBrowser from research to production

The guides cover the model first, then move into cross-platform validation, isolated contexts, and scale-ready browser deployment.