Todos os artigos
74 artigos · atualizado semanalmente Veja nossas Ferramentas
Todos os artigos
Tutoriais

QR code não é só URL: os schemas que todo dev deveria conhecer

otpauth, WIFI, MECARD, deep links e PIX — os schemas internos do QR code que resolvem problemas reais de desenvolvimento, com exemplos de código.

COVER · Tutoriais

Fui configurar TOTP para um serviço interno e precisei gerar um QR code com a chave secreta para que o time pudesse escanear no Google Authenticator. Joguei a string no primeiro gerador que apareceu, escaneei, o app não reconheceu nada. O problema não era o gerador — era que QR code de autenticação não é uma URL. É um schema diferente, com estrutura própria, e a maioria dos artigos sobre QR code nunca menciona isso.

QR code é só um container de texto. O que muda completamente de caso para caso é o que você coloca dentro. Este post cobre os schemas que resolvem problemas reais de desenvolvimento — com as strings exatas para cada um.


O que um QR code armazena de fato

Um QR code não guarda imagem, não guarda binário arbitrário — guarda texto. O leitor decodifica esse texto e decide o que fazer com ele. Se começa com https://, o celular abre o browser. Se começa com WIFI:, o Android ou iOS oferece conectar na rede. Se começa com otpauth://, um app authenticator interpreta a chave.

O limite prático de dados depende do nível de correção de erros configurado:

Nível Redundância Capacidade (texto)
L (Low) 7% ~2.953 chars
M (Medium) 15% ~2.331 chars
Q (Quartile) 25% ~1.663 chars
H (High) 30% ~1.273 chars

Nível H aguenta até 30% do código danificado e ainda decodifica corretamente — útil para QR codes impressos em superfícies que desgastam. O tradeoff é que o código fica mais denso e mais difícil de escanear de longe. Para a maioria dos casos, nível M é o equilíbrio certo.

A implicação prática: URLs longas com parâmetros de tracking, tokens JWT ou qualquer string maior que ~1.000 caracteres vão gerar QR codes densos demais para escanear com confiança em condições normais.


otpauth:// — como o 2FA usa QR code por dentro

O schema otpauth:// foi formalizado pelo Google e é o que todo app authenticator (Google Authenticator, Authy, 1Password) espera encontrar quando você escaneia um QR de configuração de 2FA.

A URI completa tem essa estrutura:

otpauth://totp/{label}?secret={BASE32_SECRET}&issuer={issuer}&algorithm=SHA1&digits=6&period=30

Exemplo real:

otpauth://totp/MinhaApp:rafael@empresa.com?secret=JBSWY3DPEHPK3PXP&issuer=MinhaApp&algorithm=SHA1&digits=6&period=30

Os campos que importam:

  • totp — Time-based OTP (o padrão usado em quase todo lugar). Existe também hotp (counter-based), mas raramente é necessário.
  • secret — a chave compartilhada em Base32. Esse é o segredo que você guarda no servidor e que o app usa para gerar os códigos de 6 dígitos.
  • issuer — aparece no app como nome do serviço. Sem ele, o usuário vê só o email, sem saber a qual conta pertence.
  • period=30 — janela de validade do código em segundos. 30 é o padrão; não mude sem motivo.

Quando você gera o QR code com essa URI, qualquer app authenticator compatível com RFC 6238 vai funcionar. O QR code em si não contém lógica de TOTP — só os parâmetros para o app calcular os códigos localmente.


WIFI: — o schema que dispensa digitar senha

Compartilhar senha de Wi-Fi por QR code é suportado nativamente pelo Android desde a versão 10 e pelo iOS desde o 14. O schema segue uma estrutura próxima do formato MECARD:

WIFI:S:{SSID};T:{tipo};P:{senha};H:{oculta};;

Exemplo:

WIFI:S:Escritorio-5G;T:WPA;P:s3nh@complexa123;H:false;;
  • S — nome da rede (SSID)
  • T — tipo de segurança: WPA, WEP, ou nopass para redes abertas
  • P — senha
  • H:true — para redes com SSID oculto

O duplo ponto-e-vírgula no final é obrigatório — sem ele, alguns leitores não parsam corretamente.

Cuidado com caracteres especiais no SSID ou senha que precisam ser escapados com \: \;, \,, \", \\.


MECARD — contato direto para a agenda

MECARD é o formato que o celular interpreta como um contato para adicionar à agenda. Originalmente criado pela NTT DoCoMo para QR codes em cartões de visita, ainda funciona perfeitamente:

MECARD:N:{Sobrenome},{Nome};TEL:{telefone};EMAIL:{email};URL:{site};;

Exemplo:

MECARD:N:Duarte,Rafael;TEL:+5511999998888;EMAIL:rafael@empresa.com;URL:https://empresa.com;;

