Skip to content

Getting Started

  1. Install the package

    Terminal window
    npm i @capgo/inappbrowser
  2. Sync with native projects

    Terminal window
    npx cap sync

Import the plugin and use its two main entry points:

import { InAppBrowser, ToolBarType, BackgroundColor } from '@capgo/inappbrowser';
// 1) Simple custom tab / SFSafariViewController
const openExternal = async () => {
await InAppBrowser.open({
url: 'https://capgo.app',
isPresentAfterPageLoad: true,
preventDeeplink: false,
});
};
// 2) Full WebView with navigation, headers, share, messaging, etc.
const openWebView = async () => {
await InAppBrowser.openWebView({
url: 'https://capgo.app',
title: 'Capgo',
toolbarType: ToolBarType.NAVIGATION,
backgroundColor: BackgroundColor.BLACK,
activeNativeNavigationForWebview: true,
showReloadButton: true,
shareSubject: 'Check this page',
shareDisclaimer: {
title: 'Disclaimer',
message: 'You are about to share content',
confirmBtn: 'Continue',
cancelBtn: 'Cancel',
},
});
};
// Messaging between app and the opened WebView
const setupListeners = async () => {
await InAppBrowser.addListener('urlChangeEvent', (event) => {
console.log('URL changed to:', event.url);
});
await InAppBrowser.addListener('messageFromWebview', (event) => {
console.log('Message from web:', event.detail);
});
await InAppBrowser.addListener('closeEvent', () => {
console.log('WebView closed');
});
};
// Send data to the WebView
const sendData = async () => {
await InAppBrowser.postMessage({ detail: { action: 'refresh-profile' } });
};
// Close and reload helpers
const closeBrowser = () => InAppBrowser.close();
const reloadPage = () => InAppBrowser.reload();

Opens a URL in a custom tab / SFSafariViewController.

interface OpenOptions {
/** Target URL to load */
url: string;
/** Present after the page finishes loading */
isPresentAfterPageLoad?: boolean;
/** Prevent deep links from opening external apps */
preventDeeplink?: boolean;
}
await InAppBrowser.open({ url: 'https://example.com', preventDeeplink: true });

Loads a full-featured WebView with navigation UI, headers, credentials, scripting and messaging.

interface OpenWebViewOptions {
url: string;
headers?: Record<string, string>;
credentials?: { username: string; password: string };
materialPicker?: boolean;
shareDisclaimer?: {
title: string;
message: string;
confirmBtn: string;
cancelBtn: string;
};
toolbarType?: ToolBarType;
shareSubject?: string;
title?: string;
backgroundColor?: BackgroundColor;
activeNativeNavigationForWebview?: boolean;
disableGoBackOnNativeApplication?: boolean;
isPresentAfterPageLoad?: boolean;
isInspectable?: boolean;
isAnimated?: boolean;
showReloadButton?: boolean;
closeModal?: boolean;
closeModalTitle?: string;
closeModalDescription?: string;
closeModalOk?: string;
closeModalCancel?: string;
visibleTitle?: boolean;
toolbarColor?: string;
toolbarTextColor?: string;
showArrow?: boolean;
ignoreUntrustedSSLError?: boolean;
preShowScript?: string;
preShowScriptInjectionTime?: 'documentStart' | 'pageLoad';
proxyRequests?: string;
buttonNearDone?: {
ios: { iconType: 'sf-symbol' | 'asset'; icon: string };
android: { iconType: 'asset' | 'vector'; icon: string; width?: number; height?: number };
};
textZoom?: number;
preventDeeplink?: boolean;
authorizedAppLinks?: string[];
enabledSafeBottomMargin?: boolean;
useTopInset?: boolean;
enableGooglePaySupport?: boolean;
blockedHosts?: string[];
width?: number;
height?: number;
x?: number;
y?: number;
}
await InAppBrowser.openWebView({
url: 'https://new-page.com',
toolbarType: ToolBarType.NAVIGATION,
showReloadButton: true,
});

ToolBarType values: activity (close + share), compact (close only), navigation (back/forward + close), blank (no toolbar). BackgroundColor values: white or black.

Closes the WebView/custom tab.

Options:

  • isAnimated?: boolean - Whether to animate the close action

Reloads the current WebView page.

Goes back in WebView history and returns { canGoBack: boolean }.

Replaces the current WebView URL.

Injects JavaScript into the WebView.

Sends data from the native app to the WebView (receive in JS via window.addEventListener('messageFromNative', ...)).

