Capacitor plugin for checking whether the app WebView engine is up to date, emitting realtime status events, and optionally showing a native update prompt that redirects users to the proper update destination.
bun add @capgo/capacitor-webview-version-checker
bunx cap syncMain use case: Browserslist-style compatibility checks by default.
The plugin uses this strategy out of the box, even if you do not add any plugin options:
minimumDeviceSharePercentdefaults to3- version-share data comes from a built-in dataset generated at build time from caniuse
- no runtime version-share URL call is required for the default flow
Default setup (no plugin settings):
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
plugins: {
WebviewVersionChecker: {},
},
};
export default config;Simple config-only setup with native prompt:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
plugins: {
WebviewVersionChecker: {
autoPromptOnOutdated: true,
autoPromptDismissible: false,
},
},
};
export default config;Advanced mode with custom threshold and custom dataset:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
plugins: {
WebviewVersionChecker: {
autoCheckOnLoad: true,
autoPromptOnOutdated: true,
minimumDeviceSharePercent: 3,
versionShareByMajor: {
'137': 58.2,
'136': 21.3,
'135': 4.6,
'134': 2.1,
},
},
},
};
export default config;What this means:
minimumDeviceSharePercent: 3means "consider a version compatible only if that major version still represents at least 3% of devices in my dataset".versionShareByMajoris your own dataset map where:- key = major version (for example
137) - value = share percent (
0..100)
- key = major version (for example
- If you do not provide
versionShareByMajor, the plugin uses its built-in generated dataset.
You can provide share data in two ways:
- Inline with
versionShareByMajor(as shown above) - Remote with
versionShareApiUrlreturning one of these shapes:{ "versionShareByMajor": { "137": 54.2, "136": 23.8 } }{ "shareByMajor": { "137": 54.2, "136": 23.8 } }{ "versions": [{ "major": 137, "share": 54.2 }, { "version": "136.0.0.0", "percent": 23.8 }] }
If you set versionShareApiUrl, the plugin fetches that URL at runtime and uses it as override.
Evaluation order:
- Browserslist-style threshold mode (
minimumDeviceSharePercent+ share dataset) is used first. By default this is3%with the built-in generated dataset. - Else the plugin compares against
latestVersion/latestVersionApiUrl. - Else it falls back to
minimumMajorVersion.
Advanced usage with JavaScript (manual check, listeners, custom prompt):
import { WebviewVersionChecker } from '@capgo/capacitor-webview-version-checker';
const listener = await WebviewVersionChecker.addListener('webViewOutdated', (status) => {
console.log('Outdated WebView detected', status);
});
const status = await WebviewVersionChecker.check({
latestVersionApiUrl:
'https://versionhistory.googleapis.com/v1/chrome/platforms/android/channels/stable/versions?page_size=1',
minimumMajorVersion: 124,
showPromptOnOutdated: true,
autoPromptDismissible: false,
promptTitle: 'Update WebView',
promptMessage: 'Your WebView is outdated. Please update to continue safely.',
promptUpdateButtonText: 'Update now',
promptCancelButtonText: 'Later',
});
console.log('WebView status', status);
// later
listener.remove();Capacitor already provides a built-in WebView minimum check through config:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
android: {
minWebViewVersion: 124,
},
server: {
errorPath: 'unsupported-webview.html',
},
};
export default config;android.minWebViewVersionis static config; it does not give runtime plugin events likewebViewOutdated.- With
server.errorPath, users are redirected to a static error page (hard block UX) instead of seeing a native modal in your normal app flow. - Without
server.errorPath, Capacitor only logs the issue, but does not provide a native update prompt + store deep link UX. - This plugin gives soft enforcement: users can still open/use the app, get a native update modal, and you decide whether to require update later.
- Main use case: this plugin brings Browserslist-style compatibility logic to Android WebView (for example, "support versions still used by at least 3% of devices"), while keeping your app usable.
The plugin resolves the active WebView provider package and version, then routes update links to the correct package:
- Android 5-6 and 10+: Android System WebView (
com.google.android.webview) - Android 7-9: Google Chrome (
com.android.chrome)
When provider detection is unavailable, fallback routing follows the same API-range rule above.
check(...)startMonitoring(...)stopMonitoring()getLastStatus()showUpdatePrompt(...)openUpdatePage(...)addListener('statusChanged', ...)addListener('webViewLatest', ...)addListener('webViewOutdated', ...)- Interfaces
- Type Aliases
Public API for checking WebView freshness and guiding users to updates.
check(options?: CheckWebViewOptions | undefined) => Promise<WebViewVersionStatus>Runs a version check and returns the latest known status.
| Param | Type |
|---|---|
options |
CheckWebViewOptions |
Returns: Promise<WebViewVersionStatus>
startMonitoring(options?: StartMonitoringOptions | undefined) => Promise<MonitoringStateResult>Enables background monitoring (typically on app resume).
| Param | Type |
|---|---|
options |
StartMonitoringOptions |
Returns: Promise<MonitoringStateResult>
stopMonitoring() => Promise<MonitoringStateResult>Disables monitoring.
Returns: Promise<MonitoringStateResult>
getLastStatus() => Promise<LastStatusResult>Returns the last resolved status, or null if no check was run yet.
Returns: Promise<LastStatusResult>
showUpdatePrompt(options?: ShowUpdatePromptOptions | undefined) => Promise<ShowUpdatePromptResult>Shows a native prompt asking the user to update the WebView.
| Param | Type |
|---|---|
options |
ShowUpdatePromptOptions |
Returns: Promise<ShowUpdatePromptResult>
openUpdatePage(options?: OpenUpdatePageOptions | undefined) => Promise<OpenUpdatePageResult>Opens the configured update page directly.
| Param | Type |
|---|---|
options |
OpenUpdatePageOptions |
Returns: Promise<OpenUpdatePageResult>
addListener(eventName: 'statusChanged', listenerFunc: (status: WebViewVersionStatus) => void) => Promise<PluginListenerHandle>Fired for every successful status evaluation.
| Param | Type |
|---|---|
eventName |
'statusChanged' |
listenerFunc |
(status: WebViewVersionStatus) => void |
Returns: Promise<PluginListenerHandle>
addListener(eventName: 'webViewLatest', listenerFunc: (status: WebViewVersionStatus) => void) => Promise<PluginListenerHandle>Fired when the state resolves to latest.
| Param | Type |
|---|---|
eventName |
'webViewLatest' |
listenerFunc |
(status: WebViewVersionStatus) => void |
Returns: Promise<PluginListenerHandle>
addListener(eventName: 'webViewOutdated', listenerFunc: (status: WebViewVersionStatus) => void) => Promise<PluginListenerHandle>Fired when the state resolves to outdated.
| Param | Type |
|---|---|
eventName |
'webViewOutdated' |
listenerFunc |
(status: WebViewVersionStatus) => void |
Returns: Promise<PluginListenerHandle>
Snapshot of the currently detected WebView status.
| Prop | Type | Description |
|---|---|---|
platform |
WebViewPlatform |
Native platform that generated the status. |
state |
WebViewVersionState |
Resolved version state. |
isLatest |
boolean |
Convenience boolean equivalent to state === 'latest'. |
checkedAt |
string |
ISO-8601 timestamp of the check. |
reason |
string |
Human-readable explanation for the reported state. |
currentVersion |
string |
Current WebView (or iOS system WebKit) version string. |
currentMajorVersion |
number |
Current detected major version (if parseable). |
latestVersion |
string |
Resolved latest version used for comparison. |
latestMajorVersion |
number |
Resolved latest major version (if parseable). |
currentVersionSharePercent |
number |
Device-share percentage for the installed WebView major version. Present only when a version-share dataset is available and includes the current major version. |
minimumDeviceSharePercent |
number |
Configured threshold used by compatibility-threshold mode. Present only when minimumDeviceSharePercent was requested for that check. |
versionShareSource |
string |
Source used for version-share data. Values: - versionShareByMajor (inline dataset) - versionShareApiUrl (remote dataset) - generatedVersionShareByMajor (built-in dataset generated at build time) |
deviceShareError |
string |
Diagnostic message for compatibility-threshold mode. Present when minimumDeviceSharePercent was requested but the threshold check could not be fully evaluated. |
providerPackage |
string |
Android package name of the active WebView provider. |
updateUrl |
string |
URL that should be opened to update when outdated. |
source |
string |
Internal source identifier for the check implementation. |
Options for running a WebView version check.
| Prop | Type | Description | Default |
|---|---|---|---|
showPromptOnOutdated |
boolean |
Force showing a native prompt if an outdated WebView is detected. | false |
source |
string |
Optional tag included in the status payload so you can identify the check origin. | "manual" |
Result payload for monitor controls.
| Prop | Type | Description |
|---|---|---|
monitoring |
boolean |
Whether monitoring is currently active. |
checkOnResume |
boolean |
Whether checks run on app resume while monitoring is active. |
autoPromptOnOutdated |
boolean |
Whether outdated checks auto-trigger the native prompt. |
Options for starting monitor mode.
| Prop | Type | Description | Default |
|---|---|---|---|
checkOnStart |
boolean |
Run a check immediately when monitoring starts. | true |
checkOnResume |
boolean |
Whether foreground checks should run while monitoring is enabled. | true |
Last known check snapshot.
| Prop | Type | Description |
|---|---|---|
status |
WebViewVersionStatus | null |
Null until the first check completes. |
Result payload for showUpdatePrompt().
| Prop | Type | Description |
|---|---|---|
shown |
boolean |
Whether a native prompt was actually shown. |
openedUpdatePage |
boolean |
Whether the update page was opened from the prompt action. |
Options for showing the native update prompt.
| Prop | Type | Description |
|---|---|---|
title |
string |
Prompt title. |
message |
string |
Prompt message. |
updateButtonText |
string |
Update CTA label. |
cancelButtonText |
string |
Cancel CTA label. |
updateUrl |
string |
Optional URL to open if the update action is selected. |
Result payload for openUpdatePage().
| Prop | Type | Description |
|---|---|---|
opened |
boolean |
Whether opening the update URL succeeded. |
url |
string |
URL that was attempted. |
Options for opening the update page directly.
| Prop | Type | Description |
|---|---|---|
updateUrl |
string |
Optional URL override. |
| Prop | Type |
|---|---|
remove |
() => Promise<void> |
'android' | 'ios' | 'web'
'latest' | 'outdated' | 'unknown'
