@capgo/capacitor-webview-version-checker
June 16, 2026 · View on GitHub
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.
Install
You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command:
npx skills add https://github.com/cap-go/capacitor-skills --skill capacitor-plugins
Then use the following prompt:
Use the `capacitor-plugins` skill from `cap-go/capacitor-skills` to install the `@capgo/capacitor-webview-version-checker` plugin in my project.
If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:
bun add @capgo/capacitor-webview-version-checker
bunx cap sync
Usage
Main 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();
Why WebView Version Checker?
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;
Why we're doing this instead
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.
Android Provider Handling
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.
API
Public API for checking WebView freshness and guiding users to updates.
check(...)
check(options?: CheckWebViewOptions | undefined) => Promise<WebViewVersionStatus>
Runs a version check and returns the latest known status.
| Param | Type |
|---|---|
options | CheckWebViewOptions |
Returns: Promise<WebViewVersionStatus>
startMonitoring(...)
startMonitoring(options?: StartMonitoringOptions | undefined) => Promise<MonitoringStateResult>
Enables background monitoring (typically on app resume).
| Param | Type |
|---|---|
options | StartMonitoringOptions |
Returns: Promise<MonitoringStateResult>
stopMonitoring()
stopMonitoring() => Promise<MonitoringStateResult>
Disables monitoring.
Returns: Promise<MonitoringStateResult>
getLastStatus()
getLastStatus() => Promise<LastStatusResult>
Returns the last resolved status, or null if no check was run yet.
Returns: Promise<LastStatusResult>
showUpdatePrompt(...)
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(...)
openUpdatePage(options?: OpenUpdatePageOptions | undefined) => Promise<OpenUpdatePageResult>
Opens the configured update page directly.
| Param | Type |
|---|---|
options | OpenUpdatePageOptions |
Returns: Promise<OpenUpdatePageResult>
addListener('statusChanged', ...)
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('webViewLatest', ...)
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('webViewOutdated', ...)
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>
Interfaces
WebViewVersionStatus
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. |
CheckWebViewOptions
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" |
MonitoringStateResult
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. |
StartMonitoringOptions
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 |
LastStatusResult
Last known check snapshot.
| Prop | Type | Description |
|---|---|---|
status | WebViewVersionStatus | null | Null until the first check completes. |
ShowUpdatePromptResult
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. |
ShowUpdatePromptOptions
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. |
OpenUpdatePageResult
Result payload for openUpdatePage().
| Prop | Type | Description |
|---|---|---|
opened | boolean | Whether opening the update URL succeeded. |
url | string | URL that was attempted. |
OpenUpdatePageOptions
Options for opening the update page directly.
| Prop | Type | Description |
|---|---|---|
updateUrl | string | Optional URL override. |
PluginListenerHandle
| Prop | Type |
|---|---|
remove | () => Promise<void> |
Type Aliases
WebViewPlatform
'android' | 'ios' | 'web'
WebViewVersionState
'latest' | 'outdated' | 'unknown'