Con APIs externas, los desarrolladores Python pueden implementar recuperación de datos, información financiera y procesamiento de imágenes sin construir todo desde cero. Sin embargo, «gratuito para usar» y «seguro para usar en producción» son dos cosas completamente diferentes.
Este artículo presenta 10 APIs gratuitas y prácticas para Python con código listo para producción, detalles de Rate Limit y patrones de diseño seguro. Más allá de una simple lista de APIs, cubrimos la filosofía de diseño que usan los profesionales al trabajar con APIs externas.
Nivel objetivo: Principiante a intermedio (capaz de usar requests). Requisito previo:
pip install requests
Para gestión segura de claves API, consulta también «10 Patrones de Implementación de Seguridad en Python.»
Plantilla Básica de Llamadas API
Antes de profundizar en APIs individuales, establezcamos la plantilla base que toda llamada API debe seguir. En producción, estos cuatro puntos son el estándar mínimo:
- Establecer un timeout — evita que tu programa espere indefinidamente
- Verificar códigos de estado — maneja correctamente las respuestas distintas de 200
- Manejar excepciones — afronta fallos de red y timeouts
- No asumir JSON — evita crashes cuando la respuesta es HTML o texto
import requests
url = "https://api.example.com/data"
try:
response = requests.get(url, timeout=5)
response.raise_for_status()
data = response.json()
print(data)
except requests.exceptions.Timeout:
print("Timeout: server not responding")
except requests.exceptions.HTTPError as e:
print(f"HTTP error: {e.response.status_code}")
except requests.exceptions.RequestException as e:
print(f"Request error: {e}")
except ValueError:
print("JSON decode error: response is not JSON")
Mantén esta plantilla como función de utilidad compartida en tu proyecto. Los ejemplos de código siguientes omiten el manejo de errores por brevedad, pero siempre aplica este patrón en código de producción.
Tabla Comparativa de APIs Gratuitas
| API | Propósito | Clave API | Rate Limit | Comercial | Dificultad |
|---|---|---|---|---|---|
| ① Open-Meteo | Datos del clima | Ninguno | Flexible | Sí | ★☆☆ |
| ② ExchangeRate | Tipos de cambio | Ninguno | 1.500/día | Sí | ★☆☆ |
| ③ CoinGecko | Precios de cripto | Ninguno | 10–30/min | Verificar ToS | ★☆☆ |
| ④ JSONPlaceholder | Prueba/Mock | Ninguno | Ninguno | — | ★☆☆ |
| ⑤ REST Countries | Info de países | Ninguno | Flexible | Sí | ★☆☆ |
| ⑥ The Cat API | Imágenes de gatos | Opcional | 10/min | Sí | ★☆☆ |
| ⑦ IP-API | Geolocalización por IP | Ninguno | 45/min | Solo pago | ★☆☆ |
| ⑧ Advice Slip | Frases aleatorias | Ninguno | 1/2seg | Sí | ★☆☆ |
| ⑨ PokeAPI | Datos de Pokémon | Ninguno | Flexible | Sí | ★★☆ |
| ⑩ Numbers API | Curiosidades numéricas | Ninguno | Flexible | Sí | ★☆☆ |
① Open-Meteo — API del Clima sin Clave
Open-Meteo es una API de datos meteorológicos completamente gratuita y sin clave API. Proporciona clima actual, temperatura, velocidad del viento, precipitación y pronósticos hasta 16 días. El uso comercial está permitido, lo que la convierte en la opción preferida para herramientas relacionadas con el clima.
import requests
url = "https://api.open-meteo.com/v1/forecast"
params = {
"latitude": 35.6762,
"longitude": 139.6503,
"current_weather": True
}
response = requests.get(url, params=params, timeout=5)
data = response.json()
weather = data["current_weather"]
print(f"Temp: {weather['temperature']}°C")
print(f"Wind: {weather['windspeed']} km/h")
La mayor ventaja es acceso instantáneo a datos sin ninguna autenticación. No se necesita registro de clave API ni creación de cuenta. Cambia la latitud/longitud y obtendrás datos meteorológicos de cualquier parte del mundo.
Open-Meteo es un proyecto de código abierto que usa datos de agencias meteorológicas europeas. La precisión es alta incluso para ubicaciones en Asia y América, lo que lo hace adecuado tanto para proyectos personales como para herramientas comerciales.
② ExchangeRate API — Tipos de Cambio
ExchangeRate API proporciona tipos de cambio de divisas gratuitos para las principales monedas. Útil para herramientas de conversión de divisas, sitios de comparación de precios y dashboards financieros. No requiere clave API, con 1.500 solicitudes por día.
import requests
url = "https://open.er-api.com/v6/latest/USD"
response = requests.get(url, timeout=5)
data = response.json()
jpy_rate = data["rates"]["JPY"]
print(f"1 USD = {jpy_rate} JPY")
# Currency conversion example
usd_amount = 100
jpy_amount = usd_amount * jpy_rate
print(f"{usd_amount} USD = {jpy_amount:.0f} JPY")
Una consideración crítica con datos financieros es la frecuencia de actualización. Esta API se actualiza aproximadamente una vez al día, por lo que no es adecuada para trading en tiempo real. Proporciona suficiente precisión para conversión aproximada de divisas y referencias de precios diarios.
Al mostrar tipos de cambio a los usuarios, siempre indica que «los tipos son aproximados». Pueden existir discrepancias con los tipos en tiempo real, y estos datos no deben usarse como base para transacciones financieras.
③ CoinGecko API — Precios de Criptomonedas
CoinGecko proporciona precios de criptomonedas, capitalización de mercado, volúmenes de trading y rankings. El plan gratuito es sorprendentemente potente y ampliamente usado para desarrollo de herramientas relacionadas con cripto.
import requests
url = "https://api.coingecko.com/api/v3/simple/price"
params = {
"ids": "bitcoin,ethereum",
"vs_currencies": "usd,eur",
"include_24hr_change": "true"
}
response = requests.get(url, params=params, timeout=5)
data = response.json()
btc = data["bitcoin"]
print(f"BTC: ${btc['usd']:,.0f} (24h: {btc['usd_24h_change']:.1f}%)")
El Rate Limit de CoinGecko en el plan gratuito es de aproximadamente 10–30 solicitudes por minuto. Dado que los precios de cripto son volátiles, el caché es esencial. Obtén datos cada minuto, almacena localmente y sirve desde caché.
CoinGecko permite obtener múltiples monedas en una sola solicitud. Usa ids=bitcoin,ethereum,solana con separación por comas para reducir drásticamente el número de solicitudes.
④ JSONPlaceholder — El Estándar para Práctica de API
JSONPlaceholder es una API mock diseñada para aprendizaje y pruebas de APIs REST. Proporciona datos simulados para usuarios, posts, comentarios y álbumes, ampliamente usada para prototipado de desarrollo de APIs y pruebas de frontend.
import requests
# Get posts
url = "https://jsonplaceholder.typicode.com/posts"
params = {"_limit": 3}
response = requests.get(url, params=params, timeout=5)
posts = response.json()
for post in posts:
print(f"[{post['id']}] {post['title']}")
# Practice POST requests
new_post = {"title": "Test", "body": "Hello", "userId": 1}
res = requests.post(url, json=new_post, timeout=5)
print(f"Created: status={res.status_code}")
La mayor ventaja es soporte para todos los métodos HTTP: GET, POST, PUT, PATCH, DELETE. Las solicitudes POST y DELETE no modifican datos reales — las respuestas son simuladas, lo que permite experimentar con seguridad. Ideal para incorporar nuevos ingenieros y probar clientes API.
Si necesitas una API mock para tu propio proyecto, usa el diseño de JSONPlaceholder como referencia y configura un servidor mock local con json-server (paquete npm).
⑤ REST Countries — Información de Países
REST Countries proporciona información básica sobre cada país del mundo — población, área, capital, bandera, moneda, idiomas y región — todo en formato JSON. Excelente para herramientas de educación geográfica, dashboards de estadísticas y aplicaciones internacionalizadas.
import requests
url = "https://restcountries.com/v3.1/name/japan"
response = requests.get(url, timeout=5)
data = response.json()[0]
print(f"Country: {data['name']['common']}")
print(f"Capital: {data['capital'][0]}")
print(f"Population: {data['population']:,}")
print(f"Region: {data['region']}")
print(f"Flag: {data['flag']}")
Esta API es ideal para caché ya que los datos de países rara vez cambian. Obtén todos los datos una vez y almacena localmente — no necesitas llamar a la API de nuevo. Cargar todos los datos en memoria al iniciar es el enfoque más eficiente.
El endpoint /v3.1/all devuelve datos de los más de 250 países de una vez. Usa filtros de campos (?fields=name,population,capital) para reducir el tamaño de la respuesta y ahorrar ancho de banda.
⑥ The Cat API — Imágenes de Gatos Aleatorias
The Cat API devuelve imágenes aleatorias de gatos. Aunque parece lúdica, es genuinamente útil en producción para pruebas de visualización de imágenes en UI, generación de placeholders dinámicos y pruebas de clientes API.
import requests
url = "https://api.thecatapi.com/v1/images/search"
params = {"limit": 3}
response = requests.get(url, params=params, timeout=5)
images = response.json()
for img in images:
print(f"URL: {img['url']} (size: {img['width']}x{img['height']})")
Las funciones básicas funcionan sin clave API, pero registrarse para una clave gratuita aumenta los límites de tasa y desbloquea filtros por raza y favoritos.
Al probar funciones de «visualización dinámica de imágenes» en desarrollo frontend, esta API proporciona un entorno de prueba más realista que imágenes dummy estáticas.
⑦ IP-API — Geolocalización por IP
IP-API devuelve datos de geolocalización a partir de direcciones IP — país, región, ciudad, ISP y zona horaria. Se usa para análisis de acceso, visualización de contenido por región y monitoreo de seguridad.
import requests
url = "http://ip-api.com/json/"
response = requests.get(url, timeout=5)
data = response.json()
print(f"Country: {data['country']}")
print(f"Region: {data['regionName']}")
print(f"City: {data['city']}")
print(f"ISP: {data['isp']}")
print(f"Timezone: {data['timezone']}")
El nivel gratuito es solo HTTP (HTTPS requiere plan de pago). Para entornos de producción que requieran HTTPS, considera actualizar o cambiar a alternativas como ipinfo.io. El uso comercial también requiere el plan de pago.
El límite de tasa es de 45 solicitudes por minuto. Para consultas masivas de IP, usa el endpoint http://ip-api.com/batch para mayor eficiencia.
⑧ Advice Slip API — Frases Aleatorias
Advice Slip API devuelve consejos y frases aleatorias en inglés. Útil para pantallas de prueba de UI, funciones de mensaje diario y embellecimiento de chatbots.
import requests
url = "https://api.adviceslip.com/advice"
response = requests.get(url, timeout=5)
data = response.json()
advice = data["slip"]["advice"]
print(f"Today's advice: {advice}")
Esta API presenta un diseño de endpoint minimalista — solo /advice (aleatorio) y /advice/{id} (por ID). Aplica un límite de intervalo de 2 segundos entre llamadas consecutivas.
Las APIs con diseños «un endpoint, una respuesta» como esta sirven como referencias de libro de texto para diseño de APIs. Al construir tu propia API, empezar así de simple es una buena práctica de producción.
⑨ PokeAPI — Ideal para Aprender Datos Estructurados
PokeAPI proporciona nombres, tipos, estadísticas e imágenes de Pokémon. Más allá de los datos del juego, su estructura lo hace excelente para aprender procesamiento de JSON anidado, paginación y manejo de datos relacionales — patrones que encontrarás en toda API de producción.
import requests
url = "https://pokeapi.co/api/v2/pokemon/pikachu"
response = requests.get(url, timeout=5)
data = response.json()
print(f"Name: {data['name']}")
print(f"Type: {data['types'][0]['type']['name']}")
print(f"HP: {data['stats'][0]['base_stat']}")
print(f"Image: {data['sprites']['front_default']}")
Las respuestas de PokeAPI están profundamente anidadas, requiriendo patrones de acceso como data["types"][0]["type"]["name"]. Esto es común en APIs de producción (Stripe, Twilio, AWS SDK), así que practicar aquí facilita la integración real de APIs.
PokeAPI tiene más de 1.000 entradas con soporte de paginación (?offset=20&limit=20). El patrón lista → detalle se aplica directamente al diseño de APIs de e-commerce y redes sociales.
⑩ Numbers API — Curiosidades Numéricas
Numbers API devuelve trivia y datos curiosos sobre cualquier número. Útil para sitios educativos, herramientas de quiz y embellecimiento de UI con contenido diario.
import requests
number = 42
url = f"http://numbersapi.com/{number}?json"
response = requests.get(url, timeout=5)
data = response.json()
print(f"{number}: {data['text']}")
# e.g.: 42: 42 is the answer to the Ultimate Question ...
Los tipos incluyen trivia (por defecto), math, date y year. Por ejemplo, http://numbersapi.com/3/14/date?json devuelve trivia sobre el 14 de marzo.
Numbers API es solo HTTP — sin soporte HTTPS. Para uso en producción, evítala o retransmite solicitudes a través de tu servidor y devuelve respuestas HTTPS a los clientes.
Rate Limits y Estrategia de Caché
La trampa más peligrosa con APIs gratuitas es exceder los límites de tasa. Los servicios gratuitos tienen límites estrictos, y las violaciones resultan en bloqueos de IP que pueden durar horas o días.
Patrones típicos de límite de tasa:
| Patrón | Ejemplo | Caso de Uso |
|---|---|---|
| Por segundo | 1/seg | Datos en tiempo real |
| Por minuto | 60/min | APIs estándar |
| Por día | 1.000/día | Recuperación de datos |
La solución es el caché. Almacena las respuestas de la API localmente y sírvelas desde caché dentro de una ventana TTL.
import requests
import time
import json
import os
CACHE_FILE = "cache.json"
CACHE_TTL = 300 # 5 minutos
def get_with_cache(url):
if os.path.exists(CACHE_FILE):
with open(CACHE_FILE) as f:
cache = json.load(f)
if url in cache and time.time() - cache[url]["time"] < CACHE_TTL:
return cache[url]["data"]
response = requests.get(url, timeout=5)
data = response.json()
cache = {}
if os.path.exists(CACHE_FILE):
with open(CACHE_FILE) as f:
cache = json.load(f)
cache[url] = {"data": data, "time": time.time()}
with open(CACHE_FILE, "w") as f:
json.dump(cache, f)
return data
En producción, usa Redis o memcached en lugar de caché en archivo. Django proporciona django.core.cache, y FastAPI tiene aiocache para soporte de caché integrado.
Patrones Esenciales de Diseño Seguro
El código de producción que usa APIs externas requiere estos cinco patrones de diseño:
| Patrón | Propósito | Riesgo si Falta |
|---|---|---|
| timeout | Evitar espera infinita | Programa se congela |
| retry | Manejar fallos transitorios | Procesamiento se detiene |
| rate control | Respetar límites de API | Bloqueo de IP |
| fallback | Manejar caídas de API | Servicio caído |
| cache | Reducir solicitudes | Límite excedido |
Un patrón de producción combinado:
import requests
import time
def safe_api_call(url, max_retries=3, delay=1):
for attempt in range(max_retries):
try:
response = requests.get(url, timeout=5)
if response.status_code == 429: # Rate Limit
wait = int(response.headers.get("Retry-After", delay * 2))
time.sleep(wait)
continue
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException:
if attempt < max_retries - 1:
time.sleep(delay * (attempt + 1))
continue
return None # fallback
return None
Recuerda este principio de producción: las APIs externas son poco fiables por defecto. Caídas, cambios de especificación, picos de latencia, cambios de límites — estos no son escenarios de «podría pasar», son «pasará». Los profesionales diseñan asumiendo que las APIs externas no pueden ser confiables.
Para más sobre diseño seguro, consulta «10 Patrones de Implementación de Seguridad en Python.»
Errores Comunes y Términos de Servicio
Conoce los patrones de fallo que los principiantes suelen encontrar:
| Error | Resultado | Solución |
|---|---|---|
| Llamadas API en bucle | Bloqueo de IP | sleep + caché |
| Sin caché | Límite excedido | Caché por archivo/Redis |
| Sin manejo de errores | Crash del programa | try/except obligatorio |
| Sin timeout | Programa se congela | timeout=5 como estándar |
| Ignorar ToS | Riesgo legal | Siempre leer Términos |
Siempre verifica los Términos de Servicio. Incluso las APIs gratuitas pueden tener restricciones:
- Sin uso comercial — solo uso personal
- Atribución requerida — obligación de mostrar «Powered by ○○»
- Sin redistribución — no se puede republicar datos crudos en otro servicio
- Restricciones HTTPS — nivel gratuito solo HTTP (IP-API, Numbers API)
«Gratuito» no significa «usar como quieras». Ignorar los Términos de Servicio es más peligroso que enviar código con errores — es un riesgo legal directo.
Diseño Profesional — Provider Abstraction
Los desarrolladores experimentados siempre piensan en las APIs externas de esta manera:
- Las APIs gratuitas son para prototipado y validación
- Planifica migración a plan de pago o reemplazo auto-hospedado en producción
- Diseña para evitar dependencia excesiva de cualquier proveedor
Esto se logra mediante Provider Abstraction — encapsulando las llamadas API detrás de una interfaz para que los proveedores puedan intercambiarse sin cambiar el código de la aplicación.
class WeatherProvider:
def get_temperature(self, lat, lon):
raise NotImplementedError
class OpenMeteoProvider(WeatherProvider):
def get_temperature(self, lat, lon):
url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}¤t_weather=true"
data = requests.get(url, timeout=5).json()
return data["current_weather"]["temperature"]
class PaidWeatherProvider(WeatherProvider):
def get_temperature(self, lat, lon):
# Swap to paid API by changing just this class
pass
# Usage
weather = OpenMeteoProvider()
temp = weather.get_temperature(35.67, 139.65)
print(f"Temperature: {temp}°C")
Con este diseño, cambiar de proveedores de API requiere cambiar solo una clase. No necesitas reescribir toda tu aplicación. Durante las pruebas, también puedes intercambiar un proveedor mock.
Esto también se conoce como «Strategy Pattern» y se aplica más allá de las APIs a bases de datos, servicios de email, almacenamiento de archivos — cualquier integración de servicio externo.
Preguntas Frecuentes
P: ¿Cuál es la diferencia entre APIs con y sin clave?
Las claves API identifican usuarios. Las APIs sin clave son convenientes pero tienden a tener límites de tasa más estrictos basados en IP. Las APIs con clave pueden gestionar límites por usuario y típicamente permiten más solicitudes.
P: ¿Puedo construir un servicio público usando APIs gratuitas?
Depende de los Términos de Servicio. Open-Meteo y REST Countries permiten uso comercial, pero el nivel gratuito de IP-API es solo no comercial. Siempre verifica los ToS de cada API antes de publicar.
P: ¿Qué pasa si una API se cae repentinamente?
Por eso es importante el diseño de fallback. Mantén datos recientes en caché para poder servirlos durante caídas. Para tiempos de inactividad prolongados, usa Provider Abstraction para cambiar a una API alternativa.
P: ¿Qué significa 429 Too Many Requests?
Has excedido el límite de tasa. Verifica el encabezado de respuesta Retry-After y espera los segundos especificados antes de reintentar. Si consistentemente recibes 429, implementa caché o aumenta los intervalos entre solicitudes.
Conclusión
Las APIs gratuitas permiten a los desarrolladores Python implementar clima, divisas, cripto, imágenes y muchas otras funciones en tiempo récord. Pero lo que realmente importa no es qué APIs eliges — es cómo las usas.
- Siempre implementa timeout y manejo de errores
- Verifica los Rate Limits y mantente dentro de ellos usando caché
- Lee los Términos de Servicio antes de usar cualquier API
- Gestiona dependencias con Provider Abstraction
- Diseña asumiendo que las APIs externas son poco fiables
Las APIs son potentes, pero la dependencia excesiva rompe las cosas. Usadas sabiamente, pueden acelerar drásticamente tu velocidad de desarrollo. Esa es la esencia de la integración de APIs externas.

Deja una respuesta