Annual Defect Report 2026Download
Blog & Reports
How-to guide7 min read · Team Mobot

How to Test Universal Links on iOS

Test Universal Links in the iOS Simulator and on a real iPhone: xcrun simctl openurl, AASA validation, and fixes when Universal Links aren't working.

Short answer: you can test Universal Links in the iOS Simulator. Install your app on a booted simulator, then run xcrun simctl openurl booted "https://example.com/path". The Simulator can send https:// links to Safari, or show an "Open in app?" prompt, even when the association works, so treat it as a routing check and confirm on a real iPhone. If the link opens Safari on a real iPhone, it isn't working. Check three things in order: your app has the applinks: Associated Domains entitlement for that exact host, your apple-app-site-association (AASA) file is served over https:// at /.well-known/ with no redirects, and the path matches your components rules. Then repeat the test on a real iPhone by tapping the link in Messages, Mail or Notes.

  1. Build and run your app on a simulated iPhone so the app is installed and the simulator is booted.
  2. In Terminal, open the link on the booted simulator:

xcrun simctl openurl booted "https://example.com/buy/42"

simctl is Apple's command-line tool for simulated devices. Run xcrun simctl help to list its subcommands (Apple: Interacting with devices using the command line). Usage is xcrun simctl openurl <device> <URL>, where <device> is a simulator UDID or booted. On the Simulator, results for https:// links are inconsistent. Some developers see the app open; others see Safari, sometimes with an "Open in app?" prompt, even when Associated Domains and the AASA file are correct. Apple doesn't document this behaviour. So check routing with your custom URL scheme, for example xcrun simctl openurl booted "myapp://buy/42", and confirm true Universal Link behaviour on a real iPhone. 3. Check the result: - The app opens to the right screen. The association works and your routing works. - Safari opens, or an "Open in app?" prompt appears. On the Simulator this can happen even when the association works. Test the same link on a real iPhone; if Safari opens there, the link isn't working. See the next section. - The app opens to the wrong screen. The association works, but your routing code is wrong. 4. Run the same URL list with the app not running and with it in the background. Those are two different code paths (see "How do I set up the app side?" below). 5. You can also paste the link into Notes on the simulator and tap it. Apple's own test method is to long-press the link in Notes and check that both "open in app" and "open in browser" options appear (Apple TN3155: Debugging universal links).

Testing against a staging server. If your AASA file is on a server Apple's CDN can't reach, add an alternate mode to the entitlement: applinks:staging.example.com?mode=developer. Apple suggests this mode when you run the app from Xcode or change the file faster than the CDN caches it (Apple: Associated Domains entitlement; TN3155). Remove it before you release.

Apple's debugging technote (TN3155) and the associated domains docs cover the common causes:

Symptom Likely cause Fix
Safari opens every time No AASA file on that exact host, or a mismatch between applinks: and the host Each subdomain in applinks: needs its own AASA file. applinks:example.com doesn't cover www.example.com.
Safari opens every time AASA response is a 301 or 302 redirect, or a 403 or 404 Serve the file directly on every domain, to every IP address and user agent
Works on one device, not another Someone chose "open in browser" for that domain Long-press the link in Notes and choose the app option. That choice becomes the device's default.
Typed into Safari's address bar, app doesn't open By design: direct navigation in the browser never opens the app Test from Notes or Messages on a real iPhone
Tapped on your own site, stays in Safari Same-domain links continue in the browser Use a different subdomain for links that should open the app
Fixed the server, still broken The device still has the old file from Apple's CDN Reinstall the app, or use ?mode=developer while testing. There's no CDN invalidation.
Domain has a port applinks:example.com:8080 isn't supported Remove the port
Some paths fail Path excluded or not matched in components, or old and new AASA formats mixed Use one format. Test with swcutil verify (below).
App opens, wrong screen Routing bug, often cold start vs. warm start Test both scene entry points

Web browsers decide for themselves whether to support Universal Links, and support may vary in third-party browsers.

How do I check my AASA file?

Run these checks from a Mac instead of relying on an online AASA validator. All of them come from Apple TN3155.

  1. Fetch it and read the headers:

curl -v https://example.com/.well-known/apple-app-site-association

You want a 200 with JSON and no 301 or 302. Repeat with a random user agent (curl -A "MyAgent-Bot/*" …), because your server should accept any user agent.

  1. Download it the way the system does, then check it against a URL:

sudo swcutil dl -d example.com sudo swcutil verify -d example.com -j ./example.json -u https://example.com/buy/42

