Como Corrigir Erro CORS no Express + React (Guia 2026)

Publicado em marco de 2026 • 8 min de leitura

O que e o Erro CORS?

Se voce ja construiu um frontend React que se comunica com um backend Express.js, quase certamente ja viu este erro no console do navegador:

Access to fetch at 'http://localhost:3001/api/data' from origin 'http://localhost:3000'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource.

CORS significa Cross-Origin Resource Sharing (Compartilhamento de Recursos entre Origens). E um mecanismo de seguranca do navegador que restringe requisicoes HTTP feitas de uma origem (dominio + porta + protocolo) para uma origem diferente. O navegador aplica essa politica — nao o servidor. Quando uma requisicao cruza origens, o navegador primeiro verifica se o servidor permite isso procurando headers HTTP de resposta especificos, principalmente Access-Control-Allow-Origin.

Se esses headers estiverem ausentes ou incorretos, o navegador bloqueia a resposta e lanca o erro CORS — mesmo que o servidor tenha retornado 200 OK. Isso nao e um bug do Express. E o navegador fazendo exatamente o que deveria fazer.

Por que o CORS Acontece no React + Express?

Em uma configuracao tipica de desenvolvimento React + Express, voce executa dois servidores separados:

  • Servidor de dev React: http://localhost:3000 (Create React App) ou http://localhost:5173 (Vite)
  • Servidor API Express: http://localhost:3001 (ou outra porta)

Como as portas sao diferentes, o navegador trata esses como origens diferentes. Qualquer chamada fetch ou axios do seu app React para a API Express e uma requisicao cross-origin, e o navegador vai bloquea-la a menos que seu servidor Express permita explicitamente.

Em producao, o problema frequentemente desaparece — se voce faz deploy de ambos no mesmo dominio (por ex., Next.js servindo ambos, ou um reverse proxy Nginx roteando /api para o Express) — mas durante o desenvolvimento, erros CORS sao quase garantidos se voce executar os dois servidores separadamente.

Correcao Rapida: Instalar o Middleware cors

A forma mais rapida de corrigir CORS no Express e usar o pacote oficial cors do npm. Instale-o:

npm install cors

Depois adicione ao seu app Express antes de qualquer definicao de rota:

// server.js (ou app.js)
const express = require('express');
const cors = require('cors');

const app = express();

// Permitir todas as origens — use apenas em desenvolvimento
app.use(cors());

app.use(express.json());

app.get('/api/data', (req, res) => {
  res.json({ message: 'Hello from Express!' });
});

app.listen(3001, () => {
  console.log('Server running on http://localhost:3001');
});

Chamar app.use(cors()) sem argumentos adiciona Access-Control-Allow-Origin: * a todas as respostas, o que permite requisicoes de qualquer origem. Isso e ok para desenvolvimento local, mas nao deve ser usado em producao para APIs que lidam com dados autenticados.

Configuracao para Producao

Para producao, sempre especifique exatamente quais origens sao permitidas, e configure credenciais, metodos e headers explicitamente:

const corsOptions = {
  origin: function (origin, callback) {
    const allowedOrigins = [
      'https://www.yourdomain.com',
      'https://yourdomain.com',
      'http://localhost:3000',   // Manter para dev local
      'http://localhost:5173',   // Servidor dev Vite
    ];
    // Permitir requisicoes sem origin (ex: curl, Postman, server-to-server)
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error(`CORS blocked for origin: ${origin}`));
    }
  },
  credentials: true,           // Permitir cookies e headers Authorization
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
  exposedHeaders: ['Content-Range', 'X-Content-Range'],
  maxAge: 86400,               // Cache da resposta preflight por 24 horas
};

app.use(cors(corsOptions));

// Tratar explicitamente requisicoes preflight para todas as rotas
app.options('*', cors(corsOptions));

Alguns pontos-chave sobre esta configuracao:

  • credentials: true — Necessario se seu app React envia cookies ou headers Authorization. Quando isso esta definido, origin nao pode ser *; deve ser uma origem especifica.
  • app.options('*', cors()) — Navegadores enviam uma requisicao HTTP OPTIONS (preflight) antes de qualquer requisicao nao simples (PUT, PATCH, DELETE ou requisicoes com headers customizados). O Express deve responder a essas, ou a requisicao real sera bloqueada.
  • maxAge — Diz ao navegador por quanto tempo cachear a resposta preflight, reduzindo requisicoes OPTIONS desnecessarias.

