Free Tool

Free iOS Universal Link Validator

Validate apple-app-site-association files and iOS Universal Links. Check JSON syntax, content type, app-ID format, paths and components, and per-detail rules. Free, instant, no signup.

Fetches /.well-known/apple-app-site-association (modern) and falls back to /apple-app-site-association at root (legacy iOS 9-12). Cached 5 min.

No signup required
Free forever
GDPR compliant
Powered by U2L

Quick Answer

An iOS Universal Link validator fetches and deep-validates the apple-app-site-association (AASA) file at /.well-known/ on a domain. The U2L Universal Link Validator checks JSON syntax, Apple's required Content-Type header, appID format (TEAMID.bundle.id), per-detail structure (modern components vs legacy paths), and surfaces every issue with severity grading - error / warning / info.

Quick Facts

  • Fetches https://{domain}/.well-known/apple-app-site-association (modern) and https://{domain}/apple-app-site-association (legacy iOS 9-12 fallback).
  • Apple does NOT follow redirects when fetching AASA. The file must serve directly with 200 OK and Content-Type: application/json.
  • JWT signing is no longer required (since iOS 14, 2020). AASA is now plain JSON.
  • Validates appID format: TEAMID.bundle.id (10-char team prefix + reverse-DNS bundle). Malformed appIDs are silently rejected by Apple.
  • Modern format (iOS 13+): appIDs array + components with case-sensitivity, percent-encoding, and exclude rules. Legacy format: appID + paths array.
  • Cached at the U2L edge for 5 minutes. Repeat checks on the same domain return instantly.
  • For Android App Links validation alongside iOS, see /tools/deep-link-tester (cross-platform view).

How to validate an AASA file

One step. Domain in, AASA validation out.

  1. 1

    Enter your domain

    The validator checks https://{domain}/.well-known/apple-app-site-association first, then falls back to /apple-app-site-association at root (legacy path). Most modern setups use /.well-known/.

  2. 2

    Read the validation panel

    URL fetched, status, Content-Type, declared appIDs, path / component count, and a severity-graded issue list. Errors will break Universal Links; warnings are best-practice gaps.

  3. 3

    Inspect raw AASA JSON

    Expand the raw JSON for field-level deep dive. Useful when the validator's structured analysis isn't enough.

What is a iOS Universal Link Validator?

iOS Universal Link Validator is a tool that fetches and deep-validates the apple-app-site-association (AASA) file for a domain. AASA is the JSON config Apple uses to determine which iOS app handles which URLs on your domain. Tapping a https://example.com link on iPhone opens your app instead of Safari - if the AASA is correctly configured. Misconfigurations silently fall back to opening the browser, which is a frustrating user experience and a tough bug to track down.

AASA evolved across iOS versions. iOS 9-12 expected the file at the root (https://example.com/apple-app-site-association) and required JWT signing. iOS 13+ added support for /.well-known/ path and the modern 'components' format with richer path-matching rules. iOS 14+ removed the JWT requirement; AASA is now plain JSON. Modern deployments use /.well-known/ with the components format; legacy fallbacks at root remain for old iOS versions.

The validation here goes deeper than the cross-platform Deep Link Tester (/tools/deep-link-tester). Beyond format checks, this validator surfaces iOS-specific gotchas: Apple's strict Content-Type requirement (must be application/json), no-redirects rule (Apple doesn't follow 301/302 to fetch AASA), TEAMID prefix format (10 alphanumeric uppercase chars), and the modern-vs-legacy format distinction.

Common pitfalls caught by the validator: Cloudflare / Vercel serving AASA as text/plain instead of application/json (silently breaks Apple's parser), missing TEAMID prefix in appIDs (10-char team prefix is required), JSON syntax errors from CMS templating (trailing commas), and AASA served from a redirect rather than directly (Apple won't follow). Each is graded by severity and surfaced with actionable guidance.

How does a iOS Universal Link Validator work?

When you submit a domain, the U2L API runs two parallel fetches: AASA at /.well-known/apple-app-site-association (modern, preferred) and AASA at /apple-app-site-association (legacy iOS 9-12 fallback). Each fetch has a 6-second timeout. The first one found is used; if both return content, .well-known/ wins.

For the AASA file, the validator parses the JSON and validates structure. Required: applinks.details array. Each detail must have appIDs (modern, iOS 13+) or appID (legacy); appIDs must match TEAMID.bundle.id format (10-char team prefix + reverse-DNS bundle). Either paths (legacy) or components (modern) must be defined.

