Skip to content
DL2App

Blog

Android App Links not opening your app: a checklist that finds the cause

Your https link opens Chrome instead of your Android app. Work through these checks in order, from assetlinks.json and signing fingerprints to how the link was tapped, and you will find which one is failing.

· DL2App · 7 min read

You tap a link to your own domain on an Android phone and Chrome opens instead of your app. Since Android 12 there is no "open with" dialog to rescue you: if verification failed, the link quietly goes to the browser. The cause is almost always one of a short list, and they can be checked in order.

Start at the top. Each step assumes the ones before it pass.

1. The assetlinks.json file is reachable

Android decides whether a domain may open your app by reading a file at:

https://link.yourapp.com/.well-known/assetlinks.json

Open that address in a browser and check:

  • It answers 200 directly. No redirect of any kind, not http to https and not the bare domain to www. The verifier does not follow redirects for this file.
  • It is served over HTTPS with a valid certificate for that exact hostname.
  • It is JSON, sent as application/json.
  • It is not behind a login, a cookie wall, a bot check or a firewall rule. Cloudflare's bot protection is a common culprit, because Google's verifier is not a browser.

Every hostname needs its own file. yourapp.com and www.yourapp.com are two domains to Android.

2. The file names your app and its signing key

A minimal file looks like this:

[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.yourcompany.yourapp",
      "sha256_cert_fingerprints": [
        "14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"
      ]
    }
  }
]
  • The package name matches the build exactly, including any .debug or .staging suffix if you are testing one of those builds.
  • The fingerprint is SHA-256, in uppercase hex pairs separated by colons. SHA-1 does not count.
  • It is the fingerprint of the key that signed the installed app. This is where most failures come from:
    • Installed from Google Play with Play App Signing: Google re-signs your app. You need the app signing key fingerprint from Play Console, under Protected with Play › Play Store distribution › Go to Play app signing. Your upload key's fingerprint will not match.
    • A debug build from Android Studio: it is signed with your machine's debug keystore. Run ./gradlew signingReport and add the debug variant's SHA-256 too.
    • A release build you signed yourself: run keytool -list -v -keystore your-release.keystore and use the SHA-256 line.

You can list several fingerprints in the array, so add every key your test and release builds are signed with: Play's app signing key, your own release key, your debug key.

3. The manifest asks for verification

In AndroidManifest.xml, the activity that should open needs an intent filter like this:

<intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" />
    <data android:host="link.yourapp.com" />
</intent-filter>
  • android:autoVerify="true" is on the intent filter. Without it, Android never checks the file and the link is treated as an ordinary web link.
  • Both DEFAULT and BROWSABLE categories are there. Links from a browser need BROWSABLE.
  • The scheme is https. Custom schemes such as yourapp:// cannot be verified.
  • Every host you use is listed, including any second host you use for hand-offs and any custom domain, and each one serves its own assetlinks.json.
  • On Android 11 and older, one failing host fails them all. If any host in the app's verified intent filters doesn't pass, none of them are verified. Android 12 and later verify each host separately.

4. Verification actually succeeded on the phone

Android checks the files when the app is installed or updated, so a fix on the server only shows up after a reinstall, or after you ask for a new check. With the phone connected over USB:

adb shell pm get-app-links com.yourcompany.yourapp

Each host should say verified. If one says none, legacy_failure or a number such as 1024, Android could not match the file to the installed build. Go back to step 2 and compare the fingerprint with the one that signed this install.

After fixing something, ask for a fresh check instead of reinstalling:

adb shell pm verify-app-links --re-verify com.yourcompany.yourapp

Google's own reader shows what it sees from outside, which is useful when the file looks right in a browser but verification still fails:

https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://link.yourapp.com&relation=delegate_permission/common.handle_all_urls

If you publish on Google Play, Play Console's Deep links page also lists each domain your app declares and whether it passes.

5. Your app passes the link to your code

If the app opens but lands on its home screen, Android did its part. The link reached your app and was dropped.

  • Native Android: read intent.data in onCreate, and also in onNewIntent if the activity is singleTop or singleTask and might already be running.
  • React Native: read the link with Linking.getInitialURL() on a cold start and the url event after that. Make sure the intent filter is on MainActivity.
  • Flutter: use a package that receives App Links (such as app_links) and read the initial link on a cold start as well as later ones. If you use Flutter's built-in deep linking, the flutter_deeplinking_enabled metadata flag in the manifest controls whether Flutter's router takes the link.

6. How the link was tapped

This is where most "it works for me but not for them" reports come from. A correctly verified App Link still opens the browser when:

  • The link is typed or pasted into Chrome's address bar. App Links fire from a tap on a link, not from typing.
  • The person turned the link off for your app. Under Settings › Apps › Your app › Open by default, "Open supported links" can be switched off, and individual hosts can be unticked. A reinstall resets it.
  • The link arrives through a redirect from another domain. Email click tracking, link shorteners and ad trackers wrap your link in their own address. Whether the app opens at the end of that chain depends on the browser, and often it doesn't.
  • The tap happens inside Instagram, Facebook, TikTok or another app's own browser. Many of these load the link inside their web view and never hand it to Android. The person needs a way out to Chrome or the app.
  • The app is not installed. Then the browser is the correct result, and what happens next depends on where that page sends them.

7. Test it properly

  • Send the link to yourself in Messages, Gmail or a notes app and tap it there. That is the cleanest test of the Android side.
  • adb shell am start -a android.intent.action.VIEW -d "https://link.yourapp.com/test" opens the link as if it had been tapped, which shows whether the app claims it without involving any browser.
  • Test the shapes people actually use: from WhatsApp, from Instagram, from an email, app installed and not installed.

Check it in one go

Our free link checker runs the server-side half of this list for any link: it fetches the assetlinks.json and apple-app-site-association files, follows every redirect, checks status codes, content types, package names and fingerprints, and shows what Android, iPhone, desktop and in-app browsers are sent. If you are writing the file by hand, the assetlinks.json generator produces one from your package name and fingerprints. The iPhone version of this checklist is Universal Links not opening your app.

Or let a link service host it

The server half of this checklist is what a deep link service does for you. With DL2App, each project's hosts and custom domains serve an assetlinks.json generated from the package name and fingerprints you enter once, without redirects. Pages inside Instagram and other in-app browsers help people get out to the app. Health checks re-test the files on a schedule and email you if they break. The app side (steps 3 and 5) is still yours, and the Android setup guide walks through it, including where to find the Play signing fingerprint.

Questions people ask

Why does my Android App Link open in Chrome instead of the app? Usually one of three things: the assetlinks.json file can't be fetched cleanly (a redirect, wrong content type or a bot check), the fingerprint in it isn't the one that signed the installed build (Play App Signing is the usual reason), or the link was tapped in a way Android ignores (typed in the address bar or inside an in-app browser).

Which SHA-256 fingerprint goes in assetlinks.json? The one of the certificate that signed the app on the phone. For apps installed from Google Play with Play App Signing, that is the app signing key shown in Play Console, not your upload key. Add your debug key as well if you test debug builds.

How do I check if my App Links are verified? Run adb shell pm get-app-links your.package.name with the phone connected. Each host should say verified.

How long until a fixed assetlinks.json takes effect? Android reads the file on install or update. Reinstall the app, or run adb shell pm verify-app-links --re-verify your.package.name, then check again.

All posts

Start with one link

The free plan has no time limit and needs no card. Create a project, add your app, and send yourself the link.