EasyPrint Docs
Documentação · v1.0

Do site para a
impressora, sem diálogo.

O EasyPrint é um programa leve que roda no computador da loja e deixa sites, ERPs e lojas virtuais imprimirem cupons, etiquetas, PDFs e HTML direto na impressora, com acentos certos e em português. Funciona no Windows e no Linux, e é open source.

Para a loja

Instalar e configurar

Você não precisa entender de tecnologia. O assistente faz as perguntas certas e testa a impressão com você.

  1. Baixe e abra o EasyPrint.exeEle se instala sozinho na sua pasta de usuário. Não pede senha de administrador e não mexe no firewall.
  2. Escolha a impressoraO EasyPrint lista as impressoras do computador e reconhece as térmicas mais comuns (Epson TM, Elgin i9, Bematech, Daruma, Zebra…). Ainda sem impressora? Use o Simulador, que mostra o cupom na tela.
  3. Confirme o tipo e o papelCupom (58 ou 80 mm), etiqueta ou folha A4. A opção detectada já vem marcada.
  4. Imprima o testeOs acentos saíram estranhos? Clique em "Os acentos saíram estranhos" e o EasyPrint testa outra tabela de caracteres. O texto saiu cortado? Ele troca a largura do papel.

No Linux

Baixe o easyprint-linux-x64 e rode. Ele se instala em ~/.local/bin e cria o atalho no menu de aplicativos:

curl -fsSL https://github.com/GuiVicS/easyprint/raw/main/install.sh | sh

Impressoras do CUPS aparecem automaticamente. Térmicas USB sem fila no CUPS aparecem como "USB direto (lp0)". Para PDF em térmica ou etiqueta, instale o poppler-utils. Para HTML, o Chrome ou o Chromium.

As duas perguntas que vão aparecer

Na primeira vez que o sistema da loja tentar imprimir, duas janelas pedem sua confirmação. Responda Permitir nas duas.

Quem perguntaO que aparecePor quê
EasyPrint"Um site quer usar suas impressoras"Você decide quais sites podem imprimir. Só acontece uma vez por site.
Chrome / Edge"Acessar outros apps e serviços neste dispositivo"Proteção do navegador para sites que conversam com programas do computador (Local Network Access, 2026).
Clicou em Bloquear no navegador sem querer?Clique no ícone à esquerda do endereço do site, procure "Acesso à rede local" e escolha Permitir. Depois recarregue a página.
Para desenvolvedores

Primeira impressão em 5 minutos

  1. Rode o EasyPrint e complete o assistenteEscolha o Simulador se não tiver impressora. O resultado aparece em Painel → Histórico.
  2. Adicione o SDKUm arquivo, sem dependências: easyprint.js (com easyprint.d.ts para TypeScript). Copie para o projeto.
  3. Conecte uma vez e imprimaMonte o cupom com blocos. O EasyPrint converte para a linguagem da impressora.
<!-- 1. carregue o SDK (copie o arquivo para o seu projeto) -->
<script src="/vendor/easyprint.js"></script>
<span id="status"></span>
<button onclick="imprimir()">Imprimir pedido</button>

<script>
  // 2. conecte UMA vez
  const printer = EasyPrint.connect({ appName: 'Minha Loja' });
  EasyPrint.widget(printer, '#status');   // selo "Impressora pronta" + ajuda

  // 3. imprima
  async function imprimir() {
    try {
      await printer.print(
        EasyPrint.receipt()
          .title('PEDIDO #123')
          .line()
          .item(2, 'X-Burguer', 'R$ 59,80', 'sem cebola')
          .total('TOTAL', 'R$ 59,80')
          .qr('https://minhaloja.com/p/123')
          .cut()
      );
    } catch (err) {
      alert(err.message + '\n' + (err.hint || ''));  // toda falha explica como resolver
    }
  }
</script>

Você não informa a impressora, o papel nem a codificação. Isso foi decidido pelo lojista no assistente. Seu código fica igual para uma térmica de 58 mm, uma de 80 mm ou uma impressora A4.

Experimente

Playground do documento

Edite o JSON e veja o cupom se ajustar à largura do papel. A quebra de linha e as colunas usam o mesmo algoritmo do agente.

Referência

Documento universal

Um documento é uma lista de blocos. Cada bloco descreve o que imprimir e o EasyPrint decide como: ESC/POS na térmica, ZPL na etiqueta ou desenho na impressora comum.

