Universal links setup, step by step for iOS

Set up iOS universal links end to end. Add the Associated Domains entitlement, host the AASA file, handle the link in your app and test it on a real device.

Short answer: Universal links need three things: an Associated Domains entitlement in the app (applinks:example.com), an apple-app-site-association file at https://example.com/.well-known/apple-app-site-association naming the app, and code that handles the incoming URL. Test by tapping links from Notes, never by typing into Safari.

What is a universal link?

Universal link: an ordinary https URL on a domain you control that iOS opens directly in your app when the app is installed, and in the browser when it is not.

Unlike a custom URL scheme, a universal link is tied to a domain you prove you own, and it always has a web fallback. Apple says that if the person hasn't installed the app, "the system opens the URL in their default web browser".

Step 1: add the Associated Domains entitlement

In Xcode, open your target's Signing & Capabilities tab, add Associated Domains, and list each domain:

applinks:example.com
applinks:www.example.com
applinks:go.example.com
  • Use the form <service>:<fully qualified domain>.
  • Apple says: "Don't include path and query components or a trailing slash."
  • Ports are not supported: "Domains in your applinks can't contain a port number."
  • A wildcard such as applinks:*.example.com covers all subdomains, with the file served at the apex.
  • Each specific subdomain is separate. A file on example.com does not cover applinks:www.example.com.
  • Web browsers and apps with the web-browser entitlement "are not allowed to register universal links".

Step 2: write the AASA file

Create a file named apple-app-site-association, with no extension:

{
  "applinks": {
    "details": [
      {
        "appIDs": ["ABCDE12345.com.example.app"],
        "components": [
          { "/": "/account/*", "exclude": true },
          { "/": "/product/*" },
          { "/": "/u/*" }
        ]
      }
    ]
  }
}
  • App IDs are <Application Identifier Prefix>.<Bundle Identifier>.
  • Rules are checked in order and "the first match wins", so exclusions go first.
  • Use components, not the legacy paths, and don't mix the two.

Check the file you publish with curl -I https://example.com/.well-known/apple-app-site-association and sudo swcutil verify on a Mac.

Step 3: host the file correctly

  • Serve it at https://<domain>/.well-known/apple-app-site-association on every domain in the entitlement.
  • Use HTTPS "with a valid certificate and with no redirects". Apple says 301 and 302 responses are not supported.
  • Allow all regions, IP addresses and user agents, so Apple's CDN can fetch it.
  • Serve it as JSON. Apple's archived guide describes application/json.
  • Keep it under 128 KB uncompressed, the limit in Apple's archived documentation.

Check delivery with curl -v and with Apple's user-agent test, curl -A "MyAgent-Bot/*" https://example.com/.well-known/apple-app-site-association. If the response is a redirect or a 403, Apple's CDN cannot use the file.

Step 4: handle the link in the app

When a universal link opens the app, iOS delivers the URL through an NSUserActivity. Your app reads the URL and routes to the right screen.

  • Parse the path and query and map them to screens.
  • Fall back to a sensible screen for URLs the app does not recognise.
  • Route your own links internally. Apple says if your app uses open methods to open a universal link to your own website, "the link won't open in your app".

Why does a universal link open Safari?

Usually because of how the link was opened, not the file. The three common cases are typed links, same-domain taps and in-app browsers.

  • Typed or pasted into Safari: never treated as a universal link. See typed links.
  • Tapped on your own website: same-domain navigation continues in Safari. Use a separate link domain.
  • Tapped inside a social app: Apple says support is "up to third-party web browsers".
  • User choice: choosing to open a domain in the browser "will set the default behavior for your device".

Step 5: test on a device

Apple's CDN fetches your file within 24 hours, and devices check for updates about once a week after install. While setting up:

  1. Add ?mode=developer to the entitlement, for example applinks:example.com?mode=developer. This bypasses the CDN on development-signed builds.
  2. Turn on Developer Mode, then Settings > Developer > Universal Links > Associated Domains Development.
  3. Use Settings > Developer > Universal Links > Diagnostics to test a URL.
  4. Paste links into Notes, tap them, and long-press to see the app and browser options.
  5. On a Mac, run sudo swcutil verify -d example.com -j apple-app-site-association -u https://example.com/product/1.
  6. For a full picture, capture a sysdiagnose and read swcutil_show.txt. Site/Fmwk Approval: approved means the CDN fetched and matched the file.

Remove ?mode=developer before release. Then repeat the Notes and swcutil tests on a production build.

FAQ

Common questions

Do I need a separate AASA file for www?

Yes, if `www.example.com` is in the entitlement. Apple says each subdomain must serve its own file, and a file on the apex only covers the apex and a `*.` wildcard entry.

How long until universal link changes reach users?

Apple's CDN requests the file within 24 hours, and installed apps check about once a week. There is no CDN invalidation, so reinstall test builds to fetch the latest copy.

Can I test universal links without deploying to my public domain?

Yes. Developer mode (`?mode=developer`) pulls the file directly from your domain, including servers not reachable from the public internet, on development-signed apps on opted-in devices.

What happens if the app is not installed?

The URL opens in the default browser, so the same page should work on the web. To route new users after they install, add [deferred deep linking](/guides/deferred-deep-linking/).

Does a universal link work when typed into the address bar?

No. Apple documents that direct navigation in the address bar is never treated as a universal link. Test by tapping links instead.

What are UTM parameters?

UTM parameters are tags added to the end of a link, such as utm_source and utm_campaign, that tell analytics tools where a visit came from. They let you see which campaign, channel and ad brought each visitor.