Deeplinkly
All articles
iOSDeep Linking

Universal Links Not Working? The iOS Debugging Checklist

Published July 3, 2026·Updated July 29, 2026·12 min read·By Sahil Asopa
Debugging iOS universal links: a broken chain between a website and an iPhone with a warning and a magnifying glass

You tap your universal link and Safari opens instead of your app. No error, no log, no clue. Universal links fail silently by design, which makes them one of the most frustrating things to debug on iOS — you're never told why iOS chose the browser over your app.

Almost every failure traces back to one of three things: a malformed apple-app-site-association file, a missing or wrong Associated Domains entitlement, or Apple's CDN serving a stale copy of your association file. This guide is an ordered checklist — work top to bottom and you'll find it.

How Universal Links Actually Work

Three things must line up for a universal link to open your app. Miss any one and iOS silently falls back to Safari:

iOS fetches your AASA file when the app is installed (and periodically after). It caches the result. This is why changes to the file don't take effect immediately, and why a reinstall is often part of the fix.

Checklist 1: The apple-app-site-association File

This is where the majority of universal link failures live. Your AASA file must satisfy every one of these — a single violation makes iOS discard it silently.

RequirementWhy it fails
Served over HTTPS with a valid certificateiOS refuses plain HTTP and self-signed / expired certs outright.
Reachable at /.well-known/apple-app-site-associationiOS checks /.well-known first. The domain root is a legacy fallback.
No file extension (not .json)The file must be named exactly apple-app-site-association, no .json suffix.
Content-Type: application/jsonA wrong MIME type (text/html, text/plain) causes iOS to reject it.
No redirects (200, not 301/302)iOS does not follow redirects when fetching the AASA file.
Valid, minified JSON — no comments, no BOMAny parse error voids the whole file.
Correct appID: TEAMID.bundleIDA wrong Team ID or bundle identifier means iOS never associates the domain.

A correct modern AASA file looks like this. The components format (iOS 13+) is preferred over the legacy paths array:

{
  "applinks": {
    "details": [
      {
        "appIDs": ["ABCDE12345.com.yourcompany.yourapp"],
        "components": [
          { "/": "/product/*", "comment": "Product pages" },
          { "/": "/promo/*",   "comment": "Campaign links" },
          { "/": "/settings",  "exclude": true, "comment": "Stay in Safari" }
        ]
      }
    ]
  }
}

Verify what your server actually returns — not what you think it returns — with a raw request:

curl -sviL https://yourdomain.com/.well-known/apple-app-site-association | head -n 20

# Check for, in the output:
#   HTTP/2 200          (no 301/302 redirect)
#   content-type: application/json
#   a JSON body with your correct TEAMID.bundleID

Find your Team ID: it's the 10-character identifier in the Apple Developer portal under Membership, and it prefixes your appID as TEAMID.bundleID. A mismatch here is the single most common AASA mistake.

Checklist 2: The Associated Domains Entitlement

Even a perfect AASA file does nothing if the app doesn't claim the domain. In Xcode, add the Associated Domains capability and an entry per domain:

<!-- YourApp.entitlements -->
<key>com.apple.developer.associated-domains</key>
<array>
  <string>applinks:yourdomain.com</string>
</array>

Checklist 3: Caching — Why It Works Sometimes

If universal links work on one device but not another, or stopped working after an AASA change, you're fighting a cache. iOS fetches your AASA file through Apple's CDN, and both layers cache aggressively.

During development, add the developer-mode query to force iOS to bypass the CDN and fetch your AASA file directly on every install:

<!-- Development only — bypasses Apple's CDN cache -->
<string>applinks:yourdomain.com?mode=developer</string>

After a production AASA change, remember that Apple's CDN can take up to 24–48 hours to refresh for already-installed apps. A clean uninstall and reinstall forces a fresh fetch on the test device. Remove the developer-mode flag before shipping to the App Store.

Cases That Legitimately Break Universal Links

