JustBrowser
Tutorials13 min read

getInstalledRelatedApps: How Sites Detect Your Installed PWAs

JustBrowser Platform Team·
getinstalledrelatedappspwa-fingerprintingbrowser-detectioncross-profile-linkingantidetect-browserbuildinpublicsaasstudioaiworkforcebuildwithclaude

Last Tuesday, I ran a fingerprint test on what I thought was a clean profile. Canvas hash — unique. WebGL renderer — plausible Intel GPU. Timezone, language, fonts — all matched my proxy's geolocation. CreepJS gave me 94% trust. Should've been golden.

Then I noticed something weird in the detection logs. A script was calling navigator.getInstalledRelatedApps(). And it was getting answers.

Turns out, I'd installed Twitter's PWA on my main machine months ago. Forgot about it completely. But every single browser profile on that device — including my "isolated" antidetect profiles — was leaking that information. Same PWA inventory across 12 different profiles. From a fingerprinting perspective, that's a giant neon sign saying "same person, same device."

This API doesn't get talked about much. It's not in the usual fingerprinting checklists. BrowserLeaks doesn't test for it. But if you're running multi-account operations and you've ever clicked "Install" on a progressive web app, you might be leaving correlation signals everywhere.

What We're Building

By the end of this tutorial, you'll understand:

  1. How getInstalledRelatedApps works and what it exposes
  2. Why it's a cross-profile correlation risk that most people miss
  3. How to test whether your profiles are leaking PWA information
  4. How to block or isolate this API per profile
  5. Which antidetect browsers handle this correctly (and which don't)

Takes about 20 minutes to work through. Worth it if you're running anything where account linking would hurt you.

Prerequisites

  • Basic familiarity with browser fingerprinting concepts
  • An antidetect browser setup (we'll use JustBrowser examples, but the concepts apply broadly)
  • Access to Chrome DevTools or similar
  • At least one PWA installed on your machine (for testing — we'll show you how to check)

If you haven't worked through the basics of browser fingerprinting yet, the WebGL fingerprinting deep-dive gives good background. Not required, but helps.

Step 1: Understand What the API Exposes

The getInstalledRelatedApps() API was designed with good intentions. It lets websites check if you've installed their native app or PWA, so they can avoid showing you "Install our app!" banners when you already have it.

Here's the basic call:

const relatedApps = await navigator.getInstalledRelatedApps();
console.log(relatedApps);
// Returns: [{ platform: "webapp", url: "https://twitter.com/manifest.json", ... }]

Seems harmless. The problem is in the details.

How it actually works:

  1. A website declares "related applications" in its web manifest (manifest.json)
  2. When you visit that site, it can call getInstalledRelatedApps()
  3. The browser checks if any of those declared apps are installed on your device
  4. It returns the ones that match

The API is scoped — twitter.com can only check for Twitter's related apps, not arbitrary apps. But here's the catch: fingerprinting services don't play by normal rules. A dedicated fingerprinting script can embed iframes or make requests to dozens of sites, each checking their own related apps. Aggregate the results and you've got a PWA inventory of the user's device.

I've seen fingerprinting test pages that check for: Twitter, Pinterest, Spotify, Starbucks, Uber, Google Maps, YouTube Music, and a dozen others. Each check is small. Combined, they're a unique identifier.

Step 2: Check What Your Device Leaks

Let's see what you're currently exposing. Open your main browser (not an antidetect profile — your regular Chrome or Edge) and open DevTools (F12). Go to the Console tab and paste:

// Check if the API exists
if ('getInstalledRelatedApps' in navigator) {
  console.log('API available');
  // Note: This will return empty unless called from a site
  // that has declared related_applications in its manifest
} else {
  console.log('API not available');
}

If you're on Chromium, it'll say "API available." Firefox and Safari users are safe from this specific vector.

Now here's the tricky part. The API only returns results when called from a page whose manifest claims the relationship. You can't just paste a script and get your full PWA list. But you can test specific sites.

Quick test: Visit twitter.com in your browser. Open DevTools, Console, and run:

navigator.getInstalledRelatedApps().then(apps => console.log(apps));

If you have Twitter's PWA installed, you'll see it in the array. If not, empty array.

Try a few other sites: starbucks.com, pinterest.com, spotify.com. Each site can only check its own apps, but by visiting several, you can map out your PWA footprint. (If you're running outreach campaigns via VeloCalls, your profiles need to stay completely isolated.)

What I found on my machine:

  • Twitter PWA: installed (forgot about it)
  • Starbucks PWA: installed (used it once for mobile ordering, never removed)
  • Spotify: not installed
  • Pinterest: not installed

Two PWAs. Doesn't sound like much. But how many other people have exactly Twitter + Starbucks PWAs installed and nothing else? It's a signal. Combined with other fingerprints, it narrows down identity fast.

Step 3: Test Your Antidetect Profiles

Here's where it matters. Open one of your antidetect browser profiles and repeat the test. Visit twitter.com, run the same DevTools query.

If you see your PWA listed: Your antidetect browser isn't isolating this API. Your profile is leaking host-system information. That's bad.

If you see an empty array: Could mean isolation is working. Could also mean the profile's PWA storage is simply empty. Test on a profile where you deliberately installed a PWA to confirm.

Most antidetect browsers I've tested don't handle this well. They isolate cookies, localStorage, IndexedDB — the usual stuff. But PWA installation state often lives at a different layer, closer to the operating system. Extension-based antidetect tools especially fail here because they're running inside the browser, not modifying how the browser stores PWA metadata. (I wasted two weeks troubleshooting "detection issues" before realizing the problem wasn't my fingerprint config — it was a Starbucks app I installed once and forgot about. Embarrassing.) If you run multi-account automation, this kind of leak can compromise the integrity of an entire pipeline.

The CreepJS test we covered before doesn't check this vector specifically. Neither does Pixelscan or BrowserLeaks. So you could have a profile that passes every common test while still leaking PWA correlation signals. Ask me how I know. (I learned this the expensive way.)

Step 4: Mitigation Approaches

There are three ways to handle this, ranging from "crude but effective" to "actually correct."

Option A: Remove All PWAs From Your Host Machine

The nuclear option. Uninstall every PWA on your device. In Chrome: Settings → Apps → Manage Apps → Remove each one.

Pros: No PWAs means nothing to leak.

Cons: Creates its own fingerprint. Zero installed PWAs is statistically unusual. Also annoying if you actually use PWAs for personal stuff.

I don't recommend this unless you're running a dedicated machine for multi-account work. On your daily driver, it's impractical.

Option B: Use Separate User Profiles or VMs

Each OS user account has its own PWA storage. If you run your antidetect browser under a different OS user than your personal browsing, the PWA inventories won't cross-contaminate.

Pros: Proper isolation at the OS level.

Cons: Operational overhead. Switching users is friction. VMs are heavier still. If you're managing 50+ browser profiles, you're not spinning up 50 VMs.

Works for high-security use cases. Overkill for most multi-account operators.

Option C: Use an Antidetect Browser That Isolates the API

This is what you want. A browser that either:

  • Returns an empty array regardless of host system state
  • Maintains per-profile PWA storage that's isolated from other profiles
  • Lets you configure spoofed PWA responses per profile

Each JustBrowser profile is a separate Chromium user-data directory, so a PWA installed in Profile A is not visible to Profile B and your host browser's PWAs are never part of a profile — the isolation comes from the per-profile data directory, not from an API override. Because it is plain per-profile storage rather than a JavaScript override, there is no injected getter for a fingerprinting script to spot.

I tested this specifically after the incident that opened this post. Created two profiles, installed Twitter PWA in one, left the other clean. Ran the API call in both. Profile A showed Twitter, Profile B showed nothing. Neither showed my host system's Starbucks PWA. That's correct behavior.

For operators who need to check their current setup: the antidetect browser myths post covers why extension-based tools fail at this kind of deep isolation.

Step 5: Verify Your Fix

After implementing whatever mitigation you chose, verify it works.

Test procedure:

  1. Install a test PWA on your host system (or confirm one exists)
  2. Open an antidetect profile
  3. Run the API check on a site whose PWA you installed
  4. Expected result: empty array (or only PWAs installed within that profile)
// Run this on the relevant site (e.g., twitter.com if testing Twitter PWA)
navigator.getInstalledRelatedApps()
  .then(apps => {
    if (apps.length === 0) {
      console.log('PASS: No host PWAs leaking');
    } else {
      console.log('FAIL: Leaking PWAs:', apps);
    }
  });

Run this across multiple profiles. The results should be consistent with your isolation strategy — either all empty, or reflecting only profile-specific installations.

If you're seeing host PWAs leak through, your antidetect browser isn't handling this vector. Time to either switch tools or implement OS-level isolation.

Common Errors and How to Fix Them

"getInstalledRelatedApps is not a function"

Cause: You're testing in Firefox or Safari. The API is Chromium-only.

Fix: Not an error — this browser simply doesn't support the API. If you're running Firefox profiles, you're not vulnerable to this specific fingerprint. Move on. (Though Firefox has its own fingerprinting surfaces; don't assume you're invisible.)

API returns empty but you definitely have PWAs installed

Cause: You're calling the API from a domain that hasn't declared those PWAs as related applications.

Fix: Test from the actual site whose PWA you installed. The API is scoped — you can only query apps the calling site claims ownership of.

Profile shows different PWAs than host system

Cause: This is actually correct behavior if your antidetect browser properly isolates PWA state.

Fix: None needed. Confirm the profile only shows PWAs installed within that profile (or none). That's isolation working correctly.

Profile shows ALL host system PWAs

Cause: Your antidetect browser isn't isolating PWA storage. The browser profile is reading from the shared system PWA registry.

Fix: This is architectural. You can't fix it with settings. Either switch to an antidetect browser with proper isolation (like JustBrowser's native engine), or implement OS-level separation with different user accounts.

Why This Matters for Multi-Account Operations

Here's the thing. If you're running ads across multiple accounts, PWA fingerprinting probably isn't what gets you banned. Platforms like Facebook and Google focus on more obvious signals first — IP, device fingerprint, behavioral patterns.

But if you're doing anything where serious correlation analysis matters — OSINT research, ad verification, competitive intelligence — this is exactly the kind of overlooked vector that catches people. It's not in the standard fingerprint tests. Nobody talks about it. And it's persistent — PWAs you installed years ago can still be queried. Honestly, that's what frustrates me most. I'm meticulous about browser hygiene and I still missed this for months.

Combined with other signals, PWA inventory becomes another data point in the correlation graph. Maybe not smoking-gun evidence on its own. But enough data points and statistical inference does the rest.

For ad verification teams checking whether campaigns render correctly across geos, this matters. For click fraud detection workflows using ClickzProtect, where you need your monitoring to be invisible, it matters. Teams running analytics across multiple domains need clean profile separation too. For anyone who assumes "I'm using an antidetect browser, I'm fine" — it's a reminder that the fingerprinting surface is larger than the usual suspects.

Next Steps

Now that you understand this vector:

  1. Audit your current profiles — Run the API check on your most important profiles. Know whether you're exposed.

  2. Test any antidetect browser before committing — PWA isolation isn't a checkbox feature you'll find in marketing materials. You have to actually test it.

  3. Consider PWA hygiene on your host machine — Maybe don't install every PWA that pops up. Or use a dedicated machine for sensitive operations.

  4. Add this to your fingerprint testing rotation — Along with CreepJS trust scores and WebGL consistency checks, PWA enumeration should be part of your verification workflow.

The fingerprinting arms race keeps finding new surfaces. Canvas, WebGL, audio, fonts — those get all the attention. But the quiet vectors like getInstalledRelatedApps often matter more precisely because nobody's watching for them.

Now you are. And honestly? I think PWA leakage is going to become a bigger deal over the next year as detection systems get smarter. Get ahead of it now.

Frequently Asked Questions

What exactly does getInstalledRelatedApps reveal about me?

It returns a list of related PWAs installed on your device. If a site's manifest declares related_applications and you've installed one of them, the API confirms it. The problem: this list is consistent across sessions and browser profiles on the same device. Two profiles with identical PWA inventories are statistically likely to be the same person — even if everything else differs.

Can I just uninstall all PWAs to avoid this fingerprint?

Technically yes, but that creates its own signal. Zero installed PWAs is uncommon among regular users. Detection systems notice statistical outliers. The better approach is profile-level isolation where each profile has its own PWA state — or using an antidetect browser that gives every profile its own browser data directory.

Do all websites have access to getInstalledRelatedApps?

No. The API only returns apps that the calling site has declared in its own web manifest. twitter.com can check if you have Twitter's PWA installed, but can't query whether you have Spotify's PWA. However, fingerprinting services can embed checks for dozens of popular PWAs by hosting manifests that claim those relationships.

Is this API available in Firefox or Safari?

No. As of July 2026, getInstalledRelatedApps is Chromium-only — Chrome, Edge, Opera, Brave, and Chromium-based antidetect browsers. Firefox and Safari don't implement it. If you're using Firefox profiles, this particular vector doesn't apply. But Firefox has its own fingerprinting surfaces that Chromium doesn't.


Try JustBrowser

Native Chromium antidetect browser — not extension-based. Real C++ engine patches at the canvas / WebGL / audio / font / screen layer, so 40+ identity parameters are genuine, not faked. REST API for Playwright, Puppeteer, Selenium. $9.99/month or $99.99/year. 7-day free trial, card required — cancel any time in the seven days and you are not charged. Unlimited profiles.

Get started → · How it differs from Multilogin / GoLogin / AdsPower

Ready to manage multiple accounts?

Seven days free, then $9.99/month — one plan, everything included.

We'd like to use Google Analytics, a Google service, to understand how our website is used. It sets two cookies in your browser and runs only if you click Accept. You can change your choice at any time with Cookie settings. Cookie Policy

Sign-in cookies and the cookie that remembers this choice are always on; the website needs them to work.

Google Analytics, a Google service, helps us understand how our website is used. It sets two cookies, _ga and _ga_TVZHQ99TZW. It is now onoff in this browser. If your browser sends a Global Privacy Control or Do Not Track signal, it stays off. Cookie Policy