Guías

Cómo solucionar errores de CORS (y por qué aparecen)

Un error de CORS significa que tu página web intentó leer una respuesta de un origen distinto (otro dominio, puerto o protocolo), y ese servidor no envió cabeceras que indiquen que está permitido. Los navegadores bloquean la respuesta para proteger a los usuarios. Lo solucionas en el servidor, devolviendo una cabecera Access-Control-Allow-Origin para el origen de tu sitio y gestionando las peticiones preflight OPTIONS; o lo evitas enviando la petición a través de tu propio backend en el mismo origen.

Es uno de los errores más confusos del desarrollo web, porque la petición a menudo sí llega bien al servidor. Esta guía explica qué está pasando y cómo solucionar cada variante.

Qué significa «origen»

Un origen es la combinación de protocolo, dominio y puerto:

URLOrigen
https://myapp.com/dashboardhttps://myapp.com
https://api.myapp.com/usershttps://api.myapp.com (subdominio distinto, así que origen distinto)
http://localhost:5173http://localhost:5173
http://localhost:3000http://localhost:3000 (puerto distinto, así que origen distinto)

Los navegadores siguen la política del mismo origen: el JavaScript de una página puede leer libremente las respuestas de su propio origen, pero no las de otros. CORS (Cross-Origin Resource Sharing) es el sistema que permite a un servidor optar por ello: «las respuestas de mi servidor pueden ser leídas por páginas de estos orígenes».

Dos consecuencias sorprenden a la gente:

  • La petición a menudo llega al servidor. CORS normalmente impide que tu código lea la respuesta, no que el servidor reciba la petición. Un POST puede haberse guardado aunque viste un error.
  • Solo los navegadores lo aplican. curl, Postman y el código del lado del servidor ignoran CORS por completo. Por eso «funciona en Postman» no dice nada sobre CORS.

Paso 1: lee el error exacto

Abre las herramientas de desarrollo (clic derecho → Inspeccionar), ve a la Consola y lee el mensaje completo. La redacción de Chrome indica qué problema tienes:

El mensaje contieneQué falla
No 'Access-Control-Allow-Origin' header is presentEl servidor no envió la cabecera, o la petición falló antes de llegar a tu código de CORS (por ejemplo un 404 o un 500)
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied originEl servidor permite un origen distinto al tuyo
Response to preflight request doesn't pass access control checkFalló la petición preflight OPTIONS
...must not be the wildcard '*' when the request's credentials mode is 'include'Envías cookies, y el servidor respondió con *
Request header field authorization is not allowedEl servidor no incluyó esa cabecera en Access-Control-Allow-Headers

Después abre la pestaña Red (Network), busca la petición que falla (y cualquier petición OPTIONS anterior) y mira su código de estado y las cabeceras de respuesta.

Comprueba primero el código de estado. Muchos «errores de CORS» son en realidad un error del servidor disfrazado. Si el servidor se cae o devuelve un 404, su respuesta de error a menudo no tiene cabeceras de CORS, así que el navegador informa de CORS en lugar del problema real. Arregla el 500 o el 404, y el error de CORS puede desaparecer.

Paso 2: decide si deberías llamar a esa API desde el navegador

Antes de añadir cabeceras, pregúntate: ¿debería el navegador llamar directamente a esta API?

  • Una API de terceros que necesita una clave secreta (OpenAI, la clave secreta de Stripe, la mayoría de servicios de correo) nunca debería llamarse desde el navegador. La clave sería visible para cada visitante. Llámala desde tu backend, y el problema de CORS desaparece, porque las peticiones de servidor a servidor no están sujetas a CORS. Consulta cómo mantener a salvo tus claves de API.
  • Una API de terceros que no controlas y que no envía cabeceras de CORS no puede arreglarse desde tu lado. Llámala desde tu backend.
  • Tu propia API puede arreglarse configurándola correctamente. Sigue leyendo.

Paso 3: arréglalo en tu servidor

El servidor debe añadir las cabeceras correctas a sus respuestas, incluidas las de error.

