EmailCheckerEmailChecker

EmailChecker vs mails.so — comparativo técnico

Comparativo técnico honesto entre EmailChecker e mails.so: endpoints, auth, response shape, rate limits, webhooks e um diff real de migração para devs que querem decidir com código.

Por João Costa (Engenharia)·Publicado em 12/06/2026·8 min de leitura

EmailChecker vs mails.so — comparativo técnico

Antes de entrar no código: esse artigo não foi escrito pra te convencer a migrar. Foi escrito porque essa é a pergunta que aparece com mais frequência no nosso suporte dev — "já uso mails.so, vale a pena trocar?" — e a resposta honesta é "depende". Vou mostrar exatamente do que depende.

Se quiser a versão long-form com benchmarks de cobertura e análise de planos, tem em comparativo mails.so vs EmailChecker com dados de cobertura. Aqui o foco é: código, diff de migração, e quando não migrar.


Contexto: por que comparar esses dois

mails.so e EmailChecker resolvem o mesmo problema na superfície — validar se um endereço de email existe e aceita mensagens antes de você enviar. A diferença começa quando você vai além do check básico de formato.

mails.so é um serviço europeu (preços em EUR), com planos bem definidos e uma proposta de "no-code first" — Zapier e Make são cidadãos de primeira classe na documentação deles. A API existe e funciona, mas a experiência de dev não é o foco central do produto.

EmailChecker nasceu API-first. A decisão arquitetural mais visível disso é que toda a lógica de validação que o dashboard exibe é a mesma que você acessa via API — sem endpoints "lite" para integrações e endpoints "completos" só no portal.

Com isso dito, vamos ao que interessa.


Endpoints: mapeamento direto

Operação mails.so EmailChecker
Validar email (single) GET /v1/validate?email= GET /v1/verify?email=
Validar email (single) POST /v1/validate POST /v1/verify
Validação em lote POST /v1/validate/bulk POST /v1/bulk
Status de job em lote GET /v1/bulk/{job_id} GET /v1/bulk/{job_id}/status
Download resultado bulk GET /v1/bulk/{job_id}/result GET /v1/bulk/{job_id}/results
Saldo de créditos GET /v1/account GET /v1/account/credits
Webhooks (config) painel web POST /v1/webhooks

O mapeamento é quase 1:1. A diferença que vai te custar tempo não é o path — é o shape da resposta, que cobre a seção seguinte.

Documentação completa de todos os endpoints na referência da API REST. A seção 8 do guia de validação de email via API cobre especificamente o drop-in replacement.


Auth: troca de header, mesma ideia

mails.so usa um header proprietário:

x-mails-api-key: mso_sua_chave_aqui

EmailChecker usa o padrão Bearer do RFC 6750:

Authorization: Bearer ec_sua_chave_aqui

Na prática, é uma linha de diff no seu cliente HTTP. Se você usa uma constante API_KEY_HEADER, é literalmente uma mudança de string. O prefixo da chave também muda (mso_ para ec_) — guarde isso pro momento de rotacionar as credenciais, porque copiar e colar a chave antiga vai gerar 401 silencioso.


Response shape: campo a campo

Aqui mora a maior parte do trabalho de migração. Os campos têm nomes diferentes, e alguns conceitos não têm equivalente direto.

Conceito mails.so EmailChecker Observação
Status geral result status Valores diferentes — ver abaixo
Email normalizado email email Igual
Domínio domain domain Igual
MX existe mx (bool) mx_found (bool) Renomeado
SMTP respondeu smtp (bool) smtp_valid (bool) Renomeado
Descartável disposable (bool) disposable (bool) Igual
Role account role (bool) role_account (bool) Renomeado
Score de risco score (0–100) Só no EC
Sugestão de correção did_you_mean suggestion Renomeado
Catch-all catch_all (bool) Só no EC
Tempo de resposta latency_ms Só no EC
Mensagem de erro error error.code + error.message EC estrutura o erro

Valores do campo de status

mails.so retorna result com: "valid", "invalid", "risky", "unknown"

EmailChecker retorna status com: "valid", "invalid", "catch_all", "disposable", "unknown"

Perceba que "risky" do mails.so é um conceito composto — pode significar catch-all, role account ou score alto de risco. No EC, esses casos são campos separados, então sua lógica de decisão fica mais granular. Isso é bom, mas exige que você reescreva os ifs que dependem de result === "risky".