BlocoBuilderPara que serve
text.text(v, {align, bold, size})Texto comum. size de 1 a 3, align left/center/right. Também .center() e .bold().
title.title('PEDIDO #1')Texto grande, centralizado e em negrito.
line.line('=')Separador na largura exata do papel.
row.row('Entrega', 'R$ 5,00')Rótulo à esquerda e valor à direita.
item.item(2, 'Pizza', 'R$ 90,00', 'borda recheada')Linha de pedido com a observação recuada.
total.total('TOTAL', 'R$ 95,00')Total em fonte dupla.
qr.qr(url, 6)QR Code nativo da impressora.
barcode.barcode('7891234567895', 'EAN13')Código de barras CODE128 ou EAN13.
image.image(await EasyPrint.image('/logo.png'))Logo ou imagem, convertida para preto e branco com pontilhado.
feed · cut · drawer.feed(3).cut().drawer()Avançar papel, cortar e abrir a gaveta de dinheiro.

Precisa de controle total?

Use printer.printRaw(bytes) para mandar comandos ESC/POS, ZPL ou EPL exatamente como estão. Aceita Uint8Array, string binária, { hex } ou um array misto.

ERP e e-commerce

PDF, HTML e ZPL prontos

Seu sistema já gera a DANFE em PDF, a comanda em HTML ou recebe a etiqueta do marketplace em ZPL? Mande do jeito que está. O EasyPrint adapta para cada impressora.

Você temChamadaO que acontece
PDF (DANFE, boleto, etiqueta Correios/Shopee)printer.printPdf(url, { route: 'danfe' })Renderizado pelo próprio Windows (ou pdftoppm no Linux). Na Zebra, cada página vira uma etiqueta. Na térmica, um cupom.
HTML (comanda, layout pronto)printer.printHtml(elemento)Renderizado num navegador isolado, com JavaScript desligado. Na térmica, ocupa a largura do papel e o espaço em branco do fim é cortado.
ZPL do Mercado Livreprinter.printRaw(zpl, { route: 'etiqueta' })Vai direto para a impressora, sem conversão.
// a URL é baixada pelo navegador com os cookies do seu site (endpoints autenticados funcionam)
await printer.printPdf('/api/notas/4821/danfe.pdf', { route: 'danfe', pages: '1' });

// comanda montada na própria tela, com os estilos da página
await printer.printHtml(document.querySelector('#comanda'), { route: 'pedido' });

Códigos de barras e QR são convertidos sem pontilhado, para continuarem legíveis no leitor. Os limites são 25 MB de PDF e 5 MB de HTML.

ERP e e-commerce

Finalidades: cada coisa na sua impressora

Seu sistema diz o que quer imprimir, e o lojista escolhe onde. Etiqueta na Zebra, DANFE na laser, pedido na térmica da cozinha. O código não precisa saber o nome de nenhuma impressora.

const printer = EasyPrint.connect({
  appName: 'Meu ERP',
  routes: { pedido: 'Pedidos (cozinha)', etiqueta: 'Etiquetas de envio', danfe: 'Notas fiscais' },
});

await printer.printRaw(zpl, { route: 'etiqueta' });   // sai na impressora escolhida para "etiqueta"

As finalidades aparecem sozinhas no painel do EasyPrint (Impressoras → Finalidades), com um seletor de impressora para cada uma. Enquanto o lojista não escolhe, a impressão sai na padrão e o resultado avisa com routedBy: 'default-fallback'.

ERP e e-commerce

Impressão pela nuvem

Para imprimir sem nenhuma tela aberta. Por exemplo: chegou um pedido às 3h e a etiqueta já sai na expedição. O seu back-end assina o trabalho, o relay guarda na fila e o EasyPrint da loja busca e imprime.

const { EasyPrintCloud } = require('./easyprint-cloud');   // SDK de servidor, sem dependências
const cloud = new EasyPrintCloud({ relayUrl, apiKey, privateKey, publicKey });

// 1x por loja: guarde deviceId + deviceSecret (segredo); o lojista cola o código (uso único)
const { deviceId, deviceSecret, connectionCode } = await cloud.createDevice('Loja Centro');
const device = { deviceId, deviceSecret };

// a qualquer momento, do servidor
await cloud.print(device, { route: 'etiqueta', raw: { text: zpl } });   // cifrado + assinado
await cloud.print(device, { route: 'danfe', pdf: pdfBuffer });

Por que é seguro

  • Assinatura Ed25519 em cada trabalho. A loja só aceita trabalhos assinados pela chave do seu sistema. Nem quem controla o relay consegue forjar uma impressão.
  • Criptografia de ponta a ponta. O pedido é cifrado (AES-256-GCM) para uma chave gerada no computador da loja. O relay só vê bytes cifrados, sem nomes nem endereços.
  • Código de uso único. Depois de conectar, o código não serve mais. E se o relay tentar trocar a chave da loja, o seu servidor percebe e não envia.
  • Amarrado ao computador. Um trabalho emitido para a Loja A é recusado na Loja B.
  • Validade e anti-replay. Trabalhos vencidos são recusados, e cada trabalho imprime uma única vez, mesmo após reiniciar.
  • Gaveta bloqueada por padrão. O lojista libera "Abrir gaveta", "PDF/HTML" e "RAW" por conexão.
  • Sem portas abertas. Só conexões de saída por HTTPS. O token fica protegido com DPAPI no Windows e em arquivo 0600 no Linux.