A matching path returns Pattern "…" matched. An excluded path returns blocked match.

  1. Check the format. Use appIDs (<Team ID>.<bundle ID>) with a components array. Don't mix it with the older appID and paths format (Apple: Supporting associated domains):
{
  "applinks": {
    "details": [
      {
        "appIDs": ["ABCDE12345.com.example.app"],
        "components": [
          { "#": "no_universal_links", "exclude": true },
          { "/": "/buy/*" },
          { "/": "/help/website/*", "exclude": true },
          { "/": "/help/*", "?": { "articleNumber": "????" } }
        ]
      }
    ]
  }
}

Put exclude rules before the broader patterns they carve out, as Apple's example does.

  1. On a real iPhone, turn on Developer Mode, go to Settings > Developer, turn on Associated Domains Development under Universal Links, then open Diagnostics and enter the full URL. It reports whether the link is valid for an installed app.

  2. Still stuck? Take a sysdiagnose on the device and open swcutil_show.txt. Find your App ID. Site/Fmwk Approval: approved means Apple's CDN approved your file. User Approval shows the person's app-or-browser choice.

Apple's CDN fetches the AASA file when the app is installed. Devices check for updates about once a week after that, and reinstalling the app gets the newest copy.

How do I set up the app side?

  1. Add the Associated Domains capability under Signing & Capabilities. Then add applinks:example.com. Include only the host, with no path, no query and no trailing slash. A *. prefix matches subdomains.
  2. Handle the incoming NSUserActivity with activityType == NSUserActivityTypeBrowsingWeb and read webpageURL (Apple: Supporting universal links in your app).
  3. If your app uses scenes, handle both entry points. When the app isn't running, the link arrives in scene(_:willConnectTo:options:) through connectionOptions.userActivities. When the app is running or suspended, it arrives in scene(_:continue:). These are two separate test cases.
  4. Validate every parameter and reject malformed URLs. Apple says to include improperly formatted URLs in your test cases.

The Simulator covers routing. Confirm the association and real taps on a real iPhone. A real iPhone covers how people actually tap links:

Source app App state Expected
Messages Not running (cold start) App opens to the deep-linked screen
Mail Backgrounded App resumes to the deep-linked screen
Notes Logged out Login, then continue to the target screen
Third-party app (chat or social) Installed App opens, or the link stays in that app's in-app browser. Record which.
Any App not installed Website handles the URL
Any Excluded path Website handles the URL

Run the matrix on more than one iPhone model and iOS version, including iOS 27.

Custom URL schemes such as myapp://item/42 need no website and no association. They also have no website fallback, and Apple notes that other apps can register the same scheme. Apple recommends Universal Links over custom schemes for this reason (Apple: Defining a custom URL scheme for your app). If you keep a scheme for backward compatibility, test it separately.

Android counterpart: Android App Links use android:autoVerify="true" and a /.well-known/assetlinks.json file. You can check verification state with adb shell pm get-app-links (Android: Verify App Links). See our Android deep links guide.

Mobot runs your link tests on real iPhones and Android phones, tapped by physical robots, so the link is opened from Messages, Mail and other apps the way a person would open it. Mobot AI and Mobot's team build your test cases from your link list and the screens each link should land on. When a link opens the wrong place, the defect report includes device screenshots of what happened.

FAQ

Can you test Universal Links in the iOS Simulator? Yes. Install your app on a booted simulator and run xcrun simctl openurl booted "<your URL>". The Simulator may open https:// links in Safari or show an "Open in app?" prompt even when the association works, so confirm on a real iPhone by tapping the link from Messages or Mail.

Why are Universal Links not working? The usual causes are a missing or redirected AASA file on that exact host, a mismatch between the applinks: entitlement and the domain, a path that isn't matched in components, or a device where someone chose to open that domain in the browser.

How do I check my AASA file? Run curl -v against https://<domain>/.well-known/apple-app-site-association and check for a 200 with no redirect. Then use sudo swcutil dl -d <domain> and sudo swcutil verify on a Mac to test specific URLs against the file.

What is the difference between Universal Links and custom URL schemes? Universal Links are verified HTTPS links that fall back to your website. Custom schemes are not verified, have no website fallback, and other apps can register the same scheme.

Test your Universal Links on real iPhones.

Start free trial (1,000 credits)or talk to sales →
How-to

See What Your Emulators Are Missing

Get a real, verified defect report from Mobot’s robots and QA analysts — on your app, on real devices.

or talk to sales