Rate limits: números concretos

mails.so publica os seguintes limites por plano:

  • Pro (10k validações/mês): 10 req/s
  • Business (50k/mês): 30 req/s
  • Unlimited: 60 req/s

EmailChecker opera com os seguintes limites:

  • Starter (5k/mês): 5 req/s
  • Growth (25k/mês): 20 req/s
  • Scale (100k/mês): 50 req/s
  • Pro (500k/mês): 100 req/s

Nos dois serviços, o header X-RateLimit-Remaining está presente na resposta. No EC, Retry-After é enviado automaticamente no 429 — você pode implementar um retry com backoff exponencial sem precisar adivinhar o cooldown.

Se o seu caso de uso é bulk assíncrono, rate limit de single-endpoint importa menos — os dois serviços processam jobs em lote sem contar cada validação individual contra o rate limit da API síncrona.


Webhooks: anatomia de um evento

mails.so não expõe configuração de webhook via API — você configura no painel e não tem controle programático. O payload que chega é assim:

{
  "event": "bulk.completed",
  "job_id": "mso_job_abc123",
  "completed_at": "2026-06-12T14:32:00Z",
  "summary": {
    "total": 1000,
    "valid": 847,
    "invalid": 103,
    "risky": 50
  }
}

No EmailChecker, você registra webhooks via API e recebe um secret para validar a assinatura HMAC-SHA256:

{
  "event": "bulk.completed",
  "job_id": "ec_job_xyz789",
  "timestamp": "2026-06-12T14:32:00Z",
  "signature": "sha256=a1b2c3...",
  "data": {
    "total": 1000,
    "valid": 851,
    "invalid": 99,
    "catch_all": 28,
    "disposable": 12,
    "unknown": 10
  }
}

A diferença prática: você consegue verificar a autenticidade do webhook no EC. Com mails.so, qualquer POST no endpoint vai ser processado — você precisa implementar algum token secreto na URL ou aceitar o risco. Se você vai consumir esses eventos em produção, vale ler antes os padrões de arquitetura para webhooks de validação — HMAC, idempotência e dead letter queue.


Diff de migração: código real

Caso 1: validação single, Node.js

- const API_URL = 'https://api.mails.so/v1/validate';
+ const API_URL = 'https://api.emailchecker.com.br/v1/verify';

  async function validateEmail(email) {
    const res = await fetch(`${API_URL}?email=${encodeURIComponent(email)}`, {
      headers: {
-       'x-mails-api-key': process.env.MAILS_API_KEY,
+       'Authorization': `Bearer ${process.env.EC_API_KEY}`,
      }
    });
    const data = await res.json();

-   return data.result === 'valid';
+   return data.status === 'valid';
  }

Caso 2: response parsing com mais campos

  function parseValidationResult(data) {
    return {
-     isValid: data.result === 'valid',
-     isRisky: data.result === 'risky',
-     isDisposable: data.disposable,
-     hasMX: data.mx,
-     suggestion: data.did_you_mean,
+     isValid: data.status === 'valid',
+     isRisky: data.score > 60,           // granular agora
+     isCatchAll: data.catch_all,          // campo novo
+     isDisposable: data.disposable,
+     isRoleAccount: data.role_account,    // renomeado
+     hasMX: data.mx_found,               // renomeado
+     suggestion: data.suggestion,         // renomeado
    };
  }

Caso 3: webhook handler com validação de assinatura (EC only)

// Novo código necessário no EC — não existe equivalente no mails.so
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

