Detect if WhatsApp is installed

Looking at the page, it appears that at least on Chrome, they programmatically open an iframe with the src of whatsapp://send/?phone=<number>&text=test. They then start a 1000ms timeout after which the "Looks like you don't have WhatsApp installed!" text is shown. This timeout is cancelled by an blur event handler, meaning that their check is based on your device opening WhatsApp when that URL is loaded, which blurs the window.

The function which triggers after the timeout also seems to check if the timeout took longer than 1250ms. I suspect that this handles the case where your phone's browser stops executing JS timers when it changes apps.

On IE, they use window.navigator.msLaunchUri, which accepts a noHandlerCallback.

See for yourself by opening your browser's devtools and searching for WhatsAppApiOpenUrl. On Chrome, the Search can be found from the devtools' menu:

screenshot of where the Search tool can be found in Chrome's devtools

Here's some example code.

const detectWhatsapp = (phone, text) => {
  const uri = `whatsapp://send/?phone=${encodeURIComponent(
    phone
  )}&text=${encodeURIComponent(text)}`;

  const onIE = () => {
    return new Promise((resolve) => {
      window.navigator.msLaunchUri(
        uri,
        () => resolve(true),
        () => resolve(false)
      );
    });
  };

  const notOnIE = () => {
    return new Promise((resolve) => {
      const a =
        document.getElementById("wapp-launcher") || document.createElement("a");
      a.id = "wapp-launcher";
      a.href = uri;
      a.style.display = "none";
      document.body.appendChild(a);

      const start = Date.now();
      const timeoutToken = setTimeout(() => {
        if (Date.now() - start > 1250) {
          resolve(true);
        } else {
          resolve(false);
        }
      }, 1000);

      const handleBlur = () => {
        clearTimeout(timeoutToken);
        resolve(true);
      };
      window.addEventListener("blur", handleBlur);

      a.click();
    });
  };

  return window.navigator.msLaunchUri ? onIE() : notOnIE();
};

Please note that it adds an event listener each time it's called. If you're rolling this out into production, please use window.removeEventListener to remove handleBlur after the promise resolves. It also appends a DOM node into the body, if that matters to you.

Usage example:

detectWhatsapp('<your number here>', 'test').then(hasWhatsapp =>
  alert('You ' + hasWhatsapp ? "don't have WhatsApp" : 'have WhatsApp')
)

Here my testing on Android:

  • Built-in Browser (Webview) and Firefox if WA installed You can use iframe to auto open WhatsApp

  • Chrome and Opera Need user click action

but luckily I only need this simple code to detect if whatsapp installed

document.querySelector('#openWA').addEventListener('click', function() {
  var f = Date.now(),
    j = setTimeout(function() {
      if (Date.now() - f > 1250)
        return;
      alert('WA not installed')
    }, 1e3);
})
<a href="whatsapp://send/?phone=62812345678&amp;text=test" id="openWA">Send to WhatsApp</button>

<!-- Auto open on WebView and Firefox -->
<iframe id="launcher" src="whatsapp://send/?phone=62812345678&amp;text=test" style="display: none;"></iframe>