Para gerar o QR Code a partir do Pix copia e cola, você entrega o texto do código, exatamente como veio, a uma biblioteca de QR Code e desenha o resultado na página. O texto não pode mudar em nada: o Manual de Padrões para Iniciação do Pix, do Banco Central, diz que o copia e cola é exatamente a mesma sequência de caracteres que o leitor de QR Code leria na imagem. O resto é cuidado de desenho: margem clara de 4 módulos, módulos escuros sobre fundo claro, nível de correção adequado e um botão de copiar ao lado.
Antes de tudo: você precisa gerar?
Na API Pix da xFlow, a cobrança já vem com a imagem. O POST /api/v1/charges e o GET /api/v1/charges/{id} devolvem pix.copyPaste, o texto, e pix.qrCodeBase64, um PNG em data-URL que entra direto no src de uma tag img. A listagem de cobranças não traz nenhum dos dois. Como exibir a imagem pronta está em Pix copia e cola por API.
Gerar o QR no seu lado faz sentido em três situações:
- Você precisa de vetor. Um SVG fica nítido em qualquer tamanho, inclusive em impressão e em telas de alta densidade.
- O layout pede controle de tamanho. Com a biblioteca, você define quantos pixels cada módulo ocupa.
- Você só guardou o texto. Se o seu banco de dados tem apenas o copia e cola, dá para redesenhar o QR sem chamar a API de novo.
Fora disso, use a imagem da API. Ela sai da mesma cobrança que o texto, e não há o que dar errado na conversão.
A regra de ouro: o texto entra intacto
O QR Code e o copia e cola precisam carregar o mesmo conteúdo, caractere por caractere. Antes de passar o texto para a biblioteca, não faça nada com ele:
- não aplique
trim,toUpperCasenem remoção de espaços (o nome do recebedor tem espaços que fazem parte do código); - não quebre o texto em linhas nem insira espaços a cada tantos caracteres;
- não codifique para URL nem escape para HTML;
- não corte o texto com um limite de caracteres de campo.
Qualquer alteração muda o CRC do fim do código, e o app do banco recusa a leitura. A estrutura do Pix copia e cola mostra por quê: cada campo declara o próprio tamanho, e o CRC16 cobre o texto inteiro.
Gerando o QR em JavaScript
O exemplo usa a biblioteca qrcode-generator, que roda no navegador e no Node.js e gera SVG sem dependências. Outras bibliotecas funcionam da mesma forma: texto de entrada, nível de correção e margem.
import qrcode from "qrcode-generator";
export function qrPixSvg(copiaECola) {
const qr = qrcode(0, "M"); // 0 = versão automática; "M" = correção média
qr.addData(copiaECola, "Byte"); // o texto exato, sem tratamento
qr.make();
// cellSize = pixels por módulo; a margem padrão é de 4 módulos
return qr.createSvgTag({ cellSize: 8, scalable: true });
}Na página, o QR, o texto e o botão ficam juntos:
<div id="qr" class="qr-pix" role="img" aria-label="QR Code para pagar com Pix"></div>
<textarea id="codigo" readonly rows="3" spellcheck="false"></textarea>
<button id="copiar" type="button">Copiar código Pix</button>
<p id="aviso" role="status"></p>const codigo = cobranca.pix.copyPaste; // veio do seu servidor
document.getElementById("qr").innerHTML = qrPixSvg(codigo);
const campo = document.getElementById("codigo");
campo.value = codigo; // value, e não innerHTML
document.getElementById("copiar").addEventListener("click", async () => {
const aviso = document.getElementById("aviso");
try {
await navigator.clipboard.writeText(codigo);
aviso.textContent = "Código copiado. Cole no app do seu banco.";
} catch {
campo.focus();
campo.select();
aviso.textContent = "Selecione o código acima e copie.";
}
});E um CSS mínimo:
.qr-pix { width: 260px; max-width: 80vw; background: #fff; }
.qr-pix svg { display: block; width: 100%; height: auto; }
#codigo { width: 100%; font-family: monospace; word-break: break-all; }O word-break: break-all quebra o texto só na tela, sem inserir caracteres. A cópia continua igual ao original. Ajuste a largura ao seu layout; o número acima é só um ponto de partida.
Tamanho, margem e contraste
Margem. A Denso Wave, criadora do QR Code, pede uma margem clara de 4 módulos em volta do símbolo. É o padrão da biblioteca do exemplo. Não deixe bordas de cartão, sombras ou texto invadirem essa área.
Tamanho. O número de módulos cresce com o tamanho do texto e com o nível de correção. No nosso teste, o exemplo estático do manual do Banco Central (137 caracteres) gerou um QR de 49 por 49 módulos no nível M, e o exemplo dinâmico (155 caracteres), um de 53 por 53. O tamanho em pixels é o número de módulos vezes os pixels por módulo, mais a margem. Prefira um número inteiro de pixels por módulo: com valores fracionados, as bordas ficam borradas. Não há um tamanho mínimo único. Teste com a câmera de celulares comuns, a uma distância normal de leitura.
Contraste. Desenhe módulos escuros sobre fundo claro. No tema escuro do seu site, mantenha o fundo branco em volta do QR, porque um fundo transparente herda a cor da página. Evite inverter as cores e evite cores claras da marca nos módulos. Também não coloque logotipo no meio do código: ele cobre módulos e depende da correção de erro para ser lido.
Nível de correção. São quatro: L, M, Q e H. Quanto mais alto, mais o código tolera sujeira e danos, e mais denso ele fica. Segundo a Denso Wave, o M é o mais escolhido, e Q ou H servem para ambientes em que o código pode sujar. Em tela, M basta. Num QR impresso que vai ficar exposto, considere Q.
Imagem da API ampliada. Se você usa o pix.qrCodeBase64 e precisa aumentar a imagem, aplique image-rendering: pixelated no CSS. Sem isso, o navegador suaviza as bordas dos módulos.
Confira antes de publicar
Depois de implementar, faça três testes:
- O conteúdo bate. Leia o QR gerado com um leitor de QR Code comum e compare o texto lido com o
pix.copyPaste. Têm de ser iguais. Nos nossos testes, os QR gerados com a função acima foram lidos de volta por um decodificador e devolveram o texto original, caractere por caractere. - O código está inteiro. Cole o texto no decodificador de Pix copia e cola e veja se todos os campos aparecem e se o CRC confere.
- O banco lê. No ambiente de teste, o
pix.copyPasteé um marcador que não pode ser pago, então este teste só vale em produção. Crie uma cobrança real de valor baixo e leia o QR com o app de mais de um banco.
Erros que quebram a leitura
- Código cortado. Um
inputcommaxlengthou uma coluna curta no banco de dados corta o fim do texto. O QR é gerado, mas o banco recusa. - Código salvo e cobrança vencida. Antes de redesenhar um QR guardado, consulte o status da cobrança. Se estiver
expired, crie outra, como mostra cobrança Pix expirada. - Texto com entidades HTML. Inserir o código com
innerHTMLpode transformar caracteres especiais. UsevalueoutextContent. - SVG esticado. Largura e altura diferentes deformam o QR. Mantenha a proporção quadrada.
- Copiar do texto formatado. Se a página mostra o código em blocos para facilitar a leitura, o botão de copiar tem de usar o texto original, e não o que está na tela.
A diferença entre QR estático e dinâmico, e o que cada um significa para a cobrança, está em QR Code Pix dinâmico por API. A referência dos campos pix.copyPaste e pix.qrCodeBase64 fica na documentação da API.
Conteúdo informativo, atualizado em 25/10/2026. Não substitui orientação jurídica.
Perguntas frequentes
Preciso gerar o QR Code se a API já devolve a imagem?
Na maioria dos casos, não. A xFlow devolve pix.qrCodeBase64, um PNG em data-URL pronto para a tag img, na criação da cobrança e na consulta por id. Gerar no front-end compensa quando você precisa de SVG, de controle fino de tamanho ou só guardou o copia e cola.
Qual nível de correção de erro usar no QR Code Pix?
O nível M é o mais usado e funciona bem em tela. Níveis mais altos, como Q e H, toleram mais sujeira e danos, mas deixam o código mais denso. Para impressão em lugar sujeito a desgaste, considere Q ou H.
Qual o tamanho mínimo do QR Code Pix na tela?
Não existe um número único. O tamanho necessário depende da quantidade de módulos do código e da distância de leitura. Use um número inteiro de pixels por módulo, mantenha a margem de 4 módulos e teste com a câmera de celulares comuns.
Por que o botão de copiar não funciona em alguns navegadores?
A API de área de transferência do navegador só funciona em contexto seguro, como HTTPS, e em geral a partir de um clique do usuário. Tenha um campo de texto só de leitura com o código como alternativa.