Erro de CORS em API: como diagnosticar preflight, origem e credenciais sem gambiarras
Publicado em 2026-08-29T20:12:00Z · atualizado em 2026-08-29T19:12:37+00:00
Um roteiro reproduzível para distinguir falha de rede, erro HTTP e bloqueio CORS, corrigindo a política no servidor em vez de mascarar o navegador.
Por Equipe IATechNerds. Revisão: Revisão humana pendente. Atualizado em 14 de agosto de 2026.
Como este conteúdo foi produzido: Guia original redigido a partir do padrão Fetch e da documentação MDN, com exemplos locais sintéticos. Os comandos foram revisados para não depender de serviços externos; a configuração final deve passar por revisão humana antes da publicação.
Intenção de busca: ajudar quem pesquisa por “erro de CORS”, “preflight OPTIONS falhou” ou “Access-Control-Allow-Origin” a localizar a camada exata do problema e aplicar uma correção segura no servidor.
Você chama uma API com fetch(), vê uma mensagem vermelha sobre CORS no console e conclui que “a API caiu”. Em seguida, o mesmo endereço funciona no navegador, no curl ou no Postman. Essa diferença é a pista principal: CORS não é um teste de disponibilidade da API, e sim uma política aplicada pelo navegador quando uma página tenta ler uma resposta de outra origem.
O diagnóstico correto separa quatro perguntas: a requisição saiu do navegador? Houve um preflight OPTIONS? O servidor respondeu com os cabeçalhos compatíveis com aquela origem, método e conjunto de headers? A aplicação devolveu um status útil? Misturar essas camadas leva a soluções perigosas, como desativar a proteção do navegador, liberar qualquer origem com credenciais ou instalar extensões que apenas escondem o problema no computador do desenvolvedor.
Ao final, você terá uma reprodução mínima, saberá ler o painel de rede e conseguirá propor uma política CORS explícita para desenvolvimento e produção.
O que CORS protege — e o que ele não protege
A política de mesma origem impede que um script carregado de um site leia livremente dados de outro site. Uma origem é formada por esquema, host e porta. Portanto, https://app.exemplo.com e https://api.exemplo.com são origens diferentes; http://localhost:3000 e http://localhost:5173 também. O caminho da URL não participa dessa comparação.
CORS cria um protocolo para o servidor declarar quais origens podem ler suas respostas. Ele não autentica usuários, não substitui autorização e não impede requisições feitas fora do navegador. Uma API privada continua precisando validar sessão, token, escopo e permissão em cada operação. Se um endpoint altera dados, aceitar a origem do front-end não prova que o usuário tem direito de executar a ação.
Também é possível que a requisição chegue ao servidor e produza efeito, mas o navegador esconda a resposta do JavaScript. Por isso, “deu CORS” não significa automaticamente “nada aconteceu”. Em operações de escrita, consulte logs e use identificadores idempotentes antes de repetir a chamada.
Identifique a origem real antes de editar qualquer configuração
Abra o console na página que executa o código e registre location.origin. Não copie apenas o domínio visual: protocolo e porta fazem parte da origem. Em desenvolvimento, a troca de porta é causa frequente de divergência. Em produção, redirecionamentos entre www e o domínio raiz podem mudar a origem efetiva.
console.log(location.origin)
// exemplo: http://localhost:5173No painel de rede, selecione a requisição e procure o header de solicitação Origin. Esse é o valor que a API deve comparar com sua lista permitida. A comparação deve ser exata; não use uma busca parcial como “contém exemplo.com”, pois um host malicioso pode incluir esse texto em outro domínio.
Registre também a URL final depois de redirecionamentos. Um 301 do endpoint HTTP para HTTPS ou de uma rota antiga para outra origem pode transformar uma política correta para a URL inicial em uma resposta incompatível no destino.
Saiba quando o navegador envia um preflight OPTIONS
Algumas chamadas consideradas simples podem seguir diretamente para o método real. Outras exigem uma verificação prévia. O navegador cria automaticamente uma requisição OPTIONS contendo a origem, o método pretendido e, quando necessário, os nomes dos headers não simples. Esse preflight pergunta ao servidor se a chamada pode prosseguir.
Um POST com Content-Type: application/json, um PUT, um DELETE ou o uso de Authorization normalmente leva ao preflight. Você não deve programar o OPTIONS no front-end: implemente a resposta no servidor ou no gateway que recebe a chamada.
No painel de rede, filtre pelo endpoint e observe se há duas linhas. Se o OPTIONS falha, concentre o diagnóstico nele; o método real pode nem ser enviado. Se o preflight passa e a chamada real falha, analise os headers da segunda resposta, o status HTTP e a lógica da aplicação.
Leia os quatro cabeçalhos que explicam a maioria dos casos
Access-Control-Allow-Origin deve conter a origem autorizada ou, em respostas públicas sem credenciais, o curinga. Access-Control-Allow-Methods informa quais métodos o servidor permite no preflight. Access-Control-Allow-Headers precisa cobrir os headers solicitados, como content-type e authorization. Access-Control-Allow-Credentials só é necessário quando a chamada usa credenciais do navegador.
Os nomes dos headers não diferenciam maiúsculas de minúsculas, mas seus valores obedecem regras próprias. Não copie uma lista enorme por tentativa. Compare o que aparece em Access-Control-Request-Method e Access-Control-Request-Headers com a resposta do OPTIONS. A política mínima é mais simples de auditar.
Se a API devolve dinamicamente a origem solicitante, adicione Vary: Origin para que caches não sirvam a política de um site para outro. Um CDN sem essa variação pode criar falhas intermitentes que desaparecem ao limpar o cache.
Credenciais mudam as regras do curinga
Cookies, certificados do cliente e autenticação HTTP entram no modo de credenciais. No fetch, cookies de outra origem não são enviados por padrão; a aplicação pode usar credentials: "include". Nesse cenário, a resposta não pode combinar credenciais com Access-Control-Allow-Origin: *. O servidor precisa devolver uma origem explícita autorizada e Access-Control-Allow-Credentials: true.
fetch('https://api.exemplo.test/perfil', {
credentials: 'include'
})Permitir credenciais amplia o impacto de uma política incorreta. Mantenha uma lista fechada de origens, valide-a no servidor e configure cookies com atributos compatíveis com a arquitetura. CORS não neutraliza CSRF por si só. Uma operação sensível ainda precisa de desenho de sessão e proteção apropriada.
Se a API usa token no header Authorization, o preflight deve permitir esse header. O token não transforma a requisição em “mesma origem” e não deve ser colocado na URL para contornar a política.
Crie uma reprodução mínima que outra pessoa consiga executar
Reduza o caso a um arquivo HTML e a uma chamada sem framework. Remova interceptadores, bibliotecas e tratamentos globais até sobrar o método, a URL, os headers essenciais e o corpo. Uma reprodução pequena mostra se o problema pertence ao navegador, à configuração do cliente ou à infraestrutura.
fetch('https://api.exemplo.test/itens', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({nome: 'teste'})
}).then(async r => ({status:r.status, texto:await r.text()}))
.then(console.log).catch(console.error)Sirva o HTML em uma origem conhecida, por exemplo http://localhost:5173. Abrir pelo esquema file: cria outro contexto e pode atrapalhar a comparação. Guarde o horário, a origem, o endpoint e uma captura textual dos headers; evite incluir tokens no relato.
Reproduza o preflight com curl sem confundir o resultado
O curl não aplica a política CORS, mas pode simular os headers do preflight para inspecionar o que o servidor declara. Isso ajuda a verificar proxies e backends sem depender da interface do navegador.
curl -i -X OPTIONS 'https://api.exemplo.test/itens' -H 'Origin: http://localhost:5173' -H 'Access-Control-Request-Method: POST' -H 'Access-Control-Request-Headers: content-type,authorization'Uma resposta útil costuma ter status de sucesso e os cabeçalhos compatíveis. Se o gateway devolve 404, 405 ou exige autenticação antes de responder ao OPTIONS, a requisição real ficará bloqueada. Configure a rota de preflight para alcançar a camada CORS antes de regras que não entendem esse método.
O sucesso do curl não encerra o teste: volte ao navegador para confirmar a aplicação da política. Use o conversor de curl para código para documentar a chamada e o inspetor de URL para conferir esquema, host e porta.
Diferencie CORS de DNS, TLS, bloqueio de conteúdo e erro HTTP
Se a aba de rede não mostra resposta, procure erros de resolução de nome, certificado, conexão recusada ou conteúdo misto. Uma página HTTPS chamando HTTP pode ser bloqueada antes de CORS. Se há resposta 401, 403, 404 ou 500, a aplicação também tem um problema real, mesmo que o console destaque os headers ausentes.
Erros do backend devem incluir a política CORS quando a origem é permitida. É comum configurar os headers apenas em respostas 200; então uma exceção legítima vira uma mensagem opaca para o front-end. Posicione o middleware CORS cedo o bastante para cobrir respostas de erro, sem ignorar autenticação e autorização.
Extensões de privacidade, proxies corporativos e service workers também podem alterar o caminho. Teste em perfil limpo apenas para isolar a causa, não para “resolver” produção. Registre a diferença observada e volte à configuração que será usada pelos visitantes.
Implemente uma lista de origens, não um reflexo automático
Uma implementação segura compara o header Origin com uma coleção de valores exatos mantida por ambiente. Se houver correspondência, devolve a própria origem e Vary: Origin. Se não houver, responde normalmente sem conceder leitura cross-origin, ou rejeita de acordo com o desenho da API.
const permitidas = new Set([
'https://app.exemplo.com',
'http://localhost:5173'
]);
function origemPermitida(origin) {
return typeof origin === 'string' && permitidas.has(origin);
}Não use endsWith('exemplo.com') sem verificar o limite do host; falsoexemplo.com passaria. Quando subdomínios dinâmicos forem realmente necessários, analise a URL, exija HTTPS e valide o hostname contra uma regra que respeite pontos e o domínio registrável.
Separe desenvolvimento e produção. A origem local pode ser permitida no ambiente de testes, mas não precisa aparecer na configuração pública.
Evite cinco “soluções” que apenas escondem o defeito
- Desativar a segurança do navegador ou iniciar o Chrome com flags permissivas.
- Instalar extensão que injeta headers e concluir que a API está corrigida.
- Usar
mode: "no-cors"esperando ler JSON; a resposta será opaca. - Adicionar
*a todos os headers junto com credenciais. - Criar um proxy público que encaminha qualquer URL sem autenticação nem limites.
Esses atalhos mudam o cliente de teste ou abrem uma superfície nova, mas não definem a política da API. Um proxy de backend pode ser parte legítima da arquitetura quando o navegador não deve chamar o terceiro diretamente. Nesse caso, restrinja destinos, métodos, tamanho, autenticação, tempo e registros; não transforme o proxy em encaminhador genérico.
Também evite alterar método ou tipo de conteúdo apenas para transformar a chamada em “simples”. Se a API espera JSON autenticado, a correção é responder corretamente ao preflight.
Teste a política como contrato e impeça regressões
Inclua testes automatizados para uma origem permitida e outra negada. Verifique o preflight de cada método e conjunto de headers realmente usados. Para endpoints com credenciais, confirme que o curinga não aparece e que a origem retornada é exata. Teste também respostas de erro, pois elas precisam permanecer legíveis para origens autorizadas.
Em integração, envie OPTIONS com Origin, Access-Control-Request-Method e Access-Control-Request-Headers. Depois faça a chamada real. Não basta afirmar que um middleware foi habilitado; valide os bytes que atravessam gateway, CDN e aplicação.
Monitore mudanças na lista de origens como configuração sensível. Uma revisão deve explicar por que a nova origem precisa de acesso, quais ambientes serão afetados e se credenciais estão envolvidas. Essa disciplina evita que uma correção temporária vire uma permissão permanente.
Checklist de revisão antes de encerrar o incidente
- A origem foi copiada de
location.originou do header da requisição? - O painel de rede mostra preflight? Qual foi o primeiro status que falhou?
- Método e headers solicitados aparecem na resposta do
OPTIONS? - A chamada usa cookies ou outra credencial?
- Há origem explícita quando credenciais estão habilitadas?
Vary: Originacompanha respostas dinâmicas?- Respostas de erro também recebem a política correta?
- O teste foi repetido no navegador, não apenas no curl?
- A lista de origens é exata e separada por ambiente?
- Nenhuma extensão ou flag insegura é necessária para o caso funcionar?
Se cada item possui uma evidência, o problema deixa de ser “CORS misterioso” e vira um contrato verificável entre página, navegador, gateway e API.
Fontes e documentação primária
- WHATWG — Fetch Standard, protocolo CORS
- MDN — Cross-Origin Resource Sharing (CORS)
- MDN — Preflight request
Camada extra: como tomar uma decisão melhor neste cenário
Um artigo sobre Erro de CORS em API: como diagnosticar preflight, origem e credenciais sem gambiarras fica mais útil quando separa a solução imediata da decisão que continua válida depois que a tela, a versão do software ou o dispositivo muda.
Um roteiro reproduzível para distinguir falha de rede, erro HTTP e bloqueio CORS, corrigindo a política no servidor em vez de mascarar o navegador. A ideia central pode ser testada com quatro perguntas: o que foi observado, qual hipótese explica o sintoma, qual mudança é reversível e qual evidência prova que funcionou. Esse encadeamento evita que uma coincidência seja confundida com causa e torna o procedimento repetível por outra pessoa.
Qualidade de IA precisa de um teste, não de uma impressão
Para CORS, API, HTTP, JavaScript, escolha três tarefas representativas: uma simples, uma ambígua e uma em que a resposta possa ser conferida em fonte primária. Compare utilidade, rastreabilidade, privacidade, velocidade e quantidade de correção humana necessária. Uma resposta elegante não compensa uma citação inexistente ou uma conclusão que não pode ser reproduzida.
Separe ainda o que pode sair do dispositivo do que deve permanecer local. Dados públicos toleram fluxos diferentes de documentos internos, contratos, informações pessoais ou bases de clientes. A escolha entre processamento local e nuvem deve ser feita pelo risco do conteúdo, não apenas pela conveniência da interface.
Grade de avaliação prática
| Critério | Pergunta | Evidência |
|---|---|---|
| Correção | A resposta bate com a fonte? | Checagem independente |
| Rastreabilidade | É possível localizar de onde veio? | Citação ou trecho verificável |
| Privacidade | Que dado sai do dispositivo? | Política e configuração |
| Esforço | Quanto trabalho humano resta? | Tempo de revisão |
O ponto em que a IA deixa de ajudar
Se a tarefa exige precisão absoluta e a saída não pode ser validada, a automação deve ser limitada a apoio: localizar trechos, organizar opções ou preparar uma primeira versão. A decisão final precisa permanecer com alguém capaz de verificar a fonte e assumir a responsabilidade pelo resultado.
Checklist de fechamento
- Registre o estado inicial antes de alterar qualquer coisa.
- Faça uma mudança por rodada e anote o efeito.
- Teste um caso normal, um caso-limite e o cenário que originalmente falhou.
- Confirme que a solução continua válida depois de reiniciar, reabrir ou repetir o fluxo.
- Guarde uma forma de voltar ao estado anterior quando a alteração for destrutiva.
Esse método acrescenta profundidade sem transformar o artigo em teoria abstrata: o leitor entende por que cada passo existe e como reconhecer quando a situação exige uma decisão diferente.
