npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@jhrunning/inappbrowserescaper

v1.0.0

Published

A TypeScript library to help users escape from in-app browsers like Instagram, Facebook, Telegram, etc.

Readme

InAppBrowserEscaper

npm version TypeScript License: MIT CI/CD

A lightweight TypeScript library that helps users escape from in-app browsers (Instagram, Facebook, Telegram, etc.) to their default browser for a better browsing experience.

🎮 Live Demo

https://github.com/user-attachments/assets/56dfa68e-ae6f-4640-ad71-bdfdd5999f78

📱 Try the Interactive Demo - Experience the library in action!

📱 Tip: For the best demo experience, open the link from Instagram, Facebook, or any other in-app browser on your mobile device.

🚀 Features

  • Zero Dependencies: Lightweight with no external dependencies
  • TypeScript Support: Fully typed with comprehensive TypeScript definitions
  • Framework Agnostic: Works with React, Angular, Vue, or vanilla JavaScript
  • Mobile Optimized: Specifically designed for mobile in-app browsers
  • Customizable UI: Flexible escape modal with customizable styling
  • Multiple Strategies: Auto-redirect, modal display, or manual trigger options
  • Comprehensive Detection: Detects popular in-app browsers

📱 Supported In-App Browsers

  • Instagram (iOS ✅, Android ✅)
  • Facebook (iOS ✅, Android ✅)
  • Facebook Messanger (iOS ❌, Android ✅)
  • Telegram (iOS ✅, Android ✅)
  • Snapchat (iOS ❌, Android ❌)
  • LinkedIn (iOS ✅, Android ❌)
  • Line (iOS ✅, Android ✅)
  • KakaoTalk (iOS ✅, Android ✅)
  • Safari In App - SFSafariViewController (iPhone ✅, iPad ❌)
  • Chrome Custom Tab (Android ❌)

📦 Installation

npm/yarn

npm install @jhrunning/inappbrowserescaper
yarn add @jhrunning/inappbrowserescaper

CDN (Browser)

<!-- Include from your own hosting -->
<script src="path/to/@jhrunning/inappbrowserescaper/dist/browser/inappbrowserescaper.js"></script>

<!-- Or use a CDN when published -->
<script src="https://unpkg.com/@jhrunning/inappbrowserescaper/dist/browser/inappbrowserescaper.js"></script>

🔧 Quick Start

Browser Usage (CDN/Direct Include)

For direct browser usage without a build system:

<script src="path/to/dist/browser/inappbrowserescaper.js"></script>
<script>
  const { InAppBrowserDetector, InAppBrowserEscaper } = window.InAppBrowserEscaper;
  
  if (InAppBrowserDetector.isInAppBrowser()) {
    InAppBrowserEscaper.escape();
  }
</script>

Module Usage (Node.js/Bundlers)

import InAppBrowserEscaper, { InAppBrowserDetector } from '@jhrunning/inappbrowserescaper';

// Check if user is in an in-app browser
if (InAppBrowserDetector.isInAppBrowser()) {
  // Show escape modal
  InAppBrowserEscaper.escape({
    message: 'For the best experience, please open this in your browser',
    buttonText: 'Open in Browser'
  });
}

Auto-Escape on Page Load

document.addEventListener('DOMContentLoaded', () => {
  if (InAppBrowserDetector.isInAppBrowser()) {
    InAppBrowserEscaper.escape({
      autoRedirect: true // Automatically attempt to open in external browser
    });
  }
});

🎨 Framework Integrations

React

import React from 'react';
import { useInAppBrowserEscaper } from '@jhrunning/inappbrowserescaper/react';

function MyComponent() {
  const { isInApp, browserInfo, escapeFromInApp } = useInAppBrowserEscaper();

  if (isInApp) {
    return (
      <div>
        <p>You're browsing in {browserInfo?.appName}</p>
        <button onClick={() => escapeFromInApp()}>
          Open in Browser
        </button>
      </div>
    );
  }

  return <div>You're in a regular browser!</div>;
}

Angular

import { Component, OnInit } from '@angular/core';
import { InAppBrowserEscaperService } from '@jhrunning/inappbrowserescaper/angular';

@Component({
  selector: 'app-my-component',
  template: `
    <button *ngIf="isInApp" (click)="escapeFromInApp()">
      Open in Browser
    </button>
  `
})
export class MyComponent implements OnInit {
  isInApp = false;