Beyond structure, the validator checks: Content-Type header (Apple requires application/json), file size (Apple's 128 KB hard limit), redirect status (Apple doesn't follow redirects). It also surfaces all declared appIDs and counts paths / components for quick capacity check.

Issues are graded by severity: error (Universal Links will fail), warning (works but suboptimal or fragile), info (advisory). The raw AASA JSON is expandable for field-level deep dive.

Use Cases

How marketers, businesses, and developers use ios universal link validator.

Pre-launch iOS app deep-link QA

Before submitting your app to App Store, run the validator against your production domain. Catch AASA misconfigs before they hit users.

'Universal Links not working' debugging

User reports tapping your link opens Safari instead of the app. Validator confirms whether AASA is accessible and parseable - usually the fix is here.

Multi-team AASA verification

Domain hosting AASA for multiple iOS apps (work + personal apps from different teams). Validator surfaces all declared appIDs in one view.

iOS 14+ migration off JWT signing

Migrating from old JWT-signed AASA to modern plain JSON. Validator confirms the new file is correctly formatted before flipping the DNS / CDN.

Modern components migration

Upgrading legacy 'paths' to modern 'components' (iOS 13+) for richer path matching. Validator confirms the new format is structurally valid.

CDN config validation

After moving CDN providers, AASA may serve different headers or cache differently. Validator catches Content-Type regressions and other CDN-introduced issues.

Periodic deep-link health check

Quarterly checks on production AASA. CDN cache changes, JSON format drift, content-type regressions all happen silently; periodic checks catch them.

Multi-domain Universal Link strategy

App handling URLs on multiple domains (example.com + example.io + cdn.example.com). Validate each domain's AASA separately.

Compliance / security audit evidence

SOC 2 / ISO audits checking mobile-app security configs. AASA validity is publicly verifiable evidence (no app-internal access required).

Cross-team handoff verification

Frontend / DevOps team configures AASA; iOS team verifies. Validator gives both teams a shared view of the config without app-side debugging.

iOS Universal Link Validator vs Alternatives

Side-by-side feature and pricing comparison with the top alternatives.

FeatureU2LApple's aasa-validator (CLI)Branch.io testerManual curl + jq
Free, no signupmacOS installAccount
Browser-only
Fetches /.well-known/ + legacy rootManual
Validates Content-TypeManual
Validates appID formatLimitedManual
Severity-graded issuesLimited
Edge-cached responses5 min
Cross-platform (Android too)Companion toolManual

iOS Universal Link Validator vs Apple's aasa-validator CLI

Apple ships a command-line aasa-validator on macOS. Free, official, deeper iOS-specific validation including JWT signature checks (legacy iOS 9-13).

U2L's web validator is browser-only - no install, works from any platform. For iOS 14+ deployments where JWT is no longer needed, U2L covers all common validation needs. For deep iOS 9-13 JWT-era debugging, Apple's CLI remains useful.

iOS Universal Link Validator vs Branch.io's deep-link diagnostic

Branch.io is the enterprise deep-linking platform. Their diagnostic includes AASA / assetlinks validation plus deferred-deep-linking testing, attribution debugging, and full deep-link analytics. Free tier; paid tiers $99-$2000+/mo.

U2L's validator is a focused, free subset: just AASA validation. For full deep-linking platforms with attribution, Branch wins. For 'is my AASA valid?', U2L is enough.

Best Practices

Host AASA at /.well-known/, not legacy root

Modern iOS prefers https://example.com/.well-known/apple-app-site-association. Keep root path (/apple-app-site-association) as fallback for iOS 9-12 if your audience still includes them.

Set Content-Type: application/json explicitly

Apple's parser requires application/json. CDNs / static-file servers often default to text/plain or application/octet-stream. Configure the Content-Type explicitly in your server / CDN config.

Use modern 'components' format (iOS 13+)

Components support case-sensitivity, percent-encoding, query / fragment matching, and exclude rules - much richer than legacy paths. Use components for new deployments; keep paths only for backward compat with iOS 9-12.

Don't serve AASA from a redirect

Apple does NOT follow redirects when fetching AASA. The file must serve directly with 200 OK. If your CDN redirects (HTTP to HTTPS, www to non-www), make sure the AASA URL itself is on the canonical destination, not the redirect source.

Verify TEAMID prefix in every appID

ABCDE12345.com.example.app is correct. com.example.app alone is wrong - Apple silently rejects. Find your team ID in Apple Developer account > Membership.

Test on a real device after deploy

