App Links & Universal Links Auditor
Pricing
Pay per usage
App Links & Universal Links Auditor
Audit a public domain's Apple App Site Association and Android assetlinks.json files in one API call. Validates Universal Links and App Links configuration, returns per-platform breakdown, readiness score, grade, and recommendations.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Sanskar Jaiswal
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Audits a public domain's Apple App Site Association file (Universal Links) and Android assetlinks.json file (App Links) in one API call. Fetches both well-known files, validates them against the Apple and Google requirements, and returns a per-platform breakdown, a readiness score from 0 to 100, a letter grade, issues, and recommendations as structured JSON.
Use cases
- Mobile app teams verifying domain association files after releases, CMS migrations, and CDN cutovers
- iOS developers validating AASA structure before submitting an app that uses Universal Links
- Android developers validating assetlinks.json statements before enabling App Links verification
- Agency consultants running recurring deep-link posture checks across client domains
- QA pipelines gating deploys on broken or malformed association files
- Web engineering teams confirming association files are served over HTTPS, without redirects, and without signing (no file extension on AASA)
Input
| Field | Type | Default | Description |
|---|---|---|---|
| startUrl | string | (required) | Public domain or base URL to audit. A bare hostname gets the https scheme prepended. Private IP ranges, URL credentials, and non-HTTP schemes are rejected. |
| timeoutSeconds | integer | 10 | Request timeout per file, from 3 to 30 seconds. |
| maxBytes | integer | 131072 | Maximum response body size to download and parse per file, from 1 KB to 512 KB. |
Output
One dataset item per run:
| Field | Type | Description |
|---|---|---|
| inputUrl | string | URL as provided in the input. |
| finalUrl | string | Normalized base URL after validation. |
| https | boolean | Whether the base URL uses HTTPS. |
| ok | boolean | Whether all HTTP requests completed without network errors. |
| checkedAt | string | ISO 8601 timestamp of the check. |
| aasaChecked | boolean | Whether the Apple check ran (always true). |
| aasaFound | boolean | Whether the AASA file was found (200 on the well-known path or the legacy root path). |
| aasaUrl | string | The AASA URL that produced the result. |
| aasaStatus | integer or null | HTTP status of the AASA response. |
| aasaHttps | boolean or null | Whether the AASA file was served over HTTPS. |
| aasaContentType | string or null | Content-Type of the AASA response. |
| aasaJsonValid | boolean or null | Whether the AASA body parsed as JSON. |
| aasaParseError | string or null | JSON parse error for the AASA body, if any. |
| aasaAppCount | integer | Number of entries in the legacy top-level apps array (modern format should use none). |
| aasaDetailCount | integer | Number of entries in applinks.details. |
| aasaApplinksPresent | boolean | Whether the applinks block is present. |
| aasaValidAppIds | integer | Number of validly formatted app IDs in the legacy top-level apps array. |
| aasaInvalidAppIds | array | Invalidly formatted app IDs in the legacy top-level apps array. |
| aasaWebcredentialsCount | integer | Number of apps in the webcredentials block. |
| aasaAppclipsPresent | boolean | Whether a valid appclips block is present. |
| aasaDetails | array | Per-detail analysis: appIDs, invalid appIDs, components, component issues, legacy paths, and per-entry issues. |
| aasaRedirected | boolean | Whether the AASA file was served through a redirect. |
| aasaRedirectIssue | boolean | Whether the redirect is flagged as an issue (iOS may fail association behind redirects). |
| aasaIssues | array | All AASA issues found. |
| assetlinksChecked | boolean | Whether the Android check ran (always true). |
| assetlinksFound | boolean | Whether assetlinks.json was found (200). |
| assetlinksUrl | string | The assetlinks.json URL. |
| assetlinksStatus | integer or null | HTTP status of the assetlinks.json response. |
| assetlinksHttps | boolean or null | Whether assetlinks.json was served over HTTPS. |
| assetlinksContentType | string or null | Content-Type of the assetlinks.json response. |
| assetlinksJsonValid | boolean or null | Whether the assetlinks.json body parsed as JSON. |
| assetlinksParseError | string or null | JSON parse error for the assetlinks.json body, if any. |
| assetlinksTargetCount | integer | Number of statements in assetlinks.json. |
| assetlinksPackageCount | integer | Number of unique valid Android package names across statements. |
| assetlinksPackages | array | The unique valid Android package names. |
| assetlinksValidFingerprints | integer | Number of validly formatted SHA-256 certificate fingerprints. |
| assetlinksInvalidFingerprints | array | Invalidly formatted fingerprints. |
| assetlinksValidRelations | integer | Number of valid delegate_permission relations. |
| assetlinksInvalidRelations | array | Invalidly formatted relations. |
| assetlinksStatements | array | Per-statement analysis: namespace, package, fingerprints, relations, and per-statement issues. |
| assetlinksIssues | array | All assetlinks.json issues found. |
| score | integer | Readiness score from 0 to 100. |
| grade | string | Letter grade from A+ to F. |
| issues | array | Combined issues from both platforms. |
| recommendations | array | Actionable fixes for each platform. |
| error | string or null | Error message when the audit could not complete. |
Example input
{"startUrl": "https://www.wikipedia.org","timeoutSeconds": 10,"maxBytes": 131072}
Example output
{"inputUrl": "https://www.wikipedia.org","finalUrl": "https://www.wikipedia.org/","https": true,"ok": true,"checkedAt": "2026-09-28T09:15:00.000Z","aasaChecked": true,"aasaFound": true,"aasaUrl": "https://www.wikipedia.org/.well-known/apple-app-site-association","aasaStatus": 200,"aasaHttps": true,"aasaContentType": "application/json","aasaJsonValid": true,"aasaParseError": null,"aasaAppCount": 0,"aasaDetailCount": 1,"aasaApplinksPresent": true,"aasaValidAppIds": 0,"aasaInvalidAppIds": [],"aasaWebcredentialsCount": 0,"aasaAppclipsPresent": false,"aasaDetails": [{"index": 0,"appIDs": ["TEAMID123.org.wikipedia.wiki"],"appIDCount": 1,"invalidAppIDs": [],"components": [{ "index": 0, "path": "/*", "issues": [] }],"componentCount": 1,"componentIssues": 0,"paths": [],"issues": []}],"aasaRedirected": false,"aasaRedirectIssue": false,"aasaIssues": [],"assetlinksChecked": true,"assetlinksFound": true,"assetlinksUrl": "https://www.wikipedia.org/.well-known/assetlinks.json","assetlinksStatus": 200,"assetlinksHttps": true,"assetlinksContentType": "application/json","assetlinksJsonValid": true,"assetlinksParseError": null,"assetlinksTargetCount": 1,"assetlinksPackageCount": 1,"assetlinksPackages": ["org.wikipedia.wiki"],"assetlinksValidFingerprints": 1,"assetlinksInvalidFingerprints": [],"assetlinksValidRelations": 1,"assetlinksInvalidRelations": [],"assetlinksStatements": [{"index": 0,"namespace": "android_app","package_name": "org.wikipedia.wiki","sha256Fingerprints": ["AA:BB:...:99"],"fingerprintCount": 1,"relations": ["delegate_permission/common.handle_all_urls"],"issues": []}],"assetlinksIssues": [],"score": 97,"grade": "A+","issues": [],"recommendations": ["Both association files are well-formed. Schedule this audit periodically to catch deploy and CDN regressions."],"error": null}
Security
- Fetches only the three association paths on the audited domain: /.well-known/apple-app-site-association, /apple-app-site-association (legacy fallback), and /.well-known/assetlinks.json
- HTTP and HTTPS only; rejects URL credentials, non-HTTP schemes, private IPv4 and IPv6 literals, and hostnames whose DNS resolves to private IP ranges
- Redirects are revalidated against the SSRF rules before following; at most 3 redirects per file
- Response bodies are capped by the maxBytes input (default 128 KB, hard max 512 KB)
- Does not fetch appIDs, package names, or any URLs referenced inside the association files
- No login, no JavaScript execution, no cookies, no stored page content
Pricing
| Event | Price | Description |
|---|---|---|
| Actor start | $0.005 | Charged once per run. |
| Domain audited | $0.01 | Charged per domain audited (both platforms in one run). |
A typical single-domain audit costs $0.015 per run.
FAQ
Does the actor check both Apple and Android files in one run? Yes. Every run fetches the AASA file (well-known path with legacy root fallback) and assetlinks.json, and returns per-platform results plus a combined score.
Does the actor validate the AASA JSON structure? Yes. It checks the applinks block, apps and details arrays, appID format (TEAMID.bundle.identifier), component shape (the "/" key, exclude, and allowed keys), legacy paths arrays, and the optional webcredentials and appclips blocks.
Does the actor validate assetlinks.json statements? Yes. It checks that the file is a JSON array of statements, each with a relation list, a target with namespace android_app, a valid Android package name, and SHA-256 certificate fingerprints in hex or base64 format.
What about redirects? iOS does not reliably follow redirects for the AASA file. The actor follows up to 3 redirects to complete the audit but flags the redirect as an issue when the AASA file is served behind one.
Can I audit multiple domains? Run the actor once per domain, or schedule it across your domain list for recurring monitoring.
Does the actor open the app or test deep links end to end? No. It audits the server-side association files, which are the most common point of failure. End-to-end deep-link testing requires a device.