La forma más directa de consumir una API en el navegador hoy en día es con fetch en JavaScript. Esta API nativa reemplazó a XMLHttpRequest y permite hacer peticiones HTTP con muy poco código, especialmente cuando la combinamos con promesas y async/await.
Qué es fetch
fetch en JavaScript es la API estándar del navegador para realizar peticiones HTTP. La función fetch() devuelve una promesa que se resuelve con un objeto Response. Esa promesa solo se rechaza cuando existe un error de red real, como que el usuario esté sin internet o el servidor no responda. Los códigos de error HTTP como 404 o 500 no provocan rechazo, por eso siempre hay que comprobar el estado de la respuesta.
Además de los navegadores, Node.js incluye fetch en JavaScript de forma estable desde la versión 21 (estuvo disponible de forma experimental desde la 18).
Puedes leer la documentación completa en MDN – Fetch API.
Una petición GET paso a paso
Vamos a usar la API pública de prueba JSONPlaceholder. El siguiente ejemplo obtiene un listado de usuarios con fetch en JavaScript usando async/await:
async function obtenerUsuarios() {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) {
throw new Error('Error al obtener los usuarios');
}
const usuarios = await response.json();
console.log(usuarios);
return usuarios;
}
obtenerUsuarios();
El método response.json() lee el cuerpo de la respuesta y lo convierte automáticamente a un objeto JavaScript. También existen response.text(), response.blob() y otros según el tipo de contenido que esperes.
Comprobar errores: response.ok
Como mencionamos, fetch en JavaScript no considera un código 404 o 500 como error de red. Por eso es obligatorio validar response.ok, que devuelve true solo cuando el código de estado está entre 200 y 299.
async function obtenerUsuario(id) {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
if (!response.ok) {
if (response.status === 404) {
throw new Error('Usuario no encontrado');
}
throw new Error(`Error HTTP: ${response.status}`);
}
return await response.json();
}
De esta forma puedes distinguir entre problemas de red y problemas del servidor o recursos inexistentes.
Enviar datos con POST
Para crear recursos necesitamos una petición POST. Con fetch en JavaScript se indica el método, las cabeceras y el cuerpo convertido a JSON:
async function crearUsuario() {
const nuevoUsuario = {
name: 'Ana García',
username: 'anagarcia',
email: '[email protected]'
};
const response = await fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(nuevoUsuario)
});
if (!response.ok) {
throw new Error('No se pudo crear el usuario');
}
const usuarioCreado = await response.json();
console.log(usuarioCreado);
return usuarioCreado;
}
JSONPlaceholder devuelve el objeto que enviamos añadiéndole un id simulado, lo que permite probar el flujo completo sin necesidad de una API real.
Cancelar o limitar el tiempo de una petición
A veces es necesario cancelar una petición o limitar cuánto tiempo estamos dispuestos a esperar. fetch en JavaScript soporta esto mediante AbortController.
async function obtenerConTimeout() {
const controller = new AbortController();
// Aborta automáticamente después de 5 segundos
const timeoutId = setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users', {
signal: controller.signal
});
clearTimeout(timeoutId);
const data = await response.json();
return data;
} catch (error) {
if (error.name === 'AbortError') {
console.log('La petición fue cancelada');
} else {
console.error(error);
}
}
}
Desde hace poco también podemos usar AbortSignal.timeout(ms) de forma más directa:
const response = await fetch(url, {
signal: AbortSignal.timeout(8000)
});
CORS en dos minutos
CORS (Cross-Origin Resource Sharing) es un mecanismo de seguridad del navegador. Cuando haces fetch en JavaScript a un dominio distinto del que cargó tu página, el navegador bloquea la lectura de la respuesta si el servidor no envía las cabeceras adecuadas.
La cabecera más importante es Access-Control-Allow-Origin. Si el servidor la incluye con el valor * o con tu dominio específico, el navegador permite leer los datos. JSONPlaceholder permite peticiones desde cualquier origen, por eso funciona en ejemplos y pruebas.
Si ves el error “CORS policy blocked”, el problema está en el servidor, no en tu código de fetch en JavaScript.
Mostrar los datos en la página
Una vez que tienes los datos, lo más seguro es insertarlos en el DOM usando textContent en lugar de innerHTML cuando se trata de información que viene de una API.
async function mostrarUsuarios() {
const usuarios = await obtenerUsuarios();
const contenedor = document.getElementById('usuarios');
usuarios.forEach(usuario => {
const div = document.createElement('div');
div.textContent = `${usuario.name} - ${usuario.email}`;
contenedor.appendChild(div);
});
}
De esta manera evitamos riesgos de inyección de HTML malicioso.
Buenas prácticas
- Extrae la lógica de peticiones a funciones reutilizables.
- Siempre valida
response.okantes de leer el cuerpo. - Define timeouts razonables para mejorar la experiencia de usuario.
- Usa
try/catchalrededor de las llamadas con async/await. - No expongas tokens o claves API en el código del cliente.
- Considera crear una pequeña capa de abstracción si tu aplicación hace muchas peticiones.
- Prefiere
textContentsobreinnerHTMLcon datos externos. - Maneja los casos de error mostrando mensajes claros al usuario.
¿Puedo usar fetch en Node.js?
Sí. Desde la versión 21 de Node.js, fetch en JavaScript está disponible de forma global y estable. En versiones anteriores puedes usar el paquete node-fetch o activar la característica experimental.
¿Qué diferencia hay entre fetch y axios?
Fetch es la solución nativa del navegador y de Node.js moderno. Axios es una librería que añade algunas comodidades como interceptores y transformación automática de JSON, pero requiere instalar un paquete extra. Para proyectos pequeños o cuando no necesitas esas funcionalidades extras, fetch en JavaScript es suficiente.
¿Cómo envío un formulario con fetch?
Puedes usar new FormData(formulario) como valor de body y omitir la cabecera Content-Type para que el navegador ponga la correcta automáticamente. También puedes seguir enviando JSON si prefieres ese formato.
Si quieres seguir aprendiendo sobre JavaScript, echa un vistazo a más tutoriales de JavaScript que tenemos en el blog.
Imagen de portada: ProjectManhattan, CC BY-SA 3.0, vía Wikimedia Commons (recortada).
