Artigo Build·Desenvolvimento·13 min de leitura de leitura

Como Gerar QR Code em JavaScript (2026): Guia Completo com Código Pronto

Gerar QR Code em JavaScript é tarefa de algumas linhas quando se conhece a biblioteca certa. Este guia cobre as três principais libs em 2026, casos de uso (URL, PIX, WiFi, vCard), customização visual com logo, download em PNG e SVG, e testes automatizados para garantir que o QR realmente escaneia.

Vitor Morais

Por Vitor Morais

Fundador do MochaLabz ·

🔳

Gere QR Codes online

URL, texto, WiFi, vCard ou PIX — download em PNG e SVG, customização de cor.

Usar gerador →

QR Code virou padrão universal em 2020 (pandemia acelerou adoção) e segue em 2026 como interface entre papel e digital. Cardápios, pagamentos PIX, Wi-Fi de café, login em serviços, eventos, rastreio de entrega, vCards — tudo codificado em pontos brancos e pretos. Gerar QR em JavaScript é tarefa de menos de 10 linhas quando você sabe qual biblioteca usar.

Este guia cobre as três principais bibliotecas em 2026, os casos de uso mais comuns com código pronto (URL, PIX, WiFi, vCard), customização visual com logo, download nos formatos PNG e SVG, e como testar automatizadamente se o QR gerado realmente escaneia.

Como funciona QR Code (versão rápida)

QR é uma matriz 2D de pontos brancos e pretos que codifica dados via Reed-Solomon (correção de erro). Os três quadrados grandes nos cantos são o padrão de localização — qualquer leitor identifica orientação por eles. O conteúdo central é a combinação de: formato (URL, texto, vCard...), máscara de bit (oito variações padronizadas) e código de correção de erros (4 níveis: L, M, Q, H).

Contexto

Nível de correção define quanto do QR pode estar danificado/coberto e ainda funcionar: L (~7%), M (~15%), Q (~25%), H (~30%). Para QR com logo central, use H. Para QR puro (sem customização), M é o padrão e suficiente.

Três bibliotecas principais em 2026

Bibliotecas JavaScript para gerar QR Code
CritérioTamanhoMelhor para
qrcode~50 KBUso geral, padrão da indústria
qr-code-styling~200 KBQR visual com logo e cores customizadas
qr-creator~20 KBQuando peso do bundle importa muito
qrcode-svg~15 KBApenas SVG, sem canvas
qrious~25 KBAlternativa leve, canvas-only

Biblioteca qrcode: a escolha padrão

Instala via npm e cobre 90% dos casos. Suporta canvas (preview), SVG (responsivo), data URL (embedir em HTML) e string no terminal (CLI).

npm install qrcode # Se usar TypeScript: npm install -D @types/qrcode

Uso básico: URL em canvas