Use o relay de referência (cloud/relay-server.js) ou implemente o protocolo no seu back-end. A especificação está em reference/erp.md.

Referência

API do SDK

ChamadaO que faz
EasyPrint.connect(opts)Conecta e devolve o cliente. Chamar de novo devolve o mesmo cliente. Opções: appName, routes, downloadUrl, token, ports, autoReconnect, debug.
printer.print(doc, opts)Imprime um builder, {blocks}, um array ou uma string. opts: route, printer, copies, jobName.
printer.printPdf(src, opts)PDF por URL, Blob ou bytes. opts: pages, fit, paperSize, route.
printer.printHtml(html, opts)HTML (string ou elemento da página). JavaScript desligado por padrão.
printer.printText · printImage · printRawAtalhos para texto, imagem e bytes crus.
printer.routes()Finalidades e as impressoras escolhidas pelo lojista.
printer.printers()Lista de impressoras com tipo, papel e colunas.
printer.on('status', fn)Avisa quando o status muda. Devolve a função para cancelar.
printer.ready()Promise que resolve quando dá para imprimir.
printer.diagnose(){ ok, status, title, message, steps[] } em pt-BR, pronto para exibir.
EasyPrint.widget(printer, el)Selo de status com instruções de correção. Isolado em Shadow DOM.
EasyPrint.image(src)Converte uma URL, <img> ou <canvas> em PNG para impressão.

Os tipos completos estão em easyprint.d.ts. Funciona com <script>, import (Vite, Webpack, Next) e require (Node 22+).

Referência

Status e erros

Toda falha vem com code (para o seu código decidir), message (o que houve) e hint (como resolver, escrito para o lojista).

StatusSignificaMostre
readyTudo certo.Indicador verde.
not_runningEasyPrint fechado ou não instalado.Passos e link de download. O SDK tenta reconectar sozinho.
awaiting_approvalEsperando o lojista clicar em Permitir."Confirme no EasyPrint".
browser_blockedO Chrome/Edge bloqueou o acesso local.Cadeado → Acesso à rede local → Permitir.
deniedO site foi bloqueado no EasyPrint.Como desbloquear em "Sites e apps".
unsupported_browserSafari com HTTPS.Sugerir Chrome, Edge ou Firefox.
ErroQuando
PRINTER_NOT_FOUNDA impressora pedida não existe. A hint lista as disponíveis.
NO_DEFAULT_PRINTERO assistente ainda não foi concluído.
PRINT_FAILED · TIMEOUTA impressora recusou ou não respondeu (papel, tampa, cabo, fila do Windows).
INVALID_DOCUMENTBloco com tipo ou campo errado. É bug no código, corrija o documento.
NOT_RUNNING · NOT_AUTHORIZED · DENIEDEquivalem aos status acima.
Receitas

Frameworks

O padrão é sempre o mesmo: um módulo que conecta uma vez, um componente que mostra o status e um try/catch que exibe a dica.

Integração com IA

Deixe a IA integrar por você

Preparamos as instruções no formato que as IAs de programação entendem melhor: o que fazer, em que ordem, os modelos de código por framework e o que não fazer. A IA detecta o seu framework, adiciona o SDK, cria o serviço de impressão, o indicador de status e o tratamento de erros.

Skill · .zip Skill EasyPrint Para Claude Code e outras ferramentas com suporte a skills. Inclui SKILL.md, as referências e o SDK.
Arquivo único · .md EASYPRINT_AI.md Para qualquer IA (ChatGPT, Gemini, Cursor, Copilot, Lovable, Bolt). Traz tudo num arquivo só, inclusive o código do SDK.

Como usar em cada ferramenta

FerramentaOnde colocar
Claude CodeExtraia o .zip em ~/.claude/skills/ (vale para todos os projetos) ou em .claude/skills/ do projeto. Depois peça: "integre impressão com EasyPrint".
Cursor / WindsurfColoque EASYPRINT_AI.md na raiz e cite @EASYPRINT_AI.md no chat.
GitHub CopilotSalve como .github/instructions/easyprint.instructions.md ou anexe com #file.
ChatGPT · Gemini · Claude.aiAnexe EASYPRINT_AI.md e cole o pedido abaixo.
Lovable · Bolt · v0Adicione o arquivo ao projeto (ou cole o conteúdo) e envie o pedido.

