El pronóstico del tiempo es uno de esos bloques que elevan el valor de un sitio sin hacer ruido: el usuario pasa más tiempo en la página, vuelve más a menudo y el contenido se percibe «vivo». Por eso los widgets y bloques meteorológicos son tan frecuentes en los portales urbanos y turísticos, en los servicios de reservas y en los sitios de inmuebles en el extranjero. En este artículo repasamos de dónde obtener datos meteorológicos, qué APIs son populares en 2026, en qué se diferencia el parseo de HTML del trabajo a través de una API, y mostramos implementaciones listas en Python, JavaScript, PHP y Go.
Qué es el «scraping del tiempo» y qué enfoques existen
Bajo «scraping del tiempo» suelen agruparse dos tareas de naturaleza distinta:
- Trabajar a través de una API oficial. El servicio entrega datos estructurados (casi siempre JSON): usted lanza una petición HTTP y recibe campos listos — temperatura, humedad, velocidad del viento, código del fenómeno meteorológico. Es la vía fiable, legal y predecible.
- Scraping de páginas HTML. Cuando la fuente no ofrece API o esta es de pago, los desarrolladores extraen los datos directamente del marcado del sitio. Funciona, pero es frágil: cualquier cambio en el HTML rompe el scraper, y el propio enfoque vulnera con frecuencia las condiciones de uso de la fuente.
La conclusión práctica es simple: siempre que exista una API, use la API. Reserve el scraping para cuando de verdad no haya otra fuente, y compruebe en todo caso el robots.txt y las condiciones de uso.
Fuentes de datos y APIs populares
Open-Meteo: gratuito y sin clave
Open-Meteo es una de las opciones más cómodas para empezar. La API no requiere clave para el uso no comercial, devuelve los datos en JSON y agrega las predicciones de los servicios meteorológicos nacionales con una resolución de 1 a 11 km. Para los proyectos comerciales existen tarifas de pago aparte, con límites mensuales de peticiones. Ideal para prototipos, widgets y proyectos open source.
OpenWeatherMap: el clásico con un límite gratuito amplio
OpenWeatherMap sigue siendo el servicio más repetido en los tutoriales. En 2026 conserva una vía gratuita operativa, pero importa entender qué producto exacto se está llamando. Los endpoints clásicos (tiempo actual, predicción cada 3 horas, contaminación del aire, mapas meteorológicos, geocodificación) están disponibles gratis con un límite de 60 peticiones por minuto y hasta 1 000 000 de peticiones al mes. Los productos de la familia One Call (3.0 / 4.0) son suscripciones aparte, con tarificación por llamada y las primeras 1000 peticiones diarias gratuitas. Antes de pasar a producción conviene fijar un tope de gasto para no rebasar por accidente el umbral gratuito.
WeatherAPI.com: una tarifa gratuita generosa
WeatherAPI.com sirve el tiempo actual, la predicción horaria y diaria, datos históricos, astronomía y geolocalización, en JSON y XML. Una elección cómoda cuando se busca un único proveedor «para todo» con un límite gratuito claro.
Visual Crossing: datos históricos potentes
A Visual Crossing se le cita a menudo entre los mejores en relación precio-prestaciones: una única API para el tiempo actual, las predicciones, los avisos y, sobre todo, series históricas largas. Hay clave gratuita y un Query Builder para componer consultas con exportación a JSON o CSV. Buena opción para analítica y dashboards.
Plataformas para empresas: Tomorrow.io, Weatherbit, Meteomatics, meteoblue
Si necesita parámetros muy especializados (unos 500 en Tomorrow.io, más de 1800 en Meteomatics, series históricas desde 1940), mire hacia las plataformas corporativas. Ofrecen alta precisión y un abanico enorme de parámetros, pero casi siempre exigen una suscripción de pago para el uso comercial.
La fuente oficial de España: AEMET OpenData
AEMET, la Agencia Estatal de Meteorología, es el servicio meteorológico oficial de España, y su plataforma de datos abiertos AEMET OpenData es la referencia para los proyectos centrados en el país. Se trata de una API REST gratuita: la clave (api key) se solicita en el portal y llega por correo electrónico. Ofrece predicciones por municipio, observaciones de las estaciones meteorológicas, avisos y series climatológicas.
Una peculiaridad que conviene conocer: la API responde en dos pasos. La primera petición no devuelve la predicción en sí, sino un JSON con el campo datos — una URL temporal desde la que se descarga el conjunto de datos real. El cliente, por tanto, debe encadenar dos peticiones HTTP. Los datos son reutilizables citando a AEMET como fuente, en las condiciones habituales de los datos abiertos.
Servicios estatales y oficiales
Para Estados Unidos existe la API gratuita y sin clave del Servicio Meteorológico Nacional (NWS, weather.gov): una opción excelente para proyectos civiles y comunitarios dentro del país. En España ese papel lo cumple AEMET con su plataforma OpenData, descrita más arriba, y otros servicios meteorológicos nacionales europeos mantienen portales de datos abiertos similares. Las fuentes estatales son gratuitas y de autoridad, pero suelen limitarse a un territorio concreto.
Comparación por criterios clave
| Fuente | Clave | Tarifa gratuita | Cobertura | Ideal para |
|---|---|---|---|---|
| Open-Meteo | No hace falta (no comercial) | Sí, generosa | Global | Prototipos, widgets, open source |
| OpenWeatherMap | Necesaria | Sí (endpoints clásicos) | Global | Tareas universales |
| WeatherAPI.com | Necesaria | Sí | Global | «Todo en uno» |
| Visual Crossing | Necesaria | Sí | Global | Histórico, analítica |
| Tomorrow.io / Meteomatics | Necesaria | Prueba/límite | Global | Negocio, parámetros específicos |
| AEMET OpenData | Necesaria (gratuita) | Sí (datos abiertos) | España | Proyectos centrados en España |
| NWS (weather.gov) | No hace falta | Sí | Solo EE. UU. | Proyectos civiles en EE. UU. |
Implementaciones en varios lenguajes
En todos los ejemplos siguientes se usa Open-Meteo, porque no necesita clave: el código puede ejecutarse tal cual. Las coordenadas de los ejemplos corresponden a Madrid (40.42, -3.70). Para pasar a otro proveedor suele bastar con cambiar la URL, añadir la clave y ajustar el parseo del JSON.
Python (requests)
import requests
def get_weather(lat: float, lon: float) -> dict:
url = "https://api.open-meteo.com/v1/forecast"
params = {
"latitude": lat,
"longitude": lon,
"current": "temperature_2m,relative_humidity_2m,wind_speed_10m,weather_code",
"timezone": "auto",
}
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
return response.json()
data = get_weather(40.42, -3.70)
current = data["current"]
print(f"Temperatura: {current['temperature_2m']}°C")
print(f"Humedad: {current['relative_humidity_2m']}%")
print(f"Viento: {current['wind_speed_10m']} km/h")Versión para OpenWeatherMap con clave y localización en español:
import requests
API_KEY = "SU_CLAVE"
def get_weather_owm(city: str) -> dict:
url = "https://api.openweathermap.org/data/2.5/weather"
params = {"q": city, "units": "metric", "lang": "es", "appid": API_KEY}
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
d = response.json()
return {
"ciudad": d["name"],
"temperatura": d["main"]["temp"],
"sensacion": d["main"]["feels_like"],
"descripcion": d["weather"][0]["description"],
}
print(get_weather_owm("Madrid"))JavaScript / Node.js (fetch nativo)
En Node.js 18+ fetch está disponible de serie: no hacen falta dependencias externas.
async function getWeather(lat, lon) {
const url = new URL("https://api.open-meteo.com/v1/forecast");
url.searchParams.set("latitude", lat);
url.searchParams.set("longitude", lon);
url.searchParams.set("current", "temperature_2m,wind_speed_10m,weather_code");
url.searchParams.set("timezone", "auto");
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Error HTTP: ${response.status}`);
}
return response.json();
}
getWeather(40.42, -3.70)
.then((data) => {
const c = data.current;
console.log(`Temperatura: ${c.temperature_2m}°C, viento: ${c.wind_speed_10m} km/h`);
})
.catch((err) => console.error("No se pudo obtener el tiempo:", err.message));PHP (cURL)
<?php
function getWeather(float $lat, float $lon): ?array
{
$query = http_build_query([
'latitude' => $lat,
'longitude' => $lon,
'current' => 'temperature_2m,wind_speed_10m,weather_code',
'timezone' => 'auto',
]);
$url = "https://api.open-meteo.com/v1/forecast?{$query}";
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_USERAGENT => 'WeatherWidget/1.0',
]);
$body = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($body === false || $code !== 200) {
return null;
}
return json_decode($body, true);
}
$data = getWeather(40.42, -3.70);
if ($data !== null) {
echo "Temperatura: " . $data['current']['temperature_2m'] . "°C\n";
}Go
package main
import (
"encoding/json"
"fmt"
"net/http"
"time"
)
type WeatherResponse struct {
Current struct {
Temperature float64 `json:"temperature_2m"`
WindSpeed float64 `json:"wind_speed_10m"`
WeatherCode int `json:"weather_code"`
} `json:"current"`
}
func main() {
url := "https://api.open-meteo.com/v1/forecast" +
"?latitude=40.42&longitude=-3.70" +
"¤t=temperature_2m,wind_speed_10m,weather_code&timezone=auto"
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var data WeatherResponse
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
panic(err)
}
fmt.Printf("Temperatura: %.1f°C, viento: %.1f km/h\n",
data.Current.Temperature, data.Current.WindSpeed)
}Petición a AEMET OpenData (predicción diaria por municipio)
# Paso 1: obtener la URL real de los datos (campo "datos" de la respuesta)
curl "https://opendata.aemet.es/opendata/api/prediccion/especifica/municipio/diaria/28079?api_key=SU_CLAVE"
# Paso 2: descargar la predicción desde la URL recibida en "datos"
curl "URL_DEL_CAMPO_DATOS"El código 28079 corresponde al municipio de Madrid (los identificadores siguen la codificación de municipios del INE). Antes de pasar a producción, contraste los endpoints con la documentación oficial de la plataforma.
El scraping de HTML como plan B (Python + BeautifulSoup)
Cuando no hay API disponible, los datos pueden extraerse del marcado. El enfoque funciona, pero es frágil: si el HTML cambia, los selectores dejan de servir, y solo es admisible usarlo si no contradice las condiciones de la fuente.
import requests
from bs4 import BeautifulSoup
def scrape_weather(url: str) -> str:
headers = {"User-Agent": "Mozilla/5.0"}
html = requests.get(url, headers=headers, timeout=10).text
soup = BeautifulSoup(html, "html.parser")
# El selector se ajusta a la página de origen concreta
temp = soup.select_one(".temperature")
return temp.get_text(strip=True) if temp else "no encontrado"La decodificación del
weather_codeen Open-Meteo sigue el estándar de la WMO: por ejemplo, 0 — despejado, 2 — nubosidad variable, 61 — lluvia débil, 71 — nevada débil. Mantenga la tabla completa de códigos como un diccionario de mapeo para mostrar al usuario una descripción legible.
Caché, límites y cuestiones legales
Unas cuantas reglas que ahorran dinero y disgustos en producción:
- Cachee las respuestas. El tiempo casi nunca debe actualizarse en cada vista de página. Cachee por coordenadas, ciudad o código postal, y renueve las condiciones actuales cada 5--15 minutos. En las aplicaciones móviles, encamine las peticiones a través de su propio backend en lugar de lanzarlas desde cada cliente.
- Guarde las claves en el servidor. La clave de API no debe incrustarse en el código cliente: es fácil robarla. Las peticiones deben pasar por su proxy de backend.
- Vigile los límites. Configure el manejo de las respuestas 401 (clave incorrecta) y 429 (límite superado), y alertas ante un crecimiento brusco del número de llamadas.
- Compruebe la licencia. La mayoría de las tarifas gratuitas solo permiten el uso no comercial. Algunos servicios (Visual Crossing, OpenWeatherMap) admiten un uso comercial limitado citando la fuente. Para el scraping, revise siempre el
robots.txty las condiciones de uso.
Dónde se aplica: portales, turismo e inmobiliario
Un bloque meteorológico es el extra típico de los proyectos ligados a la geografía y al estilo de vida del usuario:
- Los portales urbanos muestran el tiempo actual y la predicción en la portada: retiene a la audiencia y convierte el sitio en un punto de entrada diario.
- Los portales turísticos y los servicios de reservas añaden el tiempo a la ficha del destino: al viajero le importa saber qué le espera al llegar.
- Los sitios de inmuebles en el extranjero usan el tiempo como parte de la «venta del clima»: días soleados, inviernos suaves y temperaturas agradables son un argumento de peso al elegir una vivienda junto al mar o en la montaña.
Lo curioso es que, en lo técnico, el scraping del tiempo pertenece a la misma familia que otra tarea popular de estos proyectos: la recopilación y agregación de anuncios. Si el tiempo hace que la ficha del destino se perciba «viva», llenar el catálogo de inmuebles es cosa del scraping inmobiliario: recogida automática de ofertas en los portales de origen, normalización de precios y características, actualización de la base. A menudo ambos módulos trabajan codo con codo: uno se ocupa del contenido del inmueble y el otro, del contexto que lo rodea.
Conclusión
Para la mayoría de las tareas, lo sensato es empezar por Open-Meteo (arranque inmediato, sin clave) u OpenWeatherMap (límite gratuito amplio y un ecosistema maduro). Si pesan los datos históricos, mire hacia Visual Crossing; si el proyecto se centra en España, la fuente oficial es AEMET OpenData. En lo técnico, la integración ocupa unas pocas líneas en cualquier lenguaje: petición HTTP, parseo del JSON, caché. Y un bloque del tiempo bien integrado eleva de forma notable la implicación en los portales urbanos, turísticos e inmobiliarios — allí donde al usuario le importa no solo el objeto en sí, sino también el contexto que lo rodea.