import QRCode from "qrcode"; const canvas = document.getElementById("qr") as HTMLCanvasElement; await QRCode.toCanvas(canvas, "https://mochalabz.com", { width: 320, margin: 2, color: { dark: "#28190a", // cor dos pontos light: "#fffdf9", // cor do fundo }, });

Gerar como SVG (ideal pra web)

import QRCode from "qrcode"; const svgString = await QRCode.toString("https://mochalabz.com", { type: "svg", width: 320, margin: 2, color: { dark: "#28190a", light: "#fffdf9" }, }); // Injetar no DOM document.getElementById("qr-container")!.innerHTML = svgString;

Gerar como Data URL (PNG inline)

import QRCode from "qrcode"; const dataUrl = await QRCode.toDataURL("https://mochalabz.com"); // "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..." // Usar em <img> const img = document.createElement("img"); img.src = dataUrl; document.body.appendChild(img);

Salvar em arquivo (Node.js)

import QRCode from "qrcode"; // Gera e salva PNG direto no disco await QRCode.toFile( "./meu-qr.png", "https://mochalabz.com", { width: 512, margin: 2, color: { dark: "#000000", light: "#ffffff" }, errorCorrectionLevel: "H", }, );

Biblioteca qr-code-styling: para QR com identidade visual

Quando você precisa de logo no meio, pontos em formato custom (redondos, estrelas) ou cores gradient, qr-code-styling entrega. Mais pesada (~200 KB) mas suporta controle visual completo.

npm install qr-code-styling
import QRCodeStyling from "qr-code-styling"; const qrCode = new QRCodeStyling({ width: 320, height: 320, type: "svg", data: "https://mochalabz.com", image: "/logo.png", // logo central dotsOptions: { color: "#28190a", type: "rounded", // rounded | dots | classy | classy-rounded | extra-rounded }, backgroundOptions: { color: "#fffdf9", }, cornersSquareOptions: { color: "#c98238", type: "extra-rounded", }, imageOptions: { crossOrigin: "anonymous", margin: 8, // padding em torno do logo imageSize: 0.3, // 30% do QR }, qrOptions: { errorCorrectionLevel: "H", // obrigatório com logo }, }); qrCode.append(document.getElementById("qr-container")!); // ou qrCode.download({ name: "meu-qr", extension: "svg" });

Dica

Logo cobrindo mais de 30% do QR reduz taxa de leitura mesmo com ECC nível H. Se precisa logo grande, considere dois elementos lado a lado: QR puro + logo ao lado, em vez de logo embedado.

Casos de uso com código pronto

1. URL simples

await QRCode.toCanvas(canvas, "https://mochalabz.com");

2. Texto livre

await QRCode.toCanvas(canvas, "Seu texto qualquer aqui");

3. WiFi (conectar automaticamente)

function gerarQrWifi({ ssid, senha, encriptacao = "WPA", // WPA | WEP | nopass hidden = false, }: { ssid: string; senha: string; encriptacao?: "WPA" | "WEP" | "nopass"; hidden?: boolean; }) { const payload = `WIFI:T:${encriptacao};S:${ssid};P:${senha};H:${hidden};;`; return QRCode.toDataURL(payload); } // Uso const qr = await gerarQrWifi({ ssid: "MochaCafe", senha: "caramelo2026", }); // Usuário escaneia → celular conecta automaticamente ao WiFi

4. vCard (contato)

function gerarQrVCard({ nome, empresa, telefone, email, site, }: { nome: string; empresa?: string; telefone?: string; email?: string; site?: string; }) { const vcard = [ "BEGIN:VCARD", "VERSION:3.0", `FN:${nome}`, empresa ? `ORG:${empresa}` : "", telefone ? `TEL:${telefone}` : "", email ? `EMAIL:${email}` : "", site ? `URL:${site}` : "", "END:VCARD", ] .filter(Boolean) .join("\n"); return QRCode.toDataURL(vcard); } const qr = await gerarQrVCard({ nome: "Vitor Morais", empresa: "MochaLabz", email: "vitor@mochalabz.com", site: "https://mochalabz.com", });

5. E-mail com assunto pré-preenchido

const payload = `mailto:contato@empresa.com?subject=Orcamento&body=Olá,`; await QRCode.toCanvas(canvas, payload);

6. SMS

const payload = `sms:+5511999999999?body=Olá,`; await QRCode.toCanvas(canvas, payload);

7. Localização (Google Maps)

const payload = `geo:-23.550520,-46.633308?q=Praça da Sé`; await QRCode.toCanvas(canvas, payload);

8. PIX (pagamento)

Pix tem payload específico EMV. O formato completo exige múltiplos campos Bacen; para gerar corretamente, use biblioteca dedicada:

npm install pix-utils
import { createStaticPix, hasError } from "pix-utils"; import QRCode from "qrcode"; const pix = createStaticPix({ merchantName: "JOAO DA SILVA", merchantCity: "SAO PAULO", pixKey: "joao@exemplo.com", infoAdicional: "Pagamento curso", transactionAmount: 50.0, }); if (hasError(pix)) { throw new Error(pix.error); } const payload = pix.toBRCode(); const qrCodeImage = await QRCode.toDataURL(payload); // Exibir no site document.querySelector("img#pix-qr")!.setAttribute("src", qrCodeImage);

Atenção

Para PIX Cobrança (com recorrência, valor variável, identificador externo), você precisa de integração com banco via API PSP oficial — não é apenas gerar QR no cliente. O QR estático (campo fixo, sem ID de cobrança) funciona para pagamentos pontuais e testes; cobranças reais em produção exigem certificado e webhook para confirmação.

Componente React pronto

Em projetos React (Next.js, Vite, Remix), você geralmente quer um componente reusável:

"use client"; import { useEffect, useRef } from "react"; import QRCode from "qrcode"; interface QRCodeProps { data: string; size?: number; color?: string; background?: string; } export function QRCodeImage({ data, size = 320, color = "#000000", background = "#ffffff", }: QRCodeProps) { const canvasRef = useRef<HTMLCanvasElement>(null); useEffect(() => { if (!canvasRef.current) return; QRCode.toCanvas(canvasRef.current, data, { width: size, margin: 2, color: { dark: color, light: background }, errorCorrectionLevel: "M", }).catch(console.error); }, [data, size, color, background]); return <canvas ref={canvasRef} aria-label="QR Code" />; } // Uso <QRCodeImage data="https://mochalabz.com" size={256} />

Download do QR (PNG ou SVG)

// PNG a partir de canvas function baixarPng(canvas: HTMLCanvasElement, nome: string) { const link = document.createElement("a"); link.href = canvas.toDataURL("image/png"); link.download = `${nome}.png`; link.click(); } // SVG a partir de string async function baixarSvg(data: string, nome: string) { const svg = await QRCode.toString(data, { type: "svg", width: 512, margin: 2, }); const blob = new Blob([svg], { type: "image/svg+xml" }); const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = `${nome}.svg`; link.click(); URL.revokeObjectURL(link.href); }

Testes automatizados: garantir que o QR escaneia

Geração correta não garante leitura. Use jsQR para decodificar o próprio QR e validar:

npm install -D jsqr jest-canvas-mock
// qr-code.test.ts import QRCode from "qrcode"; import jsQR from "jsqr"; import { createCanvas } from "canvas"; describe("QR Code", () => { it("gera QR que decodifica para o dado original", async () => { const data = "https://mochalabz.com"; const canvas = createCanvas(320, 320); await QRCode.toCanvas(canvas, data); const ctx = canvas.getContext("2d")!; const imageData = ctx.getImageData(0, 0, 320, 320); const decoded = jsQR(imageData.data, 320, 320); expect(decoded?.data).toBe(data); }); it("gera QR para vCard válido", async () => { const vcard = "BEGIN:VCARD\nVERSION:3.0\nFN:Teste\nEND:VCARD"; const canvas = createCanvas(320, 320); await QRCode.toCanvas(canvas, vcard); const ctx = canvas.getContext("2d")!; const imageData = ctx.getImageData(0, 0, 320, 320); const decoded = jsQR(imageData.data, 320, 320); expect(decoded?.data).toContain("BEGIN:VCARD"); }); });

Armadilhas comuns

  • Dados longos com ECC baixo: URLs compridas + ECC L geram QR denso que falha em scan rápido. Aumente para M ou use URL encurtada.
  • Cores de baixo contraste: cinza em branco, pastel em pastel. Teste em luz ruim antes de publicar.
  • Logo muito grande: cobre quiet zone ou pattern de localização. Mantenha em 25-30% do tamanho total.
  • Sem quiet zone: o espaço em branco ao redor do QR é obrigatório. A margem default (2 módulos) costuma ser mínima; considere 4 em material impresso.
  • QR muito pequeno: abaixo de 2cm impresso, leitores precisam de foco perfeito. Mínimo saudável: 2,5-3cm.
  • Confiar em canvas para download de alta resolução: canvas tem DPI do monitor. Para impressão, gere PNG em pelo menos 1024×1024 ou SVG.

Customização visual sem quebrar leitura

O que funciona vs o que quebra QR
CritérioSeguroCuidado
Cor dos pontosQualquer cor escuraGradient que reduz contraste
Forma dos pontosRounded, dotsFormas muito estilizadas
Logo centralAté 30% do tamanho, ECC HMais que 30% ou sem ECC H
Borda externaDeixe quiet zone (margem)Sem margem ao redor
Background texturaSólido, claroPadrão que confunde o leitor

QR gerador completo (cliente web)

Para oferecer ao usuário final a capacidade de gerar QR customizado no site, você combina input de formulário + biblioteca + download. Um exemplo completo em React consolida tudo:

"use client"; import { useEffect, useRef, useState } from "react"; import QRCode from "qrcode"; export default function GeradorQRCode() { const canvasRef = useRef<HTMLCanvasElement>(null); const [data, setData] = useState("https://mochalabz.com"); const [cor, setCor] = useState("#28190a"); const [bg, setBg] = useState("#fffdf9"); useEffect(() => { if (!canvasRef.current || !data) return; QRCode.toCanvas(canvasRef.current, data, { width: 320, margin: 2, color: { dark: cor, light: bg }, errorCorrectionLevel: "M", }).catch(console.error); }, [data, cor, bg]); const baixarPng = () => { if (!canvasRef.current) return; const link = document.createElement("a"); link.href = canvasRef.current.toDataURL("image/png"); link.download = "qrcode.png"; link.click(); }; return ( <div> <input value={data} onChange={(e) => setData(e.target.value)} /> <input type="color" value={cor} onChange={(e) => setCor(e.target.value)} /> <input type="color" value={bg} onChange={(e) => setBg(e.target.value)} /> <canvas ref={canvasRef} /> <button onClick={baixarPng}>Baixar PNG</button> </div> ); }

QR em uma frase

Gerar QR Code em JavaScript é 3 linhas de código com biblioteca qrcode, 10 linhas com logo e customização via qr-code-styling, e serve para URL, WiFi, vCard, PIX e praticamente qualquer texto codificável. A dificuldade real não está no gerador — está em testar que o QR escaneia em ambiente hostil (papel ruim, luz fraca, celular antigo). Gere certo, teste sempre.

Perguntas frequentes

Qual biblioteca JavaScript usar para gerar QR Code?+

Três opções populares em 2026. (1) qrcode (por Ryan Day) — ~50 KB, pronta, renderiza canvas/SVG/terminal, suporta todos os modos. (2) qr-code-styling — mais visual, permite logo no centro, formas customizadas de pontos, mais pesada (~200 KB). (3) qr-creator — leve (~20 KB), mínima. Para 90% dos casos, qrcode é a escolha. Para QR com identidade visual da marca (logo, cores), use qr-code-styling.

QR Code pode ter imagem no meio (logo)?+

Sim. O padrão QR ECC (Error Correction Code) permite cobrir até 30% dos pixels com logo e ainda funcionar. Use nível de correção 'H' (High) para maior tolerância. Bibliotecas como qr-code-styling fazem o overlay automaticamente. Para sites importantes de produção, teste escaneando em múltiplos leitores — logos muito grandes ou colocados errado reduzem a leitura mesmo com ECC alto.

Quais formatos de saída um QR Code suporta?+

Dois principais: PNG (raster, universal, bom para impressão e web) e SVG (vetorial, escalável sem perda, ideal para mídia digital com diferentes tamanhos). Canvas também é usado para preview em tempo real no navegador. A escolha depende do destino: PNG para redes sociais e impressão; SVG para páginas web responsivas.

Como gerar QR Code para Pix?+

O Pix usa um payload EMV específico com chaves como merchant account, valor e identificador da transação. Você monta a string EMV (conforme padrão Bacen) e codifica em QR. Bibliotecas específicas: pix-qrcode-js e pix-utils simplificam. Para integração com conta comercial real, o Pix Cobrança exige certificado digital e endpoint do banco — sua biblioteca gera apenas o QR visual a partir do payload que o banco retorna.

QR Code precisa de internet para gerar?+

Não. A geração é puramente algorítmica — nenhuma API externa ou servidor é necessário. Qualquer biblioteca client-side em JavaScript funciona 100% offline no navegador. Use serviço online apenas se você não quiser bibliotecas no código; mas usar API para algo tão simples adiciona dependência e latência sem benefício.

Existe tamanho máximo para QR Code?+

Sim. Versão 40 (a maior) suporta ~4.296 caracteres alfanuméricos ou ~2.953 binários. Mas na prática, QR com muito conteúdo vira denso demais para scan confiável — câmeras precisam de qualidade perfeita. Para URLs, mantenha abaixo de 200 caracteres (use encurtador). Para vCard, resumido. Para PIX, payload padrão tem 200-400 caracteres e funciona bem.

QR Code funciona em modo escuro?+

Sim, desde que o contraste entre cor dos pontos e do fundo seja suficiente. Padrão é preto em branco. Variações válidas: qualquer cor escura em fundo claro ou vice-versa. Evite contraste ruim (cinza médio em branco) e combinações que quebrem leitura (vermelho em laranja). Para QR em material escuro, use pontos claros em fundo escuro — funciona em qualquer leitor moderno.

Como posso testar se o QR gerado realmente funciona?+

Três métodos. (1) Escaneie com o próprio celular usando a câmera padrão (iOS 12+ e Android 9+ detectam nativamente). (2) Use biblioteca de decodificação em JavaScript (jsQR, zxing) no próprio teste automatizado. (3) Em produção, teste em múltiplos leitores e ambientes de iluminação variada. Para uso comercial, nunca confie apenas no QR renderizado na sua tela — teste em papel impresso, em tela pequena e com iluminação fraca.

#qr code#javascript#typescript#qrcode#react#pix#wifi#vcard#node.js

Artigos relacionados