Free tool. No signup.

AASA validator

Universal links not working? Enter your domain. This checks your apple-app-site-association file the way iOS does, then tells you in plain language what is wrong and how to fix it.

Checks the live file at /.well-known/apple-app-site-association, the legacy root path, and Apple’s content delivery network. Nothing is stored.

What an apple-app-site-association file is

An apple-app-site-association file, usually shortened to AASA, is a small JSON file you host on your domain that tells iOS which app is allowed to open which URLs on that domain. It is the server half of Universal Links. The app half is the Associated Domains capability inside the app itself. Both halves must agree, or links open in Safari instead of your app.

When someone installs or updates your app, iOS asks Apple’s content delivery network for your domain’s file. The network fetches it from your server, keeps a copy, and hands that copy to devices. This is why a broken file fails silently and why a fixed file can take a while to take effect. The device is not reading your server, it is reading Apple’s cached copy of your server.

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

{
  "applinks": {
    "details": [
      {
        "appIDs": ["ABCDE12345.com.example.app"],
        "components": [{ "/": "*" }]
      }
    ]
  }
}

Three rules cover most of the failures we see: it must be reachable at /.well-known/apple-app-site-association over HTTPS, it must return a 200 with no redirect, and it must be valid JSON under 128 KB. The checker above tests all of that, plus the structural mistakes that JSON validators do not catch.

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

    The file belongs at https://yourdomain.com/.well-known/apple-app-site-association, with no file extension. A .json on the end, 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: Apple asks for the file and gets something that is not the file.

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

    Apple does not follow redirects when it fetches the association file. An apex to www rule, a trailing slash rule, a marketing redirect, 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 JSON is not valid.

    One trailing comma, one single quote, one stray comment, or an invisible byte order mark at the front of the file is enough. Apple parses strictly and silently: there is no error report anywhere, the links simply open in the browser instead of the app.

  4. 04 The app identifier is wrong.

    The appID value must be your ten character team identifier, a dot, then the exact bundle identifier, for example ABCDE12345.com.example.app. A bare bundle identifier with no team prefix, a wildcard copied from a provisioning profile, or a case mismatch in the bundle identifier all mean no app claims the link.

  5. 05 The URL does not match any declared pattern.

    The components or paths rules decide which URLs the app takes. A pattern of /link/* does not match /links/abc, patterns are case sensitive unless you say otherwise, and a query string only matters if you match it with the "?" key. If you want the app to handle everything on the domain, one component of { "/": "*" } is clearer than a long list that misses a route.

  6. 06 The app side is not set up.

    The file is only half of the association. The app needs an Associated Domains capability with an applinks:yourdomain.com entry, using the same hostname you serve the file from, and it needs a provisioning profile that includes the capability. If the entitlement is missing, misspelled, or points at the apex while your links use the www hostname, nothing you change on the server will help.

  7. 07 Apple is still serving the old file.

    Devices do not fetch the file from your server. They get it from Apple’s content delivery network, which keeps its own copy and refreshes on its own schedule, typically inside a day. Right after a change, your server can be perfect while devices still see the previous version. During development you can bypass the cache by adding ?mode=developer to the entitlement value and enabling Associated Domains Development in the device settings.

  8. 08 The device has not read the file since the change.

    iOS reads the association when the app is installed or updated. An app that was installed before you fixed the file keeps the old answer, which is why a change looks like it did nothing. Delete the app, reinstall it, and test again before concluding that the file is still wrong.

  9. 09 The user turned the association off without knowing it.

    When someone opens a universal link and then taps the small breadcrumb in the top corner of Safari to go back to the website, iOS remembers that preference and keeps opening the link in the browser from then on. Long pressing the link and choosing Open in App restores it. This is why a link can work for you and not for a colleague on the same build.

  10. 10 The link was opened somewhere universal links do not apply.

    Typing or pasting a URL into the Safari address bar never opens the app. Neither does a link that points at the same domain as the page the user is already on, nor a redirect chain that lands on your URL, nor several in-app browsers inside social and messaging apps. Test with a real tap from Notes, Messages, or Mail before you go hunting for a server problem.

Shipping on Android as well?

Android App Links fail for a different set of reasons, and the file has a different name, a different shape, and a stricter content type. The App Links validator runs the same kind of check against your assetlinks.json file, compares it to your package name and signing certificate fingerprint, and reports what Google currently resolves for the domain. Both tools are free and neither asks for an email.

If the file checks out but links still open Safari, the full setup is covered in the iOS deep linking guide, with Flutter and React Native versions for cross-platform apps.

Frequently asked questions

Where exactly should the apple-app-site-association file be served?
At https://yourdomain.com/.well-known/apple-app-site-association, over HTTPS, with no file extension and no redirect. The older root location, https://yourdomain.com/apple-app-site-association, is legacy. Serving both is fine as long as the contents match.
Does the file need a .json extension or a specific content type?
No extension. Apple asks for application/json as the content type, and in practice associations often still work when a server sends something else. Setting it correctly removes one variable, so it is worth doing.
Does the file still need to be signed?
No. Signed association files are a historical requirement. Serve plain JSON over HTTPS with a valid certificate.
How long does Apple take to pick up a change?
Apple’s content delivery network refreshes its copy on its own schedule, usually within a day. Until it does, devices keep using the previous version, even though your server already returns the new one. This validator queries that cached copy so you can see which version devices are actually getting.
Do subdomains need their own file?
Yes. Every hostname you list in the Associated Domains entitlement is a separate association, so app.example.com and www.example.com each need the file served from that exact hostname.
Does this tool store my domain or my file?
No. Every check is run live when you press the button and the result is discarded with the response. The shareable link carries only the domain, and opening it runs a fresh check.