Free tool. No signup.

Android App Links validator

App Links not working? Enter your domain. This checks your assetlinks.json file the way Android does, asks Google what it currently resolves, and tells you in plain language what is wrong and how to fix it.

assetlinks.json is a small JSON file you host on your domain that tells Android which app is allowed to open which URLs on that domain. Google calls the format Digital Asset Links. It is the server half of Android App Links. The app half is an intent filter in your manifest marked with android:autoVerify="true". Both halves must agree, or your links open in the browser instead of your app.

When someone installs or updates your app, Android asks Google to resolve the statements for every host in your intent filter. Google fetches the file from your server and answers. If anything in that chain fails, verification fails quietly: there is no warning at install time, no error in the store listing, and on Android 12 and later the link simply opens the browser as if your app were not there.

A minimal file that hands every URL on the domain to one app looks like this:

[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example.app",
      "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"
      ]
    }
  }
]

Note the square brackets. The file is an array of statements, not a single object, which is the opposite of the iOS apple-app-site-association file. Note also that sha256_cert_fingerprints is an array: most working files list two or three fingerprints, because the Play App Signing key, the upload key, and the debug key are all different certificates for the same app.

Four rules cover most of the failures we see: the file must be reachable at /.well-known/assetlinks.json over HTTPS, it must return a 200 with no redirect, it must be served as application/json, and the fingerprint in it must belong to the key that signed the build on the device. The checker above tests all of that, plus the structural mistakes a plain JSON validator cannot catch, and then asks Google what it actually resolves.

  1. 01 The file is not where Android looks for it.

    The file belongs at https://yourdomain.com/.well-known/assetlinks.json. Unlike the iOS association file this one does keep its .json extension, and unlike iOS there is no second location to fall back to. A file committed to the wrong build output, a static host that hides dot-directories, or a single page app router that answers every unknown path with index.html all produce the same result: Google asks for the file and gets something that is not the file.

  2. 02 A redirect sits in front of the file.

    Android does not follow redirects when it fetches the statement list. An apex to www rule, a trailing slash rule, a locale prefix rule, or a CDN page rule turns the fetch into a dead end even though the file exists at the other end of it. The request must be answered with a 200 and the file body at the exact URL that was asked for.

  3. 03 The file is not served as application/json.

    Google documents application/json for this file and its verifier reports a specific error when the type is wrong. This is stricter than iOS, where the wrong content type often works anyway. If the type comes back as text/html you usually have a bigger problem than a header, because the server is returning a page rather than the file.

  4. 04 The top level is an object instead of an array.

    assetlinks.json is a JSON array holding one statement object per app, so it starts with a square bracket. The iOS file is a single object, and copying that shape across is one of the most common mistakes on a project that set up universal links first. An object here is valid JSON and completely invalid as a statement list.

  5. 05 The fingerprint came from the wrong keystore.

    The same app produces a different SHA-256 fingerprint from the debug keystore, the upload keystore, and the Play App Signing key that Google holds. Android compares against whichever key actually signed the build on the device. A file that lists only the upload key verifies for nobody who installed from Play, and a file that omits the debug key fails every local test while looking correct in production.

  6. 06 The Play App Signing fingerprint is missing.

    Play App Signing has been on by default since August 2021, which means Google re-signs your app with a key you never handle. The certificate on the installed app is not the one you uploaded. Take the SHA-256 from the Play Console under App integrity, then App signing key certificate, and list it alongside your upload and debug fingerprints. Listing several fingerprints in one array is normal.

  7. 07 Only one of www and the apex serves the file.

    Android verifies each hostname on its own. A file on example.com grants nothing to links on www.example.com, and redirecting one to the other does not help because the verifier does not follow redirects. Serve the same file on both hostnames and declare both in your intent filter.

  8. 08 The app side is not set up.

    The file is only half of the association. The app needs an intent filter with android:autoVerify="true", the VIEW action, the BROWSABLE and DEFAULT categories, and a data element naming the https scheme and the exact host. Miss autoVerify and the link becomes a chooser dialog rather than a verified App Link. Declare a host that does not match the file and verification fails for that host alone.

  9. 09 Verification already ran and failed.

    Android verifies at install time. If the file was broken then, the app keeps the failed result until something makes it retry, so a fixed file can look like it did nothing. Reinstall the app, or on a development device check the current state with adb shell pm get-app-links your.package.name and force a retry with adb shell pm verify-app-links --re-verify your.package.name.

  10. 10 The user turned link handling off, or never turned it on.

    On Android 12 and later, unverified links do not open the app at all, they open the browser silently, and the user has to enable the domain by hand under App info, then Open by default. A verified link can also be switched off there. This is why the same link can open the app on your device and not on a colleague’s identical build.

  11. 11 The link was opened somewhere App Links do not apply.

    Typing or pasting a URL into the address bar never opens the app. Neither does a link inside many in-app browsers in social and messaging apps, nor a link that arrives through a chain of JavaScript redirects rather than as a real navigation. Test with a real tap from a notes app or a message before you go hunting for a server problem.

Shipping on iOS as well?

Universal Links fail for a different set of reasons, and the file has a different shape and a different name. The AASA validator runs the same kind of check against your apple-app-site-association file, including what Apple’s content delivery network is currently handing to devices. Both tools are free and neither asks for an email.

If the file checks out but links still open the browser, the full setup is covered in the Android App Links guide, with Flutter and React Native versions for cross-platform apps.

Frequently asked questions

Where exactly should assetlinks.json be served?
At https://yourdomain.com/.well-known/assetlinks.json, over HTTPS, served as application/json, with a 200 status and no redirect. This is the only path Android reads, so unlike the iOS association file there is no legacy fallback location.
Why does my file work on iOS but not on Android?
They are different files with different shapes. The iOS apple-app-site-association file is a single JSON object with no extension. assetlinks.json is a JSON array of statement objects and does keep its extension. Android is also stricter about the content type and about redirects.
Which SHA-256 fingerprint should I use?
The one belonging to the key that signs the build people actually install. If you publish through Play with Play App Signing, that is the app signing key certificate shown in the Play Console under App integrity, not your upload key. List the upload key and your debug keystore fingerprint as well so local and internal builds verify too. Multiple fingerprints in one array is normal.
How do I get the fingerprint from my keystore?
Run keytool -list -v -keystore your.keystore -alias your-alias and copy the SHA256 line, not the SHA1 line. The debug keystore lives at ~/.android/debug.keystore with the alias androiddebugkey and the password android. App Links are verified against SHA-256 only.
How long does Android take to pick up a change?
Verification happens when the app is installed or updated, so an app installed before the fix keeps its old result. Google also caches its own copy of your file for a period it does not document. On a development device you can force a retry with adb shell pm verify-app-links --re-verify your.package.name and inspect the result with adb shell pm get-app-links your.package.name.
Do subdomains need their own file?
Yes. Verification is per hostname, so app.example.com and www.example.com each need the file served from that exact hostname, and each host needs its own data element in the intent filter.
Does this tool store my domain, package name, or fingerprint?
No. Every check runs live when you press the button and the result is discarded with the response. A signing certificate fingerprint is public information that already appears in your assetlinks.json file, and it is only ever compared against content we just fetched. The shareable link carries the values you typed so the check can be run again, never a stored result.