  constructor(private inAppBrowserService: InAppBrowserEscaperService) {}

  ngOnInit(): void {
    this.isInApp = this.inAppBrowserService.isInAppBrowser();
  }

  escapeFromInApp(): void {
    this.inAppBrowserService.escape();
  }
}

📚 API Reference

InAppBrowserDetector

analyze(): BrowserInfo

Returns detailed information about the current browser environment.

const browserInfo = InAppBrowserDetector.analyze();
console.log(browserInfo);
// {
//   isInApp: true,
//   platform: 'ios',
//   userAgent: '...',
//   appName: 'instagram'
// }

isInAppBrowser(): boolean

Quick check to determine if currently in an in-app browser.

getAppName(): string | undefined

Returns the detected app name if in an in-app browser.

InAppBrowserEscaper

escape(options?: EscapeOptions): boolean

Attempts to help the user escape from the in-app browser.

Options:

  • message?: string - Custom message to display (default: "For the best experience, please open this in your browser")
  • buttonText?: string - Custom button text (default: "Open in Browser")
  • showModal?: boolean - Whether to show the escape modal (default: true)
  • autoRedirect?: boolean - Attempt automatic redirect (default: false)
  • fallbackUrl?: string - Custom URL to redirect to (default: current URL)
  • force?: boolean - Force redirect attempt even when not in an in-app browser and copy URL to clipboard (default: false)
  • showQuickInstructions?: boolean - Show quick instructions overlay with platform-specific guidance (default: false)

copyUrlToClipboard(url?: string): Promise<boolean>

Copies the current or specified URL to the clipboard.

🎨 Customization

Custom Modal Styling

The escape modal uses inline styles but can be customized by targeting the modal elements:

/* Target the modal backdrop */
div[style*="z-index: 999999"] {
  /* Your custom styles */
}

/* Target the modal content */
div[style*="z-index: 999999"] > div {
  /* Your custom styles */
}

Custom Notification Bar

// Create a custom notification instead of using the modal
if (InAppBrowserDetector.isInAppBrowser()) {
  const notification = document.createElement('div');
  notification.innerHTML = `
    <span>You're in an in-app browser. </span>
    <button onclick="InAppBrowserEscaper.escape()">Open in Browser</button>
  `;
  document.body.prepend(notification);
}

🔧 Configuration Examples

E-commerce Site

if (InAppBrowserDetector.isInAppBrowser()) {
  InAppBrowserEscaper.escape({
    message: 'For secure checkout and the best shopping experience, please open this in your browser',
    buttonText: '🛍️ Shop Securely'
  });
}

Blog/Content Site

if (InAppBrowserDetector.isInAppBrowser()) {
  InAppBrowserEscaper.escape({
    message: 'For better reading experience and full functionality, open this article in your browser',
    buttonText: '📖 Read in Browser'
  });
}

Progressive Web App

const browserInfo = InAppBrowserDetector.analyze();
if (browserInfo.isInApp && browserInfo.appName === 'instagram') {
  // Instagram has limited PWA support
  InAppBrowserEscaper.escape({
    autoRedirect: true,
    message: 'This app works best in your browser'
  });
}

🌐 Browser Support

  • iOS Safari: Full support
  • Android Chrome: Full support
  • Desktop Browsers: Detection works, escape not needed
  • All Major In-App Browsers: Comprehensive detection

🔧 Troubleshooting

"Can't find variable: exports" Error

If you encounter this error when using the library directly in a browser:

  1. Use the browser-compatible build: Use dist/browser/inappbrowserescaper.js instead of dist/index.js
  2. Access via global variable: The library is available as window.InAppBrowserEscaper
<!-- ✅ Correct way -->
<script src="dist/browser/inappbrowserescaper.js"></script>
<script>
  const { InAppBrowserDetector } = window.InAppBrowserEscaper;
</script>

<!-- ❌ Avoid this -->
<script src="dist/index.js"></script> <!-- CommonJS build, not browser-compatible -->

Module Loading Issues

  • Node.js/Bundlers: Use import statements with the main package
  • Browser without bundler: Use the browser build with global variables
  • React/Angular: Import framework-specific integrations

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

  1. Fork the project
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

📝 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Inspired by the need for better user experience in mobile in-app browsers
  • Built with TypeScript for type safety and developer experience
  • Designed to be framework-agnostic for maximum compatibility

Made with ❤️ for better mobile web experiences