Sometimes nothing is misconfigured — iOS is behaving as designed. If your setup is correct but a specific link still opens Safari, check whether you're hitting one of these:

ContextOpens the app?Why
Tapped in Messages, Mail, NotesYesStandard honored contexts.
Typed into the Safari address barNoManually entered URLs always stay in Safari by design.
Link on a page of the same domainNoiOS won't universal-link to an app from its own website — that's why you need a separate links subdomain.
window.location / JS redirectNoProgrammatic navigation is not a user tap and is ignored.
Pull-down 'Open in app' bannerYesThe Smart App Banner and long-press menu do honor the association.
Inside a third-party in-app browserVariesMany apps use their own WKWebView that swallows the link.

The same-domain trap: if your marketing site is yourdomain.com, a universal link on that same domain won't open the app. This is the most common "my config is perfect but it still fails" cause. Serve links from a dedicated subdomain like links.yourdomain.com.

Debugging Tools

When the checklist doesn't surface the issue, watch what iOS itself is doing. The Shared Web Credentials daemon (swcd) logs every association fetch and match decision.

# On a connected device via Console.app, filter the process: swcd
# Or dump the on-device association state with the CLI tool:
swcutil dl -d yourdomain.com

# Look for the domain in the output with an "approved" status.
# "denied" or a missing entry points straight at the AASA or entitlement.

To validate the file itself before you ever build, check that it parses and resolves correctly from the outside — the fastest way to rule out the AASA as the cause. Our free deep link debugger fetches your apple-app-site-association and assetlinks.json, checks the status code, content type, redirects, and JSON structure, and flags the exact rule you're violating — no signup required.

Check your AASA file in seconds

Paste your domain into the free Deeplinkly deep link debugger. It validates your apple-app-site-association and assetlinks.json and tells you exactly what's wrong.

Open the debugger

Start free

Frequently Asked Questions

Why do my universal links open Safari instead of my app?

Because at least one of the three requirements failed silently: the apple-app-site-association file is malformed, unreachable, or served with the wrong content type or a redirect; the Associated Domains entitlement is missing or has a typo; or the link was opened in a context iOS ignores, such as typing it into Safari or tapping a link on the same domain. Work the checklist top to bottom — the AASA file is the culprit most of the time.

Where should the apple-app-site-association file be hosted?

At https://yourdomain.com/.well-known/apple-app-site-association, served over HTTPS with a valid certificate, no file extension, a content type of application/json, and no redirects. iOS checks the /.well-known path first; the domain root is only a legacy fallback.

Why do universal links work after a reinstall but not before?

iOS fetches and caches your AASA file at install time through Apple's CDN. If you changed the file after installing, the device is still using the cached version. A full uninstall and reinstall forces a fresh fetch. During development, append ?mode=developer to your applinks entitlement to bypass the CDN cache entirely.

Why don't universal links work from my own website?

iOS deliberately does not open your app from a universal link hosted on the same domain as the link's website. If your marketing site and your links share a domain, the link stays in Safari. Serve deep links from a dedicated subdomain such as links.yourdomain.com to avoid this.

Do universal links need the app to already be installed?

Yes. Universal links route an existing installation to a screen. If the user doesn't have the app, the link opens your web page instead — routing them to the right screen after they install is a separate problem called deferred deep linking, which requires an install-matching service.

Fix It in Order

Universal links feel unpredictable only because iOS never tells you why it chose Safari. They're actually deterministic: validate the AASA file first, confirm the entitlement, rule out caching with a clean reinstall, and finally check whether the link is being opened in a context iOS honors. Ninety percent of failures resolve at step one.

If you'd rather not hand-manage AASA files, certificates, and subdomains at all, Deeplinkly hosts the association files for you on a branded custom domain with SSL, and its links handle deferred deep linking for users who don't have the app yet — so the routing works whether or not the app is installed.

Back to all articles

© Deeplinkly

Back to all articles© 2026 Deeplinkly

Related guides