Como Corrigir Erros de CORS
“Blocked by CORS policy” é o navegador protegendo seus usuários, não um bug no seu código. A correção é sempre no servidor que recebe a requisição. Este guia explica o que o navegador verifica e traz configurações funcionais para os casos mais comuns.
O que é CORS de fato
Os navegadores bloqueiam o JavaScript em https://app.example.com de ler respostas de outra origem (esquema + host + porta), como https://api.example.com, a menos que esse servidor permita. O servidor faz isso com os headers de resposta Access-Control-Allow-*. Requisições feitas pelo curl, Postman ou pelo seu backend não são afetadas — por isso “funciona no Postman” e falha no navegador.
Leia a mensagem de erro
- “No ‘Access-Control-Allow-Origin’ header is present” — o servidor não enviou headers de CORS, ou retornou uma página de erro (404, 500) sem eles.
- “Response to preflight request doesn’t pass access control check” — a requisição
OPTIONSfalhou: não foi tratada, retornou erro ou não tinha os headers necessários. - “The value of the ‘Access-Control-Allow-Origin’ header must not be the wildcard ‘*’ when credentials mode is ‘include’” — você envia cookies, então o servidor precisa devolver a origem exata.
Veja a requisição com falha em DevTools → Network, ou confira os headers reais da resposta com o HTTP Header Checker.
Requisições simples e preflight
Uma requisição é “simples” se for GET, HEAD ou POST com apenas headers básicos e um corpo de formulário ou texto puro. Qualquer outra coisa — Content-Type: application/json, um header Authorization, PUT ou DELETE — faz o navegador enviar antes uma requisição OPTIONS de preflight. Seu servidor precisa responder com status 204 ou 200 e estes headers:
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 600
Configurações que funcionam
Express com o pacote cors:
const cors = require('cors');
app.use(cors({
origin: ['https://app.example.com'],
credentials: true, // só se você enviar cookies
methods: ['GET', 'POST', 'PUT', 'DELETE'],
}));
Nginx:
location /api/ {
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin "https://app.example.com" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
add_header Access-Control-Max-Age 600;
return 204;
}
add_header Access-Control-Allow-Origin "https://app.example.com" always;
proxy_pass http://backend;
}
A flag always é importante: sem ela o Nginx remove o header em respostas de erro, e o navegador então mostra um erro de CORS no lugar do 500 real. Gere os headers para outros servidores (Vercel, Netlify, Cloudflare Workers, Apache) com o CORS Header Generator.
Cookies e credenciais
Para enviar cookies entre origens, a requisição precisa de credentials: 'include' (fetch) e o servidor deve responder com Access-Control-Allow-Credentials: true e a origem exata — nunca *. O próprio cookie precisa de SameSite=None; Secure. Quando você devolve a origem a partir de uma lista, envie também Vary: Origin para que os caches não entreguem os headers de um site para outro.
O que não fazer
- Não reflita qualquer header
Originde volta com credenciais habilitadas — isso permite que qualquer site leia os dados dos seus usuários. - Não “corrija” CORS com extensão do navegador ou proxy público; isso só esconde o problema na sua máquina.
- Se a API é sua e está no mesmo site, um reverse proxy (mesma origem) elimina o CORS por completo.
Reproduza a requisição do navegador com o API Tester, ou transforme-a em código com o cURL to Code.