O nome segue a ordem Sobrenome,Nome — invertida em relação ao que parece intuitivo. Se você quer que apareça como "Rafael Duarte" na agenda, escreve N:Duarte,Rafael.

A alternativa é o vCard 3.0, que suporta mais campos (foto, endereço, organização), mas gera strings maiores e QR codes mais densos. Para cartão de visita simples, MECARD é suficiente e mais compacto.


Deep link via QR code funciona com qualquer schema que o sistema operacional tenha registrado para seu app. Se seu app Android registrou o schema minhaapp://, um QR code com minhaapp://produto/123?ref=qr vai abrir o app direto na tela do produto ao ser escaneado.

A versão moderna usa Universal Links (iOS) e App Links (Android) — URLs HTTPS normais que o sistema redireciona para o app se ele estiver instalado, ou para o site se não estiver:

https://app.empresa.com/produto/123?ref=qr

A vantagem do Universal Link sobre o schema customizado: se o app não estiver instalado, o usuário cai na versão web do produto em vez de ver uma tela de erro. Para QR codes em materiais físicos (embalagens, eventos, pôsteres), onde você não controla se o usuário tem o app instalado, Universal Link é a escolha certa.

O parâmetro ?ref=qr é padrão para rastrear origem de conversões — útil para medir quantos acessos vieram de QR versus outros canais.


PIX — o schema brasileiro

O QR code do PIX não usa uma URI simples. Segue o padrão EMV (Europay, Mastercard, Visa) com estrutura TLV (Type-Length-Value), definido pelo Banco Central na resolução BCB 1/2020.

O payload estático de um PIX tem essa cara quando decodificado:

000201
010211
26580014br.gov.bcb.pix
0136a1b2c3d4-e5f6-7890-abcd-ef1234567890
5204000053039865802BR5913Rafael D6008Sao Paulo
62070503***
6304ABCD

Cada campo começa com um ID de dois dígitos, seguido pelo comprimento e o valor. Não é algo para montar na mão — use uma biblioteca que implemente a spec do Banco Central ou os SDKs oficiais dos bancos. O QR de PIX dinâmico adiciona uma camada a mais: o payload vem de uma API do banco em tempo real, não é gerado localmente.

O ponto relevante para o dev: quando você escaneia um QR de PIX, não está lendo uma URL. O app de pagamento interpreta o payload EMV diretamente.


Gerando QR code no código

Para a maioria dos casos, duas opções são suficientes.

JavaScript/Node:

// npm install qrcode
import QRCode from 'qrcode';

const svg = await QRCode.toString(
  'WIFI:S:MinhaRede;T:WPA;P:senha123;;',
  { type: 'svg', errorCorrectionLevel: 'M' }
);

Python:

# pip install qrcode[pil]
import qrcode

img = qrcode.make(
    'otpauth://totp/App:user@email.com?secret=JBSWY3DP&issuer=App',
    error_correction=qrcode.constants.ERROR_CORRECT_M
)
img.save('totp.png')

Ambas as libs aceitam qualquer string — o schema que você passa é o que determina o comportamento no celular. O gerador não sabe se é TOTP, WiFi ou URL: ele só codifica o texto.


Quando QR code não é a resposta certa

Três situações onde QR code provavelmente não resolve o problema.

O usuário já está no celular. Escanear um QR code num celular com outro celular é inviável na prática. Se o fluxo começa no mobile, use link direto ou deep link — não QR.

O payload é longo demais. JWT, URLs com muitos parâmetros, chaves criptográficas longas — qualquer coisa acima de 800 caracteres vai gerar um QR code que precisa de câmera boa e iluminação razoável para ser lido. Prefira encurtar a URL ou usar um identificador que resolva para o conteúdo no servidor.

O conteúdo muda frequentemente. QR code estático impresso em material físico não pode ser atualizado. Se a URL de destino pode mudar, use um QR dinâmico (que aponta para um redirecionador que você controla) ou simplesmente não use QR em material impresso.


Nota: o conteúdo editorial acabou aqui. O que vem abaixo é uma indicação de ferramenta relacionada ao tema do post.


Ferramenta relacionada

O Gerador de QR Code suporta os principais schemas descritos neste post — URL, Wi-Fi, contato e PIX — com download em SVG e PNG, sem cadastro.

RD
Autor
Rafael Duarte
Desenvolvedor backend com passagem por fintech e SaaS B2B — trabalhou em times que escalaram APIs de zero a milhões de requisições. Carrega cicatrizes de produção suficientes para ter opiniões fortes sobre ferramentas, padrões e decisões de arquitetura. Não é acadêmico: leu a RFC do UUID quando precisou escolher entre v4 e v7 para uma tabela de alta escrita.
Ver perfil