Alternativa: Proxy do React para Desenvolvimento

Se voce esta usando Create React App, pode evitar CORS totalmente durante o desenvolvimento adicionando um campo proxy ao seu package.json. Isso diz ao dev server webpack para encaminhar requisicoes API ao seu backend Express:

// package.json (raiz do projeto React)
{
  "name": "my-react-app",
  "version": "1.0.0",
  "proxy": "http://localhost:3001",
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build"
  }
}

Agora, quando seu codigo React chama fetch('/api/data') (note: sem hostname), o dev server encaminha a requisicao para http://localhost:3001/api/data — mesma origem, sem CORS. Essa abordagem so funciona em desenvolvimento; em producao, seu deploy deve cuidar do roteamento.

Configuracao de Proxy do Vite

Se voce esta usando Vite (a alternativa moderna ao Create React App), configure o proxy no vite.config.js:

// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: {
    port: 5173,
    proxy: {
      // Todas as requisicoes comecando com /api sao encaminhadas ao Express
      '/api': {
        target: 'http://localhost:3001',
        changeOrigin: true,
        secure: false,
        // Opcional: reescrever path se suas rotas Express nao comecam com /api
        // rewrite: (path) => path.replace(/^\/api/, ''),
      },
    },
  },
});

Com essa configuracao, uma chamada a fetch('/api/users') no seu componente React e encaminhada para http://localhost:3001/api/users. Nao precisa de headers CORS durante o desenvolvimento. Seu servidor Express fica limpo.

Erros Comuns

1. Usar origin wildcard com credentials

Essa combinacao sempre falha. Navegadores rejeitam uma resposta CORS que tem Access-Control-Allow-Origin: * junto com Access-Control-Allow-Credentials: true:

// Isso NAO vai funcionar — navegador rejeita wildcard + credentials
app.use(cors({
  origin: '*',          // Wildcard
  credentials: true,    // Nao pode combinar esses
}));

Correcao: substitua '*' por uma string de origem especifica ou uma funcao que valida origens, como mostrado na configuracao de producao acima.

2. Handler OPTIONS ausente para preflight

Se seu app Express nao trata requisicoes OPTIONS, verificacoes preflight para PUT, PATCH, DELETE e requisicoes com headers customizados receberao um 404, e a requisicao real nunca e enviada. Sempre adicione app.options('*', cors(corsOptions)) antes das suas definicoes de rota.

3. Definir headers CORS manualmente e com o pacote cors

Definir duas vezes o header Access-Control-Allow-Origin faz o navegador ver um valor duplicado e bloquear a requisicao. Escolha uma abordagem — o middleware cors ou headers manuais — e use apenas uma. Nunca faca ambos.

4. Middleware CORS adicionado depois das rotas

Middleware no Express executa na ordem em que e registrado. Se voce adiciona app.use(cors()) depois dos seus route handlers, as rotas sao encontradas primeiro e os headers CORS nunca sao adicionados. Sempre coloque o middleware CORS no topo da sua pilha de middleware.

Depurando Erros CORS

Quando voce encontra um erro CORS, a mensagem no console do navegador diz qual header esta faltando ou nao corresponde. Verificar a aba Network no DevTools mostra os headers de resposta reais retornados pelo seu servidor Express — compare-os com o esperado.

Coisas comuns para verificar:

  • Access-Control-Allow-Origin esta presente na resposta?
  • A origem no header corresponde exatamente a origem do seu app React (incluindo protocolo e porta)?
  • Para requisicoes com credenciais: Access-Control-Allow-Credentials: true esta presente?
  • Para requisicoes PUT/DELETE: o preflight OPTIONS retornou 200 com Access-Control-Allow-Methods?
  • Voce esta enviando um header customizado (como Authorization)? Ele deve aparecer em Access-Control-Allow-Headers.

Depure Seu Erro CORS Instantaneamente

Cole sua mensagem de erro CORS e obtenha o codigo de correcao exato para Express, Nginx, Apache e mais — sem adivinhacao.

Abrir Debugger CORS →

Ferramentas Relacionadas