{"id":550,"date":"2026-03-20T09:00:00","date_gmt":"2026-03-20T14:00:00","guid":{"rendered":"https:\/\/tolinku.com\/blog\/?p=550"},"modified":"2026-03-07T03:32:44","modified_gmt":"2026-03-07T08:32:44","slug":"verified-vs-unverified-app-links","status":"publish","type":"post","link":"https:\/\/tolinku.com\/blog\/verified-vs-unverified-app-links\/","title":{"rendered":"Verified vs Unverified App Links on Android"},"content":{"rendered":"\n<p>Android lets apps claim to handle URLs through intent filters, but not all URL-handling claims are equal. When an app is verified to handle a domain, Android routes matching URLs directly to the app. When an app is not verified, Android shows a disambiguation dialog that asks the user which app or browser should open the link.<\/p>\n\n\n\n<p>That dialog is the dividing line between a good user experience and a frustrating one. This guide explains exactly what verification means, what changes when it passes or fails, and why getting it right matters for your app&#39;s web-to-app conversion rate.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What &quot;Verified&quot; Means<\/h2>\n\n\n\n<p>An Android App Link is considered verified when Android has confirmed two things:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The <code>assetlinks.json<\/code> file at <code>https:\/\/{domain}\/.well-known\/assetlinks.json<\/code> contains an entry for your app&#39;s package name and signing certificate.<\/li>\n<li>Your app&#39;s intent filter declares <code>android:autoVerify=&quot;true&quot;<\/code> for that domain.<\/li>\n<\/ol>\n\n\n\n<p>When both conditions are true and the verification check succeeds, Android marks your app as the trusted default handler for that domain. The trust is domain-specific. An app can be verified for one domain and unverified for another.<\/p>\n\n\n\n<p>The <a href=\"https:\/\/developer.android.com\/training\/app-links\/verify-android-applinks\" rel=\"nofollow noopener\" target=\"_blank\">Android documentation on verifying App Links<\/a> describes the technical details of the verification process. The short version: Android (or Google&#39;s servers on Android 12 and later) fetches the <code>assetlinks.json<\/code> file during or shortly after app installation and checks whether the file authorizes your app.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The User Experience: Verified<\/h2>\n\n\n\n<p>When your app is verified for a domain and a user taps a link on that domain, the experience is direct:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>User taps <code>https:\/\/example.com\/products\/123<\/code> in a browser, email, or any other app.<\/li>\n<li>Android immediately launches your app and delivers the link.<\/li>\n<li>Your app opens to the product page.<\/li>\n<\/ol>\n\n\n\n<p>No dialog. No delay. No choice presented to the user. The link behaves like a first-class feature of the platform.<\/p>\n\n\n\n<p>This matters most in high-intent moments. Someone taps a product link from an email promotion, or follows a referral link from a friend. The fewer steps between tapping the link and seeing the content, the better the conversion. Even a single extra tap on a disambiguation dialog causes measurable drop-off, because some users will choose the browser (or simply close the dialog).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The User Experience: Unverified<\/h2>\n\n\n\n<p>When your app is not verified, the experience depends on several factors:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/doc-android-disambiguation-dialog.png\" alt=\"Android disambiguation dialog letting users choose which app handles a link\"><\/p>\n\n\n\n<p><em>Source: <a href=\"https:\/\/developer.android.com\/training\/app-links\/deep-linking\" rel=\"nofollow noopener\" target=\"_blank\">Android Developer Documentation<\/a><\/em><\/p>\n\n\n\n<p><strong>If only one app has an intent filter matching the URL:<\/strong> Android may still show a dialog asking the user to confirm which app should handle the link, even if there is only one candidate. This is the default disambiguation behavior for unverified links.<\/p>\n\n\n\n<p><strong>If no app has a matching intent filter (or none pass verification):<\/strong> The URL opens in the browser. The user never sees your app.<\/p>\n\n\n\n<p><strong>If the user previously chose an app:<\/strong> Android remembers the user&#39;s choice. If a user once selected your app from the disambiguation dialog, Android may route subsequent links from that domain to your app without showing the dialog again, but this preference is fragile. On Android 12 and later, this implicit preference behavior changed and became less reliable.<\/p>\n\n\n\n<p>The disambiguation dialog itself looks like a bottom sheet with app icons and names. For most users, it is an interruption. For technical users, it is information they can act on. For everyone, it adds friction.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The autoVerify Attribute<\/h2>\n\n\n\n<p>The <code>android:autoVerify<\/code> attribute is what tells Android to attempt verification for your intent filter. Without it, your intent filter works as an unverified deep link claim.<\/p>\n\n\n\n<p>Correct placement:<\/p>\n\n\n\n<pre><code class=\"language-xml\">&lt;intent-filter android:autoVerify=&quot;true&quot;&gt;\n    &lt;action android:name=&quot;android.intent.action.VIEW&quot; \/&gt;\n    &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; \/&gt;\n    &lt;category android:name=&quot;android.intent.category.BROWSABLE&quot; \/&gt;\n    &lt;data\n        android:scheme=&quot;https&quot;\n        android:host=&quot;example.com&quot; \/&gt;\n&lt;\/intent-filter&gt;\n<\/code><\/pre>\n\n\n\n<p>The attribute goes on the <code>&lt;intent-filter&gt;<\/code> element, not on the <code>&lt;data&gt;<\/code> element. A common mistake is placing it on <code>&lt;data&gt;<\/code>, where it is silently ignored.<\/p>\n\n\n\n<p>If you add <code>autoVerify=&quot;true&quot;<\/code> but do not host a valid <code>assetlinks.json<\/code> file, verification fails and the intent filter behaves exactly like an unverified one. The attribute alone is not enough; the server-side file is required.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What Happens When Verification Fails<\/h2>\n\n\n\n<p>If Android attempts verification and the <code>assetlinks.json<\/code> file is missing, unreachable, or contains incorrect data, your app is treated as unverified for that domain. The intent filter still exists and still matches URLs, but without verified status.<\/p>\n\n\n\n<p>On Android 11 and earlier, failure for one domain in an intent filter affected all domains in that filter. On Android 12 and later, each domain is evaluated independently. A failure for <code>www.example.com<\/code> does not remove verified status for <code>example.com<\/code> if that domain&#39;s file is correct.<\/p>\n\n\n\n<p>Verification failure is silent by default. Users see the disambiguation dialog (or links go to the browser) and there is no visible error. To check verification status programmatically during development:<\/p>\n\n\n\n<pre><code class=\"language-bash\">adb shell pm get-app-links --package com.example.myapp\n<\/code><\/pre>\n\n\n\n<p>The output shows each domain and its status. <code>verified<\/code> means the check passed. <code>rejected<\/code> means the check ran but the <code>assetlinks.json<\/code> file did not match your app. <code>none<\/code> usually means verification has not run yet, the domain is unreachable, or there was a network error.<\/p>\n\n\n\n<p>For common failure reasons and how to diagnose them, see the <a href=\"https:\/\/tolinku.com\/docs\/troubleshooting\/android\/\">Tolinku Android troubleshooting guide<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Fallback Behavior When the App Is Not Installed<\/h2>\n\n\n\n<p>Neither verified nor unverified App Links help when the app is not installed. If a user taps a link and the app is not on their device, the link opens in a browser regardless of verification status.<\/p>\n\n\n\n<p>This is where deferred deep linking becomes important. When the user installs the app after tapping a link, the app can retrieve the original link and route the user to the correct content. This requires a deep linking platform that stores the original URL and delivers it to the app on first launch.<\/p>\n\n\n\n<p>Tolinku handles this through its <a href=\"https:\/\/tolinku.com\/features\/deep-linking\">deep linking platform<\/a>. The Tolinku SDK captures the intent at the web layer and replays it after installation, so the user arrives at the right place even if they had to install the app first.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verified App Links and Instant Apps<\/h2>\n\n\n\n<p>Android Instant Apps are a special case. Instant Apps can open URLs without being fully installed, and they use App Links for URL routing. Instant App verification works through the same <code>assetlinks.json<\/code> mechanism, but the instant app variant of your app requires its own entry in the Digital Asset Links file.<\/p>\n\n\n\n<p>If you are building an Instant App alongside your main app, both package names (or both applications if they share a package name with different build types) need to be authorized in the file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Comparing the Two Outcomes<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Aspect<\/th>\n<th>Verified App Link<\/th>\n<th>Unverified Deep Link<\/th>\n<\/tr>\n<\/thead>\n<tbody><tr>\n<td>Disambiguation dialog<\/td>\n<td>Not shown<\/td>\n<td>Usually shown<\/td>\n<\/tr>\n<tr>\n<td>User choice required<\/td>\n<td>No<\/td>\n<td>Often yes<\/td>\n<\/tr>\n<tr>\n<td>URL ownership proof<\/td>\n<td>Required (assetlinks.json)<\/td>\n<td>Not required<\/td>\n<\/tr>\n<tr>\n<td>Intent filter attribute<\/td>\n<td><code>autoVerify=&quot;true&quot;<\/code><\/td>\n<td>Optional \/ omitted<\/td>\n<\/tr>\n<tr>\n<td>Android version dependency<\/td>\n<td>Works on Android 6.0+<\/td>\n<td>Works on all versions<\/td>\n<\/tr>\n<tr>\n<td>Link handling preference<\/td>\n<td>Managed per-domain (Android 12+)<\/td>\n<td>Based on user choice history<\/td>\n<\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Why Verification Is Worth the Effort<\/h2>\n\n\n\n<p>The case for verification is straightforward: users who do not have to make a choice are more likely to end up in your app. The disambiguation dialog is not a disaster, but it introduces a decision point where users can choose the browser, can close the dialog, or can simply feel frustrated that clicking a link did not &quot;just work.&quot;<\/p>\n\n\n\n<p>Apps that rely on links for re-engagement (push notifications, email campaigns, referral programs, social sharing) see real differences in conversion when App Links are properly verified. A link that routes directly to the right screen in your app performs better than one that sends the user to a browser with a banner asking them to open the app.<\/p>\n\n\n\n<p>The implementation effort is modest: host one JSON file, add one attribute to your intent filter, and get the correct certificate fingerprint. For guidance on the full setup, see the <a href=\"https:\/\/tolinku.com\/docs\/user-guide\/configuring-android\/\">Tolinku Android configuration guide<\/a> and the <a href=\"https:\/\/tolinku.com\/blog\/android-app-links-complete-guide\/\">Android App Links complete guide<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>Verified App Links skip the disambiguation dialog and send users directly into your app. Unverified links show a dialog and give users a chance to choose the browser instead. The <code>android:autoVerify=&quot;true&quot;<\/code> attribute triggers verification, but verification only passes if you also host a valid <code>assetlinks.json<\/code> file with the correct certificate fingerprint for your app. The effort to get verification working is low relative to the improvement in user experience and conversion.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The difference between a verified and unverified App Link is the difference between your app opening automatically and the user seeing a dialog asking which app to use. This guide covers what verification changes about the user experience, how the auto-verify attribute works, and why it matters for conversion.<\/p>\n","protected":false},"author":2,"featured_media":549,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Verified vs Unverified App Links on Android: Key Differences","rank_math_description":"Understand the difference between verified and unverified Android App Links. Learn how the disambiguation dialog works and why verification matters for UX.","rank_math_focus_keyword":"verified vs unverified app links","rank_math_canonical_url":"","rank_math_facebook_title":"","rank_math_facebook_description":"","rank_math_facebook_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-verified-vs-unverified-app-links.png","rank_math_facebook_image_id":"","rank_math_twitter_title":"","rank_math_twitter_description":"","rank_math_twitter_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-verified-vs-unverified-app-links.png","footnotes":""},"categories":[10],"tags":[25,23,39,20,33,41],"class_list":["post-550","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android","tag-android","tag-app-links","tag-conversion","tag-deep-linking","tag-user-experience","tag-web-to-app"],"_links":{"self":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/550","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/comments?post=550"}],"version-history":[{"count":1,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/550\/revisions"}],"predecessor-version":[{"id":551,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/550\/revisions\/551"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media\/549"}],"wp:attachment":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media?parent=550"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/categories?post=550"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/tags?post=550"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}