Os universal links (iOS) e os App Links do Android abrem o seu aplicativo em vez do site quando alguém toca em um link https:// comum, e a parte do site são dois arquivos JSON que você mesmo hospeda: apple-app-site-association para iOS e assetlinks.json para Android. Os dois ficam em /.well-known/ em cada domínio que o aplicativo atende, os dois precisam ser servidos por HTTPS sem redirecionamentos, e cada um indica qual aplicativo tem permissão para abrir as suas URLs. O aplicativo também precisa de uma configuração própria (uma permissão no iOS, um intent filter no Android), mostrada abaixo ao lado de cada arquivo.
Como funcionam os universal links e os App Links do Android
Os dois sistemas conectam um site e um aplicativo nos dois sentidos: o aplicativo declara quais domínios atende, e o site confirma. A Apple descreve os universal links como links HTTP ou HTTPS comuns, então uma única URL funciona para o site e para o aplicativo, e os usuários sem o aplicativo recebem a página no navegador (Apple). Os App Links do Android, nas palavras do Google, usam o mesmo sistema de intents dos outros deep links, mas acrescentam uma etapa de verificação com um arquivo Digital Asset Links no seu site (Android Developers).
| Universal links no iOS | App Links no Android | |
|---|---|---|
| Arquivo no site | apple-app-site-association |
assetlinks.json |
| Local | https://<domínio>/.well-known/apple-app-site-association |
https://<domínio>/.well-known/assetlinks.json |
| O que o aplicativo declara | Permissão Associated Domains, applinks:<domínio> |
Intent filter com android:autoVerify="true" |
| Identifica o aplicativo por | Team ID mais bundle ID | Nome do pacote mais a impressão digital do certificado de assinatura |
| Quando é verificado | Na instalação, pelo CDN da Apple | Na instalação, e em segundo plano no Android 15 ou superior |

