CORS en JavaScript: ¿por qué Postman funciona y el navegador no?

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: cuando el navegador dice "no" y Postman dice "sí"



Imagina la situación: escribes un frontend en JavaScript, haces una solicitud fetch a una API. En respuesta, un error rojo en la consola:



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


Te agarras la cabeza, abres Postman, pegas la misma URL, presionas Enviar — y oh milagro, ¡los datos llegan! ¿El servidor funciona? Funciona. ¿Por qué entonces el navegador bloquea la solicitud?



Esta situación es un clásico del desarrollo web. En Stack Overflow, esta pregunta ha acumulado miles de visitas. Hoy vamos a mirar bajo el capó y entender por qué sucede esto, cómo funciona CORS y cómo solucionarlo. ¡Allá vamos!



¿Qué es CORS y para qué sirve?



CORS (Cross-Origin Resource Sharing) es un mecanismo de seguridad del navegador. Prohíbe que JavaScript de un sitio (por ejemplo, http://localhost:3000) haga solicitudes a otro (por ejemplo, https://api.example.com), a menos que el servidor lo permita explícitamente.



¿Por qué? Para que un atacante no pueda, a través de tu navegador, robar datos de otro sitio. Sin CORS, cualquier script podría leer tu correo, tus cuentas bancarias — un horror.



Pero aquí hay un matiz: CORS solo funciona en el navegador. Postman, curl, las solicitudes del servidor (Node.js, Python) — no verifican CORS. Esta es la primera y principal razón por la que Postman funciona y JavaScript no.



Cómo funciona CORS bajo el capó: en palabras sencillas



Cuando tu JavaScript (por ejemplo, fetch) hace una solicitud de origen cruzado, el navegador hace dos cosas:



  1. Verifica el tipo de solicitud.
  2. Si es necesario, envía una solicitud preflight (OPTIONS).


Solicitud simple vs Preflight



Hay dos tipos de solicitudes de origen cruzado:



  • Solicitud simple — si usas GET, POST o HEAD, y solo cabeceras básicas (Content-Type: text/plain, application/x-www-form-urlencoded, multipart/form-data). El navegador envía la solicitud y mira la cabecera de respuesta Access-Control-Allow-Origin.
  • Solicitud Preflight — si usas cabeceras no estándar (por ejemplo, Authorization), métodos PUT/DELETE, o Content-Type: application/json. El navegador primero envía una solicitud OPTIONS para preguntar: "¿Se puede hacer esta solicitud?"


Aquí hay un ejemplo de preflight en código:



fetch('https://api.example.com/data', {  method: 'POST',  headers: {    'Content-Type': 'application/json', // Esto provoca preflight    'Authorization': 'Bearer my-token'  },  body: JSON.stringify({ key: 'value' })}).then(response => response.json()).then(data => console.log(data)).catch(err => console.error('CORS error:', err));


Si el servidor no responde a OPTIONS con la cabecera correcta Access-Control-Allow-Origin — el navegador bloquea la solicitud principal.



¿Por qué Postman ignora CORS?



Postman no es un navegador. No utiliza la política del mismo origen (Same-Origin Policy). Simplemente envía una solicitud HTTP y recibe una respuesta. No le importa de dónde vino la solicitud — no verifica las cabeceras CORS. El servidor puede devolver cualquier cosa, Postman mostrará la respuesta.



Por lo tanto, cuando pruebas una API con Postman, ves que el servidor funciona. Pero el navegador exige que el servidor permita explícitamente el acceso desde tu dominio.



Cómo solucionar el error CORS: 3 formas reales



1. Configurar el servidor (el camino correcto)



Si tienes acceso al servidor, agrega la cabecera Access-Control-Allow-Origin. Por ejemplo, en Node.js con Express:



const express = require('express');const app = ex                

Blogs

Book Recommendations