Por qué pasa: el navegador aplica la Same-Origin Policy. Un origen es la combinación esquema + host + puerto, así que http://localhost:3000 y http://localhost:8080 son orígenes distintos. Postman no es un navegador y no aplica esa política, por eso funciona ahí.
Qué es CORS: un mecanismo para que el servidor declare qué orígenes externos pueden leer sus respuestas.
Para requests "no simples" (por ejemplo con Content-Type: application/json, métodos PUT/DELETE o headers como Authorization) el navegador manda antes un preflight OPTIONS.
El servidor responde con Access-Control-Allow-Origin, Access-Control-Allow-Methods y Access-Control-Allow-Headers.
Si usás cookies, hace falta Access-Control-Allow-Credentials: true y en ese caso el origin no puede ser *.
Cómo lo resuelvo: configurando el backend con una lista blanca de orígenes, no desactivando la seguridad del navegador ni poniendo * por defecto. Código: javascript
En desarrollo también sirve un proxy del dev server para que front y API compartan origen.
Ojo: CORS no protege al servidor; solo controla qué puede leer el navegador. Una request puede llegar igual al backend, así que la autenticación, autorización y protección CSRF siguen siendo necesarias.
Errores comunes
Decir que CORS es una protección del servidor o que se arregla en el frontend. Resolverlo con Access-Control-Allow-Origin: * junto con credenciales, o reflejando cualquier Origin sin validar.
Redactado con el asistente Underc0de IA. Actualizado el 15/11/2026. ¿Ves un error? Contanos en el foro.