Pedido para colar

Integre impressão direta com o EasyPrint neste projeto seguindo o EASYPRINT_AI.md.
Imprima o pedido/recibo (número, itens com observação, totais, cliente,
endereço e pagamento), mostre o status da impressora na barra superior e
exiba a dica de correção quando a impressão falhar. Use o nome "NOME DO SISTEMA".
Por dentro

Segurança

O EasyPrint troca a cadeia de certificados de soluções antigas por regras simples de entender.

  • Gaveta bloqueada e limite de impressões. Nenhum site abre a gaveta sem o lojista liberar. Cada origem tem limite de 120 impressões por minuto, o que segura um site invadido.
  • Só local. Escuta apenas em 127.0.0.1. Nenhuma porta fica aberta para a rede.
  • Permissão por site. O navegador informa o endereço do site (Origin) e a página não consegue falsificá-lo. Cada site novo precisa da aprovação do lojista.
  • Sem certificado raiz. Navegadores já tratam ws://127.0.0.1 como seguro, então não instalamos uma autoridade certificadora no Windows.
  • Painel protegido. Token secreto a cada execução, checagem de Host contra DNS rebinding e de Origin contra CSRF.
  • Apps sem navegador usam tokens revogáveis, guardados apenas como hash SHA-256.
  • Arquivos maliciosos. HTML é renderizado sem scripts, sem rede local e sem acesso a arquivos do computador. Imagens têm limite de tamanho e proteção contra bomba de descompressão.
  • Downloads verificáveis. A release publica o SHA256SUMS, e o instalador do Linux confere o hash antes de instalar.
Contexto

EasyPrint × QZ Tray

O QZ Tray é a referência do mercado e foi estudado para desenhar o EasyPrint. O QZ ainda tem acesso a serial, USB e HID para balanças e leitores. O EasyPrint foca em impressão simples, segura e pronta para ERP.

QZ Tray 2.3EasyPrint 1.0
InstalaçãoAdministrador, CA raiz no Windows, regra de firewallPasta do usuário, sem admin, sem CA
Tamanho140 MB (Java + JavaFX)~90 MB, um único executável
Remover o aviso de site não confiávelCertificado pago (a partir de US$ 449/ano)Um clique em Permitir, grátis
Acentos em térmicasRegressão na 2.3.0 (issue #1519)CP860/CP850 explícitos + teste guiado
IdiomaInglêsPortuguês
ConfiguraçãoPelo código do siteAssistente para o lojista
PDF e HTMLSimSim, inclusive em térmica e etiqueta
Finalidades (impressora por tipo de documento)NãoSim, escolhidas pelo lojista
Impressão pelo servidorNãoSim, assinada e cifrada de ponta a ponta
Serial, USB e HIDSimAinda não
LinuxSimSim (CUPS, USB direto, PDF, HTML)
macOSMaduroBásico (via CUPS, sem binário pronto)
LicençaLGPL 2.1MIT
Ajuda

Perguntas frequentes

Funciona com qual impressora?

Qualquer impressora instalada no Windows. Térmicas ESC/POS (Epson, Elgin, Bematech, Daruma, Tanca, Knup, genéricas POS-58/80), etiquetas ZPL (Zebra, Elgin L42) e impressoras comuns jato de tinta ou laser.

Os acentos saem errados. E agora?

No painel: Impressoras → Ajustar → Acentos. Teste CP860 e depois CP850. O passo de teste do assistente faz isso automaticamente.

Posso imprimir em duas impressoras (cozinha e caixa)?

Sim. Use printer.printers() para listar as impressoras, guarde a escolha nas configurações do seu sistema e passe { printer: 'Cozinha' } no print. Basta parte do nome.

E se o EasyPrint estiver fechado?

O SDK detecta, muda o status para not_running e reconecta sozinho quando o EasyPrint abre. Ative "Abrir quando o Windows iniciar" no painel para isso não acontecer.

Funciona no celular ou tablet?

Não. A impressão acontece no computador onde o EasyPrint está instalado. Para imprimir a partir do celular, envie o pedido para um computador da loja que tenha o EasyPrint aberto.

Funciona no Linux?

Sim. Use o binário easyprint-linux-x64 (ou o script de instalação). Impressoras do CUPS e térmicas USB (/dev/usb/lp*) são detectadas. Se aparecer erro de permissão no USB, rode sudo usermod -aG lp $USER e entre de novo na sessão.

Onde ficam as configurações?

No Windows, em %APPDATA%\EasyPrint\config.json. No Linux, em ~/.config/easyprint/config.json. O log easyprint.log fica na mesma pasta.