(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo cachear respuestas de una API en Python: paso a paso

João Barros 14 de July de 2026 4 min de lectura

Llamar repetidamente a la misma API es lento y consume tu límite de peticiones sin necesidad. Hacer caché de respuestas de una API en Python resuelve el problema: la respuesta se guarda localmente y, en la siguiente llamada, se lee del disco en milisegundos. Con la librería requests-cache lo consigues sin cambiar prácticamente nada del código que ya tienes.

Requisitos previos

  • Python 3.8 o superior instalado.
  • Conocer lo básico de la librería requests (hacer un GET).
  • Una API REST pública para probar — usamos https://api.github.com como ejemplo.

Paso 1: Instalar requests-cache

La instalación se hace con pip. requests-cache es un complemento de requests, así que instalamos ambos.

pip install requests requests-cache

Paso 2: Crear una CachedSession

En vez de usar requests.get() directamente, creas una CachedSession. Funciona igual que una sesión normal, pero guarda cada respuesta en un fichero SQLite. El parámetro expire_after define durante cuántos segundos la copia se considera válida.

from requests_cache import CachedSession

session = CachedSession(
    cache_name="api_cache",   # crea el fichero api_cache.sqlite
    backend="sqlite",
    expire_after=3600,        # la respuesta es válida durante 1 hora
)

respuesta = session.get("https://api.github.com/repos/psf/requests")
print(respuesta.status_code, respuesta.from_cache)

En la primera ejecución verás 200 False: la respuesta vino de la red. En la segunda verás 200 True — vino de la caché.

Paso 3: Medir la ganancia de tiempo

Merece la pena confirmar el efecto con un ejemplo sencillo. La diferencia entre una llamada de red y una lectura de la caché suele ser de cientos de milisegundos frente a unos pocos milisegundos.

import time

for i in range(2):
    inicio = time.perf_counter()
    r = session.get("https://api.github.com/repos/psf/requests")
    duracion = (time.perf_counter() - inicio) * 1000
    print(f"llamada {i+1}: from_cache={r.from_cache} ({duracion:.0f} ms)")

Paso 4: Controlar qué se guarda

Guardarlo todo rara vez es lo que quieres. Un error habitual es acabar con una respuesta de error atrapada en la caché. Limita la caché a respuestas 200 y a métodos GET, y define tiempos distintos por tipo de endpoint.

session = CachedSession(
    cache_name="api_cache",
    expire_after=300,              # 5 minutos por defecto
    allowable_codes=[200],         # solo guarda respuestas correctas
    allowable_methods=["GET"],     # nunca guarda POST/PUT
    stale_if_error=True,           # si la API falla, usa la copia antigua
    urls_expire_after={
        "*/rate_limit": 0,     # este endpoint nunca se guarda
        "*/repos/*": 86400 # datos de repositorios: 1 día
    },
)

stale_if_error=True es la opción que más veces te va a salvar: si la API está caída o devuelve un error 429, tu script sigue funcionando con la última respuesta buena en lugar de romperse.

Paso 5: Forzar una actualización y limpiar la caché

A veces necesitas de verdad el valor más reciente, o quieres ordenar el fichero. Puedes ignorar la caché en una única petición con refresh=True y borrar entradas con los métodos del objeto session.cache.

from requests_cache import CachedSession

session = CachedSession("api_cache", expire_after=3600)

# ignora la caché solo en esta petición y actualiza la copia guardada
r = session.get("https://api.github.com/repos/psf/requests", refresh=True)

# elimina solo las entradas ya expiradas
session.cache.delete(expired=True)

# borra todo
session.cache.clear()

Verificar el resultado

Tres señales confirman que está bien hecho:

  1. Existe un fichero api_cache.sqlite en la carpeta de tu script.
  2. La segunda llamada a la misma URL devuelve r.from_cache == True.
  3. La segunda llamada tarda un orden de magnitud menos.
print(len(session.cache.responses))   # nº de respuestas guardadas
print(list(session.cache.urls())[:5]) # URLs en caché

Si from_cache sigue devolviendo False, comprueba que estás usando session (y no requests.get) y que expire_after no es 0.

Conclusión

Con media docena de líneas ya ahorras llamadas, evitas errores 429 y haces tu script mucho más rápido durante el desarrollo. El siguiente paso natural es llevar esta caché a producción: cambia el backend SQLite por Redis (backend="redis") para compartirla entre varios procesos, y ajusta el expire_after por endpoint. Una pregunta para cerrar: ¿cuáles de los endpoints que usas cambian realmente de minuto a minuto — y cuáles podrías guardar durante un día entero sin que nadie lo notara?