Para la petición real, envía:

  • Access-Control-Allow-Origin: https://myapp.com (el origen exacto de tu front end, sin barra final)
  • Vary: Origin, si el valor depende de qué origen lo pidió

Para la petición preflight OPTIONS, responde con un estado de éxito (200 o 204) y:

  • Access-Control-Allow-Origin: https://myapp.com
  • Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE
  • Access-Control-Allow-Headers: Content-Type, Authorization (cada cabecera personalizada que envíes)
  • Opcionalmente Access-Control-Max-Age: 600, para que el navegador guarde el preflight durante un tiempo

La mayoría de frameworks tienen un paquete o una opción que hace esto. En Express, el paquete cors; en FastAPI, CORSMiddleware; en ASP.NET Core, AddCors; en Spring, @CrossOrigin o una configuración de CORS. Una configuración típica en Express:

import cors from "cors";

app.use(cors({
  origin: ["https://myapp.com", "http://localhost:5173"],
  credentials: true,
}));

Coloca el gestor de CORS antes de tus rutas y de la autenticación, para que las peticiones preflight (que no llevan inicio de sesión) no sean rechazadas con un 401.

Con un creador con IA, describe la configuración con precisión:

El front end en https://myapp.com llama a la API en https://api.myapp.com y recibe «Response to preflight request doesn't pass access control check». Configura CORS en la API para permitir exactamente https://myapp.com y el origen de la vista previa, permite GET, POST, PATCH y DELETE con las cabeceras Content-Type y Authorization, gestiona OPTIONS antes de la autenticación e incluye también las cabeceras de CORS en las respuestas de error.

Paso 4: gestiona las cookies y las credenciales

Si tu front end envía cookies (por ejemplo, una sesión de inicio de sesión) a otro origen, ambos lados deben estar de acuerdo:

  • El front end establece credentials: "include" en fetch, o withCredentials: true en axios.
  • El servidor envía Access-Control-Allow-Credentials: true.
  • El Access-Control-Allow-Origin del servidor debe ser el origen exacto, no *.

Las cookies entre sitios también necesitan SameSite=None; Secure en la cookie, y algunos navegadores restringen aún más las cookies de terceros. Es una razón más para preferir el enfoque del Paso 5.

Paso 5: evita CORS con una configuración de mismo origen

A menudo la solución más limpia es no hacer peticiones entre orígenes en absoluto. Sirve la API desde el mismo origen que la página, por ejemplo en https://myapp.com/api/...:

  • En desarrollo, la mayoría de servidores de desarrollo pueden actuar de proxy. La opción server.proxy de Vite puede reenviar /api a tu backend en otro puerto, de modo que el navegador solo se comunique con un origen.
  • En producción, enruta /api al backend mediante las reescrituras o la configuración de proxy de tu hosting, o sirve el front end y la API desde un mismo servidor.

El front end llama entonces a una ruta relativa como fetch("/api/orders"). No hay petición entre orígenes, ni preflight entre orígenes, ni quebraderos de cabeza con cookies. Además, significa que no fijas en el código un dominio de API que sea distinto en la vista previa y en producción.

Cambia el front end para llamar al backend con rutas relativas /api en lugar de una URL completa, y configura un proxy de desarrollo para que /api se reenvíe al servidor de la API. Después elimina las configuraciones de CORS que ya no necesitemos.

Qué no hacer

  • mode: "no-cors" en fetch. No salta nada; le da a tu código una respuesta vacía e ilegible.
  • Extensiones del navegador que desactivan CORS. Solo cambian tu navegador. Cada visitante seguirá viendo el error.
  • Servicios públicos de «proxy CORS» para apps reales. Pueden leer y modificar todo lo que pasa por ellos, y se caen.
  • Access-Control-Allow-Origin: * en una API que usa inicios de sesión. De todos modos no funciona con credenciales, y es el valor por defecto equivocado para datos privados.
  • Devolver cualquier cabecera Origin tal cual con las credenciales permitidas. Eso permite que cualquier sitio web haga peticiones autenticadas en nombre de tus usuarios. Usa una lista de permitidos.

