Cómo solucionar errores de CORS y problemas comunes de Access-Control-Allow-Origin: Una Guía Completa
Si alguna vez ha creado una aplicación web que realiza peticiones a una API en un dominio diferente, casi con seguridad se ha encontrado con el temido "CORS error". Suele aparecer así en la consola de su navegador:
Access to fetch at 'https://api.example.com' from origin 'https://myapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
En esta guía, explicaremos exactamente qué es CORS, por qué existe y cómo solucionar estos errores de forma definitiva.
1. Mensajes comunes de CORS error
Verá principalmente estos errores en las Herramientas para Desarrolladores de su navegador (pestaña Consola o Red):
blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present ...The 'Access-Control-Allow-Origin' header contains multiple values ...Response to preflight request doesn't pass access control check ...Method NOT ALLOWED ...(cuando el método HTTP como POST o DELETE no está permitido por CORS)
2. ¿Qué es CORS?
CORS (Cross-Origin Resource Sharing) es una característica de seguridad implementada por los navegadores. Evita que un sitio web malicioso realice peticiones a un dominio diferente (como su banco o su API privada) sin permiso.
Por defecto, los navegadores siguen la Política de Mismo Origen (Same-Origin Policy), lo que significa que un script en a.com solo puede solicitar datos de a.com. CORS es el mecanismo que permite que a.com solicite datos de forma segura de b.com si b.com lo permite explícitamente.
3. Principales causas y soluciones
3.1 Falta el encabezado "Access-Control-Allow-Origin"
Este es el error más común. Significa que el servidor al que está solicitando datos no le ha dicho al navegador que su dominio tiene permiso para acceder al recurso.
La Solución:
La corrección DEBE ocurrir en el lado del servidor. Debe añadir el encabezado Access-Control-Allow-Origin a la respuesta.
- Para APIs públicas: Establézcalo en
*(permitir todos). - Para APIs privadas: Establézcalo en su dominio específico (ej.,
https://myapp.com).
3.2 Fallos de CORS preflight
Para peticiones "complejas" (como aquellas con encabezados personalizados o métodos como PUT/DELETE), el navegador envía primero una petición automática OPTIONS. Esto se llama una petición de Preflight (previa).
El Error:
Response to preflight request doesn't pass access control check.
La Solución:
Asegúrese de que su servidor maneje las peticiones OPTIONS y devuelva un estado 200 OK o 204 No Content con los encabezados CORS correctos:
Access-Control-Allow-OriginAccess-Control-Allow-Methods(ej.,GET, POST, OPTIONS, PUT, DELETE)Access-Control-Allow-Headers(ej.,Content-Type, Authorization)
3.3 "Access-Control-Allow-Credentials"
Si envía cookies o encabezados de autorización con su petición (withCredentials: true), las reglas de CORS se vuelven más estrictas.
El Error:
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
La Solución:
- No puede usar
*paraAccess-Control-Allow-Origin. Debe especificar el origen exacto. - También debe añadir el encabezado:
Access-Control-Allow-Credentials: true.
4. Cómo solucionar CORS en diferentes entornos
4.1 Node.js (Express)
La forma más fácil es usar el middleware cors:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors({
origin: 'https://myapp.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true
}));
4.2 Nginx
Añada estas líneas a su bloque server o location:
add_header 'Access-Control-Allow-Origin' 'https://myapp.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
if ($request_method = 'OPTIONS') {
return 204;
}
4.3 Python (Flask)
Use la extensión flask-cors:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app, origins=["https://myapp.com"])
5. FAQ: Preguntas Frecuentes
P: ¿Puedo solucionar un CORS error desde el frontend (JavaScript)?
R: No. CORS es una política de seguridad del lado del servidor aplicada por el navegador. No puede "saltársela" en su código JavaScript. Si no controla el servidor, debe usar un Servidor Proxy (Proxy Server) para obtener los datos por usted.
P: ¿Por qué solo veo errores de CORS en el navegador y no en Postman?
R: Postman es una aplicación independiente, no un navegador web. No aplica la Política de Mismo Origen ni las reglas de CORS. Solo los navegadores web (Chrome, Firefox, etc.) aplican CORS.
P: ¿Cuál es el riesgo de establecer Access-Control-Allow-Origin en "*"?
R: Para datos públicos, no hay riesgo. Sin embargo, para una API que maneja datos de usuario o requiere autenticación, establecerlo en * permite que cualquier sitio web realice peticiones en nombre de un usuario conectado, lo que podría llevar al robo de datos.
6. Tabla resumen de encabezados CORS
| Encabezado | Descripción |
|---|---|
Access-Control-Allow-Origin |
Especifica qué dominios tienen permitido acceder al recurso. |
Access-Control-Allow-Methods |
Especifica qué métodos HTTP (GET, POST, etc.) están permitidos. |
Access-Control-Allow-Headers |
Especifica qué encabezados personalizados se pueden enviar. |
Access-Control-Allow-Credentials |
Indica si la respuesta se puede compartir cuando el flag credentials es true. |
Access-Control-Max-Age |
Especifica cuánto tiempo se pueden cachear los resultados de una petición preflight. |
Errores relacionados
- Cómo solucionar errores de 'Unexpected token in JSON'
- Cómo corregir 'URIError: URI malformed' en JavaScript
- Cómo solucionar 'JWT expired' y errores comunes de JWT