Universal Links require your app to declare exactly which domains it has permission to handle. That declaration lives in the Associated Domains entitlement, a small but critical piece of configuration inside your Xcode project. Get it wrong and iOS will silently ignore your links, routing users to Safari instead of your app every time.
This guide covers the full setup process: enabling the capability, understanding the entitlements file format, handling subdomains, using development mode for local testing, and tracking down the common errors that catch developers off guard. For the broader context on how Universal Links work end to end, see our Universal Links overview.
What the Associated Domains Entitlement Does
When iOS opens a URL, it checks whether any installed app has claimed that domain. The check happens at install time and on a periodic refresh. iOS fetches the Apple App Site Association (AASA) file from your server at https://yourdomain.com/.well-known/apple-app-site-association and compares the app identifiers listed there against the apps installed on the device. Our AASA file setup guide covers the file format, path matching rules, and serving requirements in detail.
The associated domains entitlement is how your app tells iOS: "I want to be considered as a candidate for these domains." Without the entitlement, iOS will never even check your AASA file for that app.
The entitlement is a list of service-domain strings. Each string combines a service type prefix with a domain:
applinks:for Universal Linkswebcredentials:for Password AutoFill and Sign in with Appleactivitycontinuation:for Handoff
For deep linking purposes you will primarily use applinks:, though you can declare multiple service types in the same entitlement.
Enabling the Capability in Xcode
Open your project in Xcode (15 or later). The steps are the same across recent versions. For a broader look at all the Xcode settings involved in Universal Links (not just entitlements), see our Xcode Universal Links configuration guide.
Step 1. In the Project Navigator on the left, click your project file (the top item with the blue icon).
Step 2. In the main editor area, select your app target from the targets list. Make sure you have the correct target selected if your project has multiple targets (for example, a watch extension or notification service extension).
Step 3. Click the "Signing & Capabilities" tab.
Step 4. Click the "+ Capability" button in the top-left corner of the capabilities list. A sheet slides down with a searchable list of available capabilities.
Step 5. Type "Associated Domains" in the search field and double-click it (or press Return) to add it to your target.
You will now see an Associated Domains section on the Signing & Capabilities tab with an empty list and a "+" button to add domain entries.
Step 6. Click "+" and type your first domain entry. The format is applinks:yourdomain.com. Press Return to confirm.
Repeat step 6 for each domain you want your app to handle. You can add as many entries as you need.
The Entitlements File
When you add the Associated Domains capability, Xcode creates (or updates) a .entitlements file in your project directory. The file is a standard Apple property list. Here is what it looks like for a typical Universal Links setup:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:tolinku.com</string>
<string>applinks:app.tolinku.com</string>
</array>
</dict>
</plist>
You can edit this file directly in a text editor or through Xcode's Signing & Capabilities UI. Both approaches are equivalent. If you manage entitlements manually (common in CI/CD pipelines), make sure this file is referenced correctly in your build settings under CODE_SIGN_ENTITLEMENTS.
Adding Subdomains
The applinks: prefix supports two ways to cover subdomains.
To claim a specific subdomain, list it explicitly:
applinks:go.example.com
applinks:app.example.com
To claim all subdomains with a single entry, prefix the domain with *.:
applinks:*.example.com
The wildcard form covers one level of subdomains only. It will match go.example.com and app.example.com, but not deep.go.example.com. If you need multiple levels, you have to add entries for each level explicitly.
Note that the wildcard entry does not cover the bare domain itself (example.com). If you want both, add two entries: applinks:*.example.com and applinks:example.com.
Specifying Path Components (iOS 15.1+)
Starting with iOS 15.1, you can scope an applinks: entry to specific paths directly in the entitlement:
applinks:example.com/products/
This is a newer feature and most production setups still rely on the AASA file for path-level routing. For broad Universal Links coverage, listing the domain without a path suffix is the simpler and more compatible approach.
Development Mode
By default, iOS caches the AASA file aggressively. This is useful in production but painful during development: you change your AASA file, build your app, install it on a device, and nothing happens because iOS is still using the cached version.
Development mode solves this. Append ?mode=developer to your entitlement entry:
applinks:example.com?mode=developer
With this flag, iOS bypasses the CDN cache and fetches the AASA file directly from your server every time the app is launched from Xcode. It also uses your device's DNS rather than Apple's CDN, which is essential when your server is running on localhost or an internal network address.
Development mode only activates when the app is run from Xcode with a development-signed build. It has no effect on App Store or TestFlight builds. You can leave the ?mode=developer suffix in your entitlements file during active development and remove it before submitting to the App Store, though Apple's review process will not reject it if you leave it in.
Finding Your Team ID and Bundle ID
The AASA file on your server must reference your app using the format TEAMID.BUNDLEID. Both identifiers need to match exactly what is configured in your Xcode project.
Team ID
Your Team ID is a 10-character alphanumeric string assigned by Apple when you enrolled in the Apple Developer Program.
To find it:
- Go to developer.apple.com and sign in.
- Click your name or account in the top-right corner.
- Your Team ID is listed under "Membership details."
Alternatively, in Xcode, open the Signing & Capabilities tab for your target and click the "team" dropdown. Hover over the team name and the Team ID is shown in a tooltip, or you can find it in the provisioning profile details.
Bundle ID
Your Bundle ID is set in your Xcode project. Open the target's General tab and look in the Identity section. It typically follows the format com.yourcompany.appname.
The combined app identifier you put in your AASA file looks like this:
{
"applinks": {
"apps": [],
"details": [
{
"appIDs": ["A1B2C3D4E5.com.yourcompany.appname"],
"components": [
{ "/": "/products/*" },
{ "/": "/account/*" }
]
}
]
}
}
Make sure this string matches exactly. A mismatch between the AASA file and what iOS derives from your provisioning profile is one of the most common causes of Universal Links failing silently. If you use Tolinku to manage your AASA file, the dashboard handles this association for you and validates the format before publishing.
Provisioning Profile Requirements
The Associated Domains entitlement must be reflected in your provisioning profile. If you use automatic signing in Xcode, this happens transparently: Xcode registers the entitlement with Apple and generates a new provisioning profile that includes it.
If you use manual signing (common in team environments and CI pipelines), you need to:
- Log in to the Apple Developer portal.
- Select your App ID under Identifiers.
- Enable the "Associated Domains" capability in the App ID's capability list.
- Regenerate any provisioning profiles that use this App ID. The old profiles will no longer include the entitlement.
- Download and install the new profiles in Xcode.
If you forget to regenerate the profiles, Xcode will usually warn you during building with a message about entitlement mismatches, but not always. When in doubt, regenerate.
Common Errors and How to Fix Them
"The entitlement is not supported in the provisioning profile"
This means your provisioning profile does not include the Associated Domains capability. The fix is to enable Associated Domains in your App ID on the developer portal and regenerate the provisioning profile as described above.
Universal Links open in Safari instead of the app
This is the most common symptom of a misconfiguration and can have several causes:
- The domain entry in your entitlement does not match the domain in your URL. Check for typos and confirm whether you need
www.or a specific subdomain. - The AASA file on your server is unreachable or returns a non-200 status. Use Apple's AASA validation tool or a direct curl to verify.
- The AASA file format is invalid JSON, or the
appIDsarray uses the wrong Team ID or Bundle ID. - The entitlement file is not being included in the build. Check
CODE_SIGN_ENTITLEMENTSin your build settings.
"Associated Domains Entitlement Mismatch"
This Xcode warning appears during archiving or exporting when the entitlements in your built binary do not match the provisioning profile. It usually means you edited the entitlements file manually or added the capability after generating the profile. Regenerate your provisioning profile on the developer portal.
The app handles some Universal Links but not others
Path-level filtering in the AASA file can cause this. If your AASA file only covers /products/* and you test a link at /checkout/, iOS will not route it to the app. Review your AASA file's components (or paths in the older format) and ensure all intended paths are covered.
Debugging Tips
Use Console.app during testing. Connect your device, open Console.app on your Mac, filter for your app's bundle ID, and look for entries from swcd (the system process that manages AASA fetching). It logs fetch attempts, cache hits, and validation failures.
Check the AASA fetch directly. The URL iOS uses is https://yourdomain.com/.well-known/apple-app-site-association. Make sure it serves valid JSON with the correct Content-Type: application/json header. No redirects: Apple's CDN follows one redirect but the direct fetch from a device does not always do the same.
Use ?mode=developer consistently during development. Without it, you may be testing against a cached AASA file that does not reflect your latest changes. For a complete testing checklist, see our guide on testing Universal Links.
Validate with the WWDC-recommended approach. After installing a new build, open a Universal Link URL from Notes or Safari rather than from the same app. iOS's link handling logic behaves differently when the source and destination are the same app.
For a complete reference on the AASA file structure that pairs with these entitlement settings, see the Tolinku Universal Links documentation and the iOS configuration guide. Apple's canonical reference is the Supporting Associated Domains article in the Xcode documentation.
The Associated Domains entitlement is small, but it is the gatekeeper for everything Universal Links does in your app. Getting the capability enabled, the entitlements file correct, and the provisioning profile updated are the prerequisites for any of the routing logic on your server to matter. Once these pieces are in place, the actual link handling becomes straightforward.
Get deep linking tips in your inbox
One email per week. No spam.