Why your Universal Links open Safari instead of your app.
Paste your domain. We fetch /.well-known/apple-app-site-association server-side and run every check iOS does — HTTPS, no-redirect, Content-Type, JSON validity, appID format, paths/components — plus the exact fix when one fails.
Server-side fetch (no CORS issues). No signup. We don't log your domains.
What's an AASA file? (read this if your Universal Links won't open the app)
apple-app-site-association (AASA) is the JSON file iOS uses to decide whether to open your app or Safari when someone taps a link on your domain. It lives at https://yourdomain.com/.well-known/apple-app-site-association, contains your app's bundle identifier and the URL paths your app handles, and Apple downloads it the first time the device sees your app or domain.
Five things have to be exactly right:
- HTTPS only — Apple rejects HTTP outright
- No redirects — since iOS 11, Apple does NOT follow 301/302; the file must be at the exact path
- Content-Type — should be
application/json, nottext/html - Valid JSON — strict, no trailing commas, no comments
- appID format — must be
TEAMID.bundle.id(10-char Team ID + dot + bundle ID)
Miss any one of these and Universal Links silently fall back to Safari. There's no error in the console, no UI hint, nothing in the system logs unless you know to check Console.app for swcd messages. That's why this tool exists.
For deeper debugging tactics, see the Field Notes on real iOS dev practice.
Universal Links FAQ
Quick answers to the questions every iOS dev hits when Universal Links don't behave.
Why do my Universal Links open Safari instead of my app?
Almost always one of: the AASA file isn't served over HTTPS, the server returns a redirect (Apple doesn't follow them since iOS 11), Content-Type is text/html instead of application/json, the appID has a typo (must be TEAMID.bundle.id), or your path patterns don't match. This validator catches all five.
Where exactly should the AASA file live?
Apple checks /.well-known/apple-app-site-association first (preferred since iOS 13). The legacy /apple-app-site-association still works but is deprecated. Both must be HTTPS, status 200, no redirects, no auth.
How do I find my Team ID for the appID?
Apple Developer Portal → Account → Membership → "Team ID" (10-character uppercase string). Combine with your bundle ID: ABCD123456.com.example.myapp.
paths vs components — which should I use?
paths is the legacy format (iOS 9-12) — flat array of patterns with limited wildcards. components (iOS 13+) is modern — array of objects with finer control over path, query string, fragment, and exclusion. Both work; components is better. This tool flags legacy paths as a warning, not an error.
I changed my AASA but iOS still uses the old version. Why?
iOS aggressively caches AASA files. To force a refresh during development: delete the app, reinstall, OR use the new apple-app-site-association SwiftUI debug entitlement. In production, Apple's swcd daemon refreshes the file on its own schedule (~once per device per day for active apps).
Does this send my domain anywhere?
We fetch your AASA file server-side from a Cloudflare Pages Function (browsers can't fetch it directly because AASA files don't send CORS headers). Your domain isn't logged. The validation result isn't stored. Each check runs fresh. The User-Agent we use identifies our validator to your server logs (NativeFirst-AASA-Validator/1.0) so it's clear who hit your endpoint.
Privacy Manifest Generator
While you're fixing iOS plumbing — generate a valid PrivacyInfo.xcprivacy in 30 seconds. Skip the ITMS-91056 App Review bounce.
ThinkBud — turn anything into mind maps + flashcards
We make ThinkBud — drop any link, PDF, or recording, get mind maps, FSRS-5 flashcards, AI podcasts. The energy behind these tools comes from shipping it.