Se você já viu a mensagem Access to fetch at '...' has been blocked by CORS policy no console do navegador, conhece bem essa frustração. Os erros de CORS estão entre os problemas mais comuns enfrentados por desenvolvedores web, mas o mecanismo por trás deles costuma ser mal compreendido. Este guia explica o CORS a partir dos fundamentos, para que você consiga corrigir esses erros — e entender por que eles existem.
O que é a Same-Origin Policy?
Os navegadores aplicam uma regra de segurança chamada Same-Origin Policy (SOP), ou política de mesma origem. Duas URLs têm a mesma origem quando compartilham o mesmo protocolo, o mesmo nome de host e a mesma porta.
https://example.com/page1 → https://example.com/page2 ✅ Mesma origem https://example.com → http://example.com ❌ Protocolo diferente https://example.com → https://api.example.com ❌ Nome de host diferente https://example.com → https://example.com:8080 ❌ Porta diferente
A SOP impede que um site malicioso leia dados de outro site. Sem ela, qualquer página da web poderia fazer requisições à API do seu banco usando os seus cookies.
O que é CORS?
CORS (Cross-Origin Resource Sharing, ou Compartilhamento de Recursos entre Origens) é um mecanismo que flexibiliza a Same-Origin Policy. Ele permite que um servidor declare explicitamente quais outras origens podem acessar seus recursos. O servidor comunica isso por meio de cabeçalhos HTTP na resposta.
Como o CORS Funciona
Requisições Simples
Para requisições GET/POST simples com cabeçalhos padrão, o navegador envia a requisição diretamente e verifica os cabeçalhos da resposta:
// O navegador envia:
GET /api/data HTTP/1.1
Host: api.example.com
Origin: https://myapp.com
// O servidor responde:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://myapp.com
Content-Type: application/json
{"data": "..."}
Requisições Preflight (OPTIONS)
Para requisições "não simples" (cabeçalhos personalizados, métodos PUT/DELETE, content type JSON), o navegador primeiro envia uma requisição preflight do tipo OPTIONS para pedir permissão ao servidor.
// 1. O navegador envia o preflight: OPTIONS /api/users HTTP/1.1 Host: api.example.com Origin: https://myapp.com Access-Control-Request-Method: DELETE Access-Control-Request-Headers: Content-Type, Authorization // 2. O servidor responde com os métodos/cabeçalhos permitidos: HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://myapp.com Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Content-Type, Authorization Access-Control-Max-Age: 86400 // 3. O navegador envia a requisição real (somente se o preflight for aprovado)
Cabeçalhos CORS de Resposta
Access-Control-Allow-Origin: https://myapp.com // Quais origens podem acessar Access-Control-Allow-Methods: GET, POST, PUT // Métodos HTTP permitidos Access-Control-Allow-Headers: Content-Type, Auth // Cabeçalhos de requisição permitidos Access-Control-Allow-Credentials: true // Permite cookies/autenticação Access-Control-Max-Age: 86400 // Cache do preflight (segundos) Access-Control-Expose-Headers: X-Request-Id // Cabeçalhos legíveis pelo JS
Configuração do Servidor
import cors from 'cors';
app.use(cors({
origin: ['https://myapp.com', 'https://staging.myapp.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 86400
}));
location /api/ {
add_header Access-Control-Allow-Origin "https://myapp.com" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
if ($request_method = OPTIONS) {
return 204;
}
}
header("Access-Control-Allow-Origin: https://myapp.com");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
Erros Comuns com CORS
- Usar
Access-Control-Allow-Origin: *com credenciais: O navegador vai bloquear essa combinação. Você precisa especificar a origem exata quandocredentials: true. - CORS é um recurso de segurança do navegador: Ele NÃO protege sua API contra requisições de servidor para servidor. Sempre valide a autenticação em cada requisição.
- Esquecer a flag
alwaysno Nginx: Sem ela, os cabeçalhos CORS não são enviados nas respostas de erro (4xx, 5xx). - Não tratar requisições OPTIONS: Se o seu servidor retornar 404 ou 405 para OPTIONS, todas as requisições preflight falham.
Experimente Nossas Ferramentas Gratuitas para Desenvolvedores
Codifique URLs, decodifique Base64 e formate JSON instantaneamente.