app.post('/webhooks/emailchecker', (req, res) => {
  const sig = req.headers['x-emailchecker-signature'];
  if (!verifyWebhookSignature(req.body, sig, process.env.EC_WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  // processa req.body.data...
  res.sendStatus(200);
});

Caso 4: bulk com polling (Python)

  import requests

- BASE = 'https://api.mails.so/v1'
- HEADERS = {'x-mails-api-key': os.environ['MAILS_API_KEY']}
+ BASE = 'https://api.emailchecker.com.br/v1'
+ HEADERS = {'Authorization': f"Bearer {os.environ['EC_API_KEY']}"}

  def submit_bulk(emails: list[str]) -> str:
-   r = requests.post(f'{BASE}/validate/bulk', headers=HEADERS, json={'emails': emails})
+   r = requests.post(f'{BASE}/bulk', headers=HEADERS, json={'emails': emails})
    return r.json()['job_id']

  def get_results(job_id: str) -> list:
-   r = requests.get(f'{BASE}/bulk/{job_id}/result', headers=HEADERS)
+   r = requests.get(f'{BASE}/bulk/{job_id}/results', headers=HEADERS)
    return r.json()['results']

Latência típica

Em testes de produção a partir de servidores no Brasil (São Paulo), os números medianos que observamos:

  • mails.so: 280–420 ms para single validation (servidores na Europa)
  • EmailChecker: 80–160 ms para single validation (infraestrutura no Brasil)

Essa diferença tem origem geográfica — mails.so roda na Europa, e a latência transatlântica é o fator principal. Se o seu backend roda em sa-east-1 ou num VPS local, a diferença vai aparecer em produção.

Para bulk, latência de endpoint importa menos — o que importa é throughput de processamento do job, que depende mais de fila interna do que de RTT de rede.


Custo: comparação de planos equivalentes

Volume mensal mails.so EmailChecker
10k validações EUR 4,80/mês (~R$ 29) R$ 39/mês
50k validações EUR 9,80/mês (~R$ 59) R$ 89/mês
100k validações EUR 9,80/mês (~R$ 59) R$ 149/mês
500k validações EUR 49,80/mês (~R$ 300) R$ 349/mês
Ilimitado EUR 49,80/mês (~R$ 300)

mails.so é mais barato em volume absoluto, especialmente nos planos de 50k e 100k. Isso é verdade e merece ser dito. Se você está num plano Business do mails.so e o custo é o driver principal, a troca não se justifica só por preço.


Quando NAO migrar

Honestamente: se você está satisfeito com mails.so, não migre.

Casos específicos onde faz sentido ficar:

Volume baixo com custo como prioridade. Os planos do mails.so são mais baratos em EUR, e se você está num plano de 10k ou 50k validações com orçamento limitado, a diferença de preço supera as vantagens técnicas.

Integração no-code já funcionando. Se você usa mails.so via Zapier ou Make e não tem um backend próprio, a migração não faz sentido — EmailChecker é API-first e o esforço de reconfiguração não vai trazer retorno.

Backend fora do Brasil. Se sua infra roda em us-east-1 ou eu-west-1, a vantagem de latência do EC some — os dois vão ter RTT parecido do ponto de vista do seu servidor.

Sem necessidade de webhooks verificados ou catch-all granular. Se result === 'valid' resolve teu problema e você nunca precisou de mais granularidade, as funcionalidades extras do EC são overhead que você vai ignorar de qualquer forma.

Migrar tem custo real: QA dos campos renomeados, atualização de dashboards internos que usam o shape antigo, rotação de chaves, teste do webhook handler novo. Isso é horas de trabalho de eng, e precisa valer a pena.


Conclusão

A migração de mails.so para EmailChecker é tecnicamente simples — um dia de trabalho para um dev familiarizado com as duas APIs. Os pontos que vão te custar tempo são o remapeamento de campos (especialmente result -> status com semântica diferente) e a lógica de webhook se você usa bulk.

Os motivos que fazem sentido migrar:

  • Latência é importante e você roda no Brasil
  • Você precisa de catch-all detection ou score granular de risco
  • Webhooks verificados via HMAC são um requisito de segurança
  • Você quer configurar webhooks programaticamente, não via painel

Os motivos que não fazem sentido migrar:

  • Custo é o fator principal e você está num plano médio do mails.so
  • Você usa Zapier/Make e não tem backend
  • Tudo que você precisa é valid vs invalid

Se ainda tiver dúvida, a documentação completa da API e a seção 8 do guia de validação de email via API têm exemplos de drop-in para os casos de uso mais comuns. Também tem o comparativo long-form mails.so vs EmailChecker se você quiser os dados de cobertura e benchmark de SMTP por país.

Se a sua dúvida é mais ampla — qual validador escolher no geral, não só entre esses dois — veja o review de 10 ferramentas de validação de email. E se a comparação for entre os dois validadores brasileiros, o comparativo entre EmailChecker e SafetyMails cobre esse caso.


João Costa — Engenharia, EmailChecker

Comece agora

Pronto pra parar de mandar email pra endereço morto?

Comece grátis com 500 créditos. Sem cartão, sem compromisso.