Causas habituales en apps creadas con IA

SituaciónSolución
El front end llama a una API de terceros con una clave secretaMueve la llamada al backend
Funciona en la vista previa, falla en el dominio publicadoAñade los orígenes publicado y del dominio personalizado a la lista de permitidos, o usa rutas relativas /api
El error solo aparece en POST, PUT o DELETEEl preflight no se gestiona; añade gestión de OPTIONS y las cabeceras permitidas
El error apareció al añadir el inicio de sesiónLas credenciales necesitan un origen exacto y Allow-Credentials
«Error de CORS» pero la pestaña Red muestra un 500Arregla primero el error del servidor
URL de API fijada en localhostUsa rutas relativas o una configuración por entorno

CORS en Mythex

Cuando un proyecto de Mythex tiene un sitio web y un servidor de API, ambos se ejecutan como servicios dentro del mismo proyecto, y puedes cambiar entre ellos en la vista previa. Pedir al agente que el front end llame al backend mediante una ruta relativa /api, con proxy en desarrollo, evita la mayoría de problemas de CORS. Si de verdad necesitas llamadas entre orígenes, dale al agente el error exacto de la consola y los orígenes implicados. Comprueba el resultado también en la app publicada, ya que su dirección es distinta a la de la vista previa. Consulta Apps de varios servicios y backends de API en la documentación, y nuestras guías sobre cómo depurar una app creada con IA y front end frente a back end.

Lista de comprobación de CORS

  • Leíste el error completo de la consola y el código de estado de la petición que falla
  • Descartaste un 404 o un 500 ocultos
  • Las API con clave secreta se llaman desde el backend, no desde el navegador
  • El servidor envía Access-Control-Allow-Origin con los orígenes permitidos exactos
  • La petición preflight OPTIONS se responde con los métodos y cabeceras permitidos, antes de la autenticación
  • Las cabeceras de CORS están presentes también en las respuestas de error
  • Credenciales: origen exacto, Allow-Credentials: true y configuración de cookies correcta
  • Están cubiertos los orígenes de la vista previa, el publicado y el dominio personalizado, o se usan rutas relativas /api
  • No hay atajos de no-cors, proxies públicos ni devolución de cualquier origen

Preguntas

¿Qué significa un error de CORS?

Tu página, cargada desde un origen, intentó leer una respuesta de un origen distinto, y la respuesta de ese servidor no incluía las cabeceras que lo permiten. El navegador impide que tu código lea la respuesta. La solución está en el servidor, o en cómo se enruta la petición, no en el código del front end.

¿Puedo solucionar un error de CORS desde el front end?

No de forma correcta. Opciones como mode: 'no-cors' solo ocultan la respuesta a tu código. Se soluciona haciendo que el servidor envíe la cabecera Access-Control-Allow-Origin adecuada, o llamando a la API desde tu propio backend o desde un proxy del mismo origen.

¿Es seguro Access-Control-Allow-Origin: *?

Está bien para datos públicos que cualquiera puede leer, como una API pública sin inicio de sesión. No puede usarse con cookies ni con otras credenciales, y para APIs privadas debes listar los orígenes exactos que están permitidos.

¿Por qué mi petición funciona en Postman o curl pero no en el navegador?

CORS lo aplican únicamente los navegadores. Herramientas como Postman y curl no lo aplican, así que una petición puede funcionar allí y aun así bloquearse cuando la hace el JavaScript de la página.

¿Qué es una petición preflight?

En peticiones que no son simples, como un POST con JSON o una que lleva una cabecera Authorization, el navegador envía primero una petición OPTIONS para preguntar al servidor qué métodos y cabeceras están permitidos. Si esa petición OPTIONS falla o no tiene las cabeceras correctas, la petición real nunca se envía.

Mythex · Pricing · Crea lo que quieras con IA · Plantillas de sitios web y apps · Mythex comparado · Glosario para crear apps con IA · Herramientas gratis para crear apps con IA · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)