Validation passing is necessary but not sufficient. Tap an actual deep link on a real iPhone (uninstall and reinstall the app first to refresh Apple's AASA cache).

Keep AASA under 100 KB

Apple's hard limit is 128 KB. Don't bloat with unnecessary path entries. Use exclude rules in components to avoid listing every URL exhaustively.

Re-validate after CDN / hosting changes

Migrating CDNs (Cloudflare to Fastly, Vercel to Netlify) can change cache headers or content-type. Re-run the validator after every infra change.

Common Mistakes to Avoid

Serving AASA as text/plain

CDN default Content-Type is often text/plain or application/octet-stream. Apple's parser requires application/json. Silent failure - the file fetches but doesn't parse.

Missing TEAMID prefix in appID

Writing 'com.example.app' without the 10-char team prefix. Apple silently rejects. Always include the full TEAMID.bundle.id form.

JSON syntax errors from CMS templating

Trailing commas, single quotes, unescaped strings - all break JSON parsing. Apple rejects the entire file. Validate JSON before deploying; the U2L validator catches parse errors.

AASA served from a redirect

Apple does NOT follow redirects. If your AASA URL 301s to a different URL, Apple sees the redirect status and gives up. Serve AASA directly with 200 OK at both /.well-known/ and root.

Mixing modern and legacy formats incorrectly

appIDs (modern array) and appID (legacy single string) can coexist in one detail entry but it's confusing. Pick one format consistently within each detail entry; mix only if you need iOS 9-12 compat.

Forgetting to deploy AASA on subdomains

If your app handles m.example.com URLs, AASA must be hosted at m.example.com - the apex domain's AASA doesn't apply. Each subdomain handling deep links needs its own AASA file.

Trusting CDN cache to update on deploy

Cloudflare / Fastly cache AASA aggressively. After deploying changes, force-purge the AASA URL from cache; re-validate to confirm the new file is live globally.

Technical Specifications

Modern pathhttps://{domain}/.well-known/apple-app-site-association
Legacy pathhttps://{domain}/apple-app-site-association (iOS 9-12 fallback)
Required Content-Typeapplication/json
AASA appID formatTEAMID.bundle.id (10-char team prefix + reverse-DNS bundle)
Modern format (iOS 13+)applinks.details[].appIDs array + components array
Legacy format (iOS 9-12)applinks.details[].appID string + paths array
Apple file-size limit128 KB
JWT signingNo longer required since iOS 14 (2020)
Cache TTL5 minutes at the Cloudflare edge
Companion tool/tools/deep-link-tester for cross-platform iOS + Android view

Industry-Specific Use Cases

iOS app developers

Pre-launch AASA QA, post-deploy verification, debugging Universal-Link failure reports.

Mobile-first product teams

Marketing email campaigns linking to in-app screens. AASA validity is the foundation of these campaigns.

DevOps and SRE

Post-deploy AASA verification. CDN config validation. Ensures infra changes don't break Universal Links silently.

Mobile QA and test engineering

Pre-release AASA smoke tests. Combined with on-device testing for full coverage.

Multi-app / multi-team domains

Companies with multiple iOS apps sharing a domain need all teams' prefixes in AASA. Validator surfaces all in one view.

App Store reviewers and certification

Pre-submission AASA validation reduces App Store review feedback related to deep-link config issues.

Frequently Asked Questions

What's apple-app-site-association?

AASA is the JSON config file Apple uses to map URLs to iOS apps. Tapping a https://example.com link on iPhone opens your app (instead of Safari) if the AASA correctly declares your app. Located at /.well-known/apple-app-site-association on the domain.

Where should I host the AASA file?

Modern: https://{domain}/.well-known/apple-app-site-association (preferred for iOS 13+). Legacy: https://{domain}/apple-app-site-association at root (iOS 9-12 fallback). Most deployments host both for max compatibility.

Does AASA still need JWT signing?

No. JWT signing was required for iOS 9-13 but removed in iOS 14 (2020). New deployments should use plain JSON. Older guides may still mention JWT; ignore that for current iOS versions.

What's the appID format?

TEAMID.bundle.id - 10-character Apple team identifier + dot + reverse-DNS bundle ID. Example: ABCDE12345.com.example.app. The team ID is in your Apple Developer account; the bundle ID is in your Xcode project's General settings.

Why does Apple require Content-Type: application/json?

Apple's AASA parser is strict about content type. Files served with text/plain, text/html, or application/octet-stream are rejected silently. Configure your server / CDN to set application/json explicitly for the AASA URL.

What's the modern 'components' format?

iOS 13+ added components - a richer path-matching format with case-sensitivity flags, percent-encoding controls, query / fragment matching, and exclude rules. Replaces legacy 'paths' arrays for new deployments. Both can coexist for backward compat.

Why does Apple not follow redirects when fetching AASA?

Security - prevents man-in-the-middle attacks where an attacker controls the redirect target. AASA must serve directly with 200 OK at the canonical URL. If your CDN redirects HTTP to HTTPS, ensure the AASA fetch goes to the HTTPS variant directly.

What if AASA is invalid?

Apple silently falls back to opening the URL in Safari. Users tap your link, get the website, never see your app. Hard to debug from the app side; the AASA validator surfaces issues at the config level.

Does the validator run actual deep-link taps?

No - it only validates the config file. To verify actual deep-link behavior, install your app on a real iPhone and tap a matching URL. Re-installing the app forces Apple to re-fetch AASA from your domain.

Why doesn't my AASA work even when validation passes?

Several other failure modes: app's Associated Domains entitlement missing, app not signed with the right team, AASA cached on the device from before deploy. Most issues are app-side config, not AASA-side. Uninstall + reinstall the app to refresh.

Does the validator support multiple domains?

Tests one domain at a time. For apps handling URLs on multiple domains, run the validator separately for each. The U2L API can be hit programmatically (1 req/sec recommended).

What's the difference vs /tools/deep-link-tester?

Deep Link Tester: cross-platform iOS + Android view. Universal Link Validator: iOS-only deeper analysis with iOS-specific gotchas (TEAMID format, no-redirects rule, modern vs legacy format). Same backend; different rendering depth.

Can I validate staging / dev environments?

Only public domains. Internal staging URLs (staging.internal, *.local) are blocked by SSRF protection. Use Apple's local CLI validator (aasa-validator) or curl from inside your network for private domains.

Is there an API I can call programmatically?

Yes. GET https://u2l.ai/api/tools/deep-link-validator?domain=example.com returns JSON with both iOS and Android results. Cached 5 min. No auth required. Be polite - 1 request per second per domain.

What's the file-size limit?

Apple's documented hard limit is 128 KB. Most AASA files are 1-10 KB; you'd need hundreds of path entries to approach the limit. Use exclude rules in components to avoid bloat.

How often does Apple re-fetch AASA?

On app install initially, then periodically (hours to days). Changes to your AASA take effect with delay; budget for this in deploy planning. To force a re-fetch on a specific device, uninstall and reinstall the app.

What if my AASA varies by region?

Apple may fetch from a US-based CDN POP; the validator fetches from Cloudflare. If your AASA varies geographically, you may see different validation than what Apple sees. Check from multiple regions if region-specific configs are critical.

Should I use 'paths' or 'components'?

Components for iOS 13+ (richer matching). Paths for iOS 9-12 fallback only. New deployments should use components exclusively unless you need to support very old iOS versions.

Key Terms

AASA
apple-app-site-association. The JSON config file declaring which iOS app IDs handle which URL paths on a domain. Located at /.well-known/apple-app-site-association.
Universal Links
iOS mechanism for tapping a https:// URL to open the app instead of Safari. Requires AASA file hosted on the domain plus Associated Domains entitlement in the app.
Team ID
Apple's 10-character identifier for your developer team. Found in your Apple Developer account > Membership. Required as the prefix in AASA appIDs (TEAMID.bundle.id).
Bundle ID
iOS app's unique identifier in reverse-DNS format (com.example.app). Set in Xcode project's General settings. Combined with Team ID forms the full appID for AASA.
Components (modern format)
iOS 13+ AASA path-matching format. Richer than legacy paths: supports case-sensitivity, percent-encoding, query / fragment matching, exclude rules.
Paths (legacy format)
iOS 9-12 AASA path-matching format. Simpler than components: just an array of URL patterns with NOT-prefix for excludes. Still works for backward compat.
Associated Domains
iOS app entitlement declaring which domains the app handles via Universal Links. Set in Xcode under Signing & Capabilities. Format: applinks:example.com.
JWT signing
Pre-iOS-14 requirement to sign AASA with a JWT. Removed in iOS 14 (2020). New deployments use plain JSON; legacy JWT-signed AASA still works but is no longer required.

Want continuous AASA monitoring across your domains?

Sign up free for U2L Pro to schedule daily AASA validation, receive alerts when the file regresses, and audit all your apps' Universal Link configs from one dashboard.

Sign up free