Returns cookies for the URL.

clearCookies({ url }) / clearAllCookies() / clearCache()

Section titled “clearCookies({ url }) / clearAllCookies() / clearCache()”

Cookie and cache management helpers.

Change WebView size/position at runtime (width, height, x, y).

Unregister all listeners for the plugin.

Fired when the URL changes in the browser.

interface UrlChangeEvent {
url: string;
}
InAppBrowser.addListener('urlChangeEvent', (event) => {
console.log('New URL:', event.url);
});

Triggered when window.mobileApp.postMessage(...) is called inside the WebView.

InAppBrowser.addListener('messageFromWebview', (event) => {
console.log('Payload from web:', event.detail);
});

Fired when the browser is closed.

InAppBrowser.addListener('closeEvent', () => {
console.log('Browser closed');
});

Fired when the custom button added with buttonNearDone is pressed.

InAppBrowser.addListener('buttonNearDoneClick', (event) => {
console.log('Button near done tapped', event);
});

Triggered when a confirm dialog (disclaimer or close modal) is accepted.

InAppBrowser.addListener('confirmBtnClicked', (event) => {
console.log('Confirm accepted, current URL:', event.url);
});

Lifecycle events for WebView load success or failure.

InAppBrowser.addListener('browserPageLoaded', () => console.log('Page loaded'));
InAppBrowser.addListener('pageLoadError', () => console.log('Page failed to load'));
import { InAppBrowser } from '@capgo/inappbrowser';
export class OAuthService {
private listeners: any[] = [];
async authenticate(authUrl: string, redirectUri: string) {
return new Promise<string>((resolve, reject) => {
// Listen for URL changes
const urlListener = InAppBrowser.addListener('urlChangeEvent', (event) => {
if (event.url.startsWith(redirectUri)) {
// Extract OAuth code/token from URL
const url = new URL(event.url);
const code = url.searchParams.get('code');
if (code) {
InAppBrowser.close();
resolve(code);
} else {
const error = url.searchParams.get('error');
reject(new Error(error || 'OAuth failed'));
}
}
});
this.listeners.push(urlListener);
// Open OAuth provider
InAppBrowser.open({
url: authUrl,
preventDeeplink: true,
});
});
}
cleanup() {
this.listeners.forEach(listener => listener.remove());
this.listeners = [];
}
}
const openCustomBrowser = async () => {
await InAppBrowser.open({
url: 'https://example.com',
isPresentAfterPageLoad: true,
preventDeeplink: false,
});
};
import { InAppBrowser } from '@capgo/inappbrowser';
export class LinkHandler {
async openExternalLink(url: string) {
// Check if URL should open in browser
if (this.shouldOpenInBrowser(url)) {
await InAppBrowser.open({
url,
preventDeeplink: true,
});
} else {
// Handle internally
window.location.href = url;
}
}
private shouldOpenInBrowser(url: string): boolean {
// External domains
const externalDomains = ['youtube.com', 'twitter.com', 'facebook.com'];
const urlDomain = new URL(url).hostname;
return externalDomains.some(domain => urlDomain.includes(domain));
}
}
  1. Always remove listeners

    const listener = await InAppBrowser.addListener('urlChangeEvent', handler);
    // When done
    listener.remove();
  2. Handle browser states

    let browserOpen = false;
    const launch = async () => {
    browserOpen = true;
    await InAppBrowser.openWebView({ url: 'https://example.com' });
    };
    InAppBrowser.addListener('closeEvent', () => {
    browserOpen = false;
    });
  3. Validate URLs before opening

    const isValidUrl = (url: string): boolean => {
    try {
    new URL(url);
    return true;
    } catch {
    return false;
    }
    };
    if (isValidUrl(url)) {
    await InAppBrowser.open({ url });
    }
  4. Customize for platform

    import { Capacitor } from '@capacitor/core';
    const options = {
    url: 'https://example.com',
    preventDeeplink: Capacitor.getPlatform() === 'ios',
    };
  • Uses SFSafariViewController
  • Supports iOS 11.0+
  • Respects Safe Area insets
  • Supports custom presentation styles
  • Uses Chrome Custom Tabs
  • Falls back to WebView if Chrome not available
  • Supports Android 5.0 (API 21)+
  • Toolbar customization supported via toolbarType, toolbarColor, buttonNearDone, etc.
  • Opens in new browser tab/window
  • Limited customization options
  • No URL change events