«Deep link» é o termo mais amplo. Um deep link comum pode usar um esquema personalizado ou um link https:// não verificado; os universal links e os App Links são a versão verificada.
O arquivo do iOS: apple-app-site-association
Crie um arquivo chamado apple-app-site-association, sem extensão, e liste os identificadores do seu aplicativo e os padrões de URL que o aplicativo deve abrir. Esta é a estrutura de exemplo da documentação da Apple, resumida:
{
"applinks": {
"details": [
{
"appIDs": ["ABCDE12345.com.example.app"],
"components": [
{ "/": "/buy/*", "comment": "Open URLs that start with /buy/ in the app." },
{ "/": "/help/website/*", "exclude": true, "comment": "Keep these in the browser." }
]
}
]
}
}
O valor de appIDs é o prefixo do identificador do aplicativo (o seu Team ID), um ponto e o bundle identifier. Cada entrada de components corresponde a uma parte da URL, e "exclude": true diz ao sistema para não abrir no aplicativo as URLs correspondentes (Apple, Supporting associated domains). A Apple também aceita um formato mais antigo com appID e paths; a nota de depuração dela pede que não se misture os dois (TN3155).
Publique em https://<nome de domínio completo>/.well-known/apple-app-site-association com um certificado válido e sem redirecionamentos. Três regras das páginas da Apple costumam dar problema:
- Cada subdomínio precisa de uma entrada própria no aplicativo. Um arquivo em
example.comatendeapplinks:example.comeapplinks:*.example.com, mas um subdomínio específico comowww.example.comprecisa do próprio arquivo. - O arquivo precisa ser acessível de qualquer endereço IP e para qualquer user agent. Um 403 ou 404 vindo de um firewall, de um filtro de bots ou de uma tela de login impede os servidores da Apple de armazená-lo em cache.
- Desde o iOS 14, os dispositivos não buscam o arquivo no seu servidor. O CDN da Apple baixa e armazena o arquivo, os dispositivos verificam atualizações cerca de uma vez por semana, e não há como invalidar esse cache diretamente; reinstalar o aplicativo baixa uma cópia mais nova (TN3155).
Durante o desenvolvimento, você pode acrescentar ?mode=developer à entrada da permissão (applinks:example.com?mode=developer) para que o dispositivo leia o arquivo diretamente do seu servidor em vez do CDN da Apple.
O arquivo do Android: assetlinks.json
O assetlinks.json é um array de declarações que nomeia o seu pacote e a impressão digital SHA-256 do certificado que assina o aplicativo. Este é o exemplo do Google para um aplicativo:
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example",
"sha256_cert_fingerprints":
["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
}
}]
Substitua o nome do pacote e a impressão digital pelos seus. Os requisitos, segundo o guia do Google (atualizado em 23 de outubro de 2026):
- Sirva em
https://<domínio>/.well-known/assetlinks.jsoncom o tipo de conteúdoapplication/json. - Use HTTPS mesmo que os intent filters do aplicativo também declarem
http. - Sem redirecionamentos, nem 301 nem 302.
- Publique em cada domínio hospedeiro que o aplicativo atende.
- Um único arquivo pode listar vários aplicativos, e o campo
sha256_cert_fingerprintsaceita várias impressões digitais, por exemplo para as builds de depuração e de produção.
Se você usa o Play App Signing, a impressão digital que você obtém com o keytool na sua máquina normalmente não vai coincidir com a dos dispositivos dos usuários. O Google orienta pegar o trecho JSON correto no Play Console, em Release > Setup > App signing.
O lado do aplicativo é um intent filter com autoVerify. Esta é a forma da documentação do Android:
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="www.example.com" />
</intent-filter>
O Android verifica cada nome de host desses filtros, e um host curinga como *.example.com exige o arquivo no domínio raiz example.com (Android Developers). No Android 15 ou superior, a verificação também roda periodicamente, e uma alteração no arquivo pode levar até sete dias para se propagar; no Android 14 ou inferior, o arquivo só é lido na instalação ou na atualização (Android Developers).
Lista de verificação do servidor
Os dois arquivos falham pelos mesmos poucos motivos, então verifique o servidor uma vez para os dois:
| Verificação | Por quê | Como testar |
|---|---|---|
| HTTPS | As duas plataformas exigem, e a Apple pede um certificado válido | Abra a URL em um navegador |
| Sem 301 nem 302 | Redirecionamentos não são aceitos em nenhum dos dois arquivos | curl -sI mostra um 200 |
| iOS: público para todos os IPs e user agents | O CDN da Apple baixa o arquivo, e um firewall ou filtro de bots o bloqueia | curl -A "MyAgent-Bot/1.0" <url> devolve o arquivo |
Android: Content-Type: application/json |
O Google lista como requisito | Cabeçalho do curl -sI |
| O mesmo arquivo em cada domínio e subdomínio listado | Cada host é verificado separadamente | Rode a verificação para cada host |
Para o tipo de conteúdo, servir os dois arquivos como application/json mantém a configuração uniforme. A documentação da Apple não indica um tipo de conteúdo para o arquivo do iOS, então esse ponto é uma escolha sua. Um exemplo estático para nginx:
location = /.well-known/apple-app-site-association {
default_type application/json;
}
location = /.well-known/assetlinks.json {
default_type application/json;
}
Como verificar que funciona
Confira o arquivo por fora e depois o comportamento em um dispositivo. Os passos de depuração da Apple, do TN3155:
- Rode
curl -v https://<domínio>/.well-known/apple-app-site-associatione confirme um 200 e o JSON, não um 301, 302, 403 ou 404. - Em um Mac,
sudo swcutil dl -d <domínio>verifica se o arquivo baixa, esudo swcutil verify -d <domínio> -j <caminho-do-JSON> -u <URL>verifica se uma URL corresponde a um padrão. - Em um iPhone, cole o link no app Notas e mantenha pressionado. Se tudo estiver configurado, aparecem as opções de abrir no aplicativo e de abrir no navegador.
Para o Android, a verificação manual do Google no Android 12 ou superior (para um aplicativo que mira uma versão anterior ao Android 12, primeiro rode adb shell am compat enable 175408749 com.example):
adb shell pm set-app-links --package com.example 0 all
adb shell pm verify-app-links --re-verify com.example
# aguarde alguns minutos e depois:
adb shell pm get-app-links com.example
A saída lista cada domínio com um estado como verified ou legacy_failure. O Google também oferece um gerador e testador de listas de declarações (ferramenta Digital Asset Links) para testar um arquivo de declarações existente. Para uma rotina de testes mais ampla, veja a lista de testes de site mobile.
Quando os links não abrem o aplicativo
Digitar uma URL na barra de endereços do navegador nunca abre o aplicativo no iOS, porque é navegação direta dentro do navegador; se o usuário já está no seu domínio, um link para o mesmo domínio também fica no Safari (TN3155). A solução da Apple para fluxos como um botão de login é usar outro subdomínio, com entrada applinks e arquivo AASA próprios, para que o sistema trate o toque como uma saída do site.
Os navegadores embutidos em aplicativos precisam de testes separados. A Apple informa que links tocados em um app de navegador ou em um WKWebView podem abrir o seu aplicativo, mas também diz que navegadores de terceiros decidem se ativam os universal links («Os universal links podem não estar ativados em todos os navegadores web», segundo o TN3155), e que um aplicativo que abre o seu link pela própria chamada open(_:) não abrirá o seu link de volta (Apple). Se o navegador de um aplicativo social específico entrega o link ao seu aplicativo não é algo que a documentação da plataforma cobre, então teste cada um que importa em um celular real.
Banner de aplicativo inteligente como alternativa
Um banner de aplicativo inteligente é um aviso exclusivo do iOS na página web: uma tag meta no <head> de cada página onde você quiser. Segundo a Apple, ele abre o aplicativo se ele estiver instalado e leva à App Store se não estiver.
<meta name="apple-itunes-app" content="app-id=myAppStoreID, app-argument=https://example.com/buy/42">
O app-id é obrigatório, e o app-argument opcional passa uma URL ao aplicativo para abrir a tela correspondente. A Apple lista dois limites: os banners não aparecem dentro de um frame, e não aparecem no simulador do iOS.
Se você não publica um aplicativo nativo, não precisa de nenhum dos dois arquivos; um aplicativo web progressivo é instalado pelo navegador.
Confira a página de contingência em tamanhos de celular
Todos que não têm o aplicativo, e todo link que não é repassado, chegam à sua página web, então essa página precisa funcionar no celular. O Mobile View Extension recarrega a aba com o user agent, o tamanho de tela e a densidade de pixels de um celular, então você vê a versão mobile real da página de contingência em vários tamanhos, e pode usar junto a emulação de dispositivo do Chrome. Ele não consegue testar a passagem para o aplicativo: roda o Chrome de desktop, não tem eventos de toque nem aplicativos instalados, então o tratamento de links exige um iPhone ou um celular Android, ou o simulador do iOS ou o emulador do Android. Para iOS sem hardware, veja testar um site em um iPhone sem ter um iPhone.
Perguntas frequentes
Qual é a diferença entre universal links e deep links?
Deep links é a categoria ampla; universal links é a versão verificada da Apple, construída sobre links HTTP ou HTTPS padrão. Um deep link também pode usar um esquema de URL personalizado, que não está ligado a um site que você controla. Os App Links do Android são a forma verificada no Android, que acrescenta a verificação Digital Asset Links aos deep links comuns.
Onde fica o apple-app-site-association?
Fica em https://<domínio>/.well-known/apple-app-site-association, sem extensão de arquivo, servido por HTTPS com um certificado válido e sem redirecionamentos. Cada subdomínio listado pelo aplicativo precisa de sua própria cópia.
Por que o meu universal link abre o Safari em vez do aplicativo?
As causas comuns são um redirecionamento, um 403 ou 404 no arquivo, uma entrada de subdomínio faltando ou um toque em link do mesmo domínio. A Apple lista essas causas no TN3155; digitar a URL na barra de endereços ou tocar em um link para o mesmo domínio enquanto navega no Safari mantém o usuário no navegador. Confira o arquivo com curl -v primeiro.
Preciso dos dois arquivos?
Você precisa do arquivo de cada plataforma para a qual publica um aplicativo. Um site com um aplicativo para iOS e outro para Android serve os dois, e cada um é independente do outro.