Short answer: Google requires assetlinks.json over HTTPS, "without any redirects (no 301 or 302 redirects)", served as application/json. Any status other than 200 "is treated as an error, and will result in an empty statement list". Check every host with curl -i and fix the server, not the file.
What is happening
assetlinks.json delivery: how your server returns https://<host>/.well-known/assetlinks.json, which must be a direct 200 over HTTPS with Content-Type: application/json.
The content can be perfect and still fail if delivery is wrong. Google's rules are explicit:
- The file must be at
https://domain.name/.well-known/assetlinks.json. "Statement lists in any other location, or with any other name, are not valid for this site." - It must be served over HTTPS, "regardless of whether your app's intent filters declare HTTPS as the data scheme".
- It must be served as
application/json. - No 301 or 302 redirects.
- Each host in the manifest needs its own file.
Why does this happen?
Site-wide rules that suit web pages break this one file. Redirects from the apex to www, from HTTP to HTTPS, or from a trailing slash path are the usual causes.
- Apex and www:
example.comredirects towww.example.com, but the manifest declaresexample.com. - Static host defaults: some hosts send
.jsonfiles with a different type, or block dot-folders like/.well-known/. - Security rules: a WAF or login wall returns a 403 or a challenge page.
- Wrong path: the file sits at
/assetlinks.jsonor/.well-known/assetlinkswithout the extension.
How to confirm it
- Run
curl -i https://example.com/.well-known/assetlinks.json. Check forHTTP/2 200,content-type: application/jsonand noLocationheader. - Repeat for every host in your intent filters, including
wwwand other subdomains. - Query Google's view:
https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://example.com&relation=delegate_permission/common.handle_all_urls. - On a device, run
adb shell pm get-app-links com.example.app. Onlyverifiedmeans success.
How to fix it
- Exclude
/.well-known/assetlinks.jsonfrom redirect rules on every host. - Publish the file on each host the manifest declares. For a wildcard host like
*.example.com, Google says to publish it at the root hostname,example.com. - Set
Content-Type: application/jsonfor the file. - Allow
/.well-known/through any firewall, bot or login rules. - Re-verify on a test device:
adb shell pm set-app-links --package com.example.app 0 alladb shell pm verify-app-links --re-verify com.example.app- wait a few minutes, then
adb shell pm get-app-links com.example.app
location = /.well-known/assetlinks.json {
default_type application/json;
try_files /.well-known/assetlinks.json =404;
}
Check the file content with Google's Statement List tester at the same time. The iOS version of this problem is AASA redirect or blocked. Repeat curl -I https://example.com/.well-known/assetlinks.json for every host.