Contador de descargas de crates.io: el 80% de las nuestras llegó con una versión nueva

En resumen: el 17 de octubre de 2026 extraje todas las cifras diarias de descargas que crates.io tiene de mis 69 crates de Rust. En 89 días registraron 3.676 descargas, y el 80,1% llegó el mismo día en que se publicó una versión nueva o el día siguiente. Una versión nueva acumula unas 13 descargas en sus primeras 24 horas, contenga lo que contenga, y luego se queda plana. Crates externos que dependan de alguno de los 69: cero. La cifra que de verdad te dice si la gente usa tu crate es la línea base de días tranquilos, y en nuestro caso fue de 339 descargas, unas 3,8 al día.
Respuesta corta para quien llega desde un buscador. El contador de descargas de crates.io es el número de veces que se pidió el archivo .crate del crate a la CDN de crates.io, contado a partir de los registros de peticiones de la CDN (crates.io pasó a contar a partir de logs en marzo de 2024). Desde el 29 de octubre de 2025 solo se cuentan las peticiones que parecen venir de cargo (o que no envían ningún user agent). No es un recuento de usuarios, instalaciones ni proyectos. La CI de un desarrollador que ejecuta cargo build en una máquina limpia 30 veces al día suma 30 descargas diarias; una persona que instala tu crate una vez y lo conserva en su caché local suma una, para siempre.
Entonces, ¿qué hay realmente dentro de la cifra de un crate pequeño? A continuación tienes una medición reciente sobre un portafolio real, el script que la obtiene (cópialo y ejecútalo con tus propios crates) y cómo leer tu propio gráfico sin engañarte en ninguna de las dos direcciones.

De dónde salieron los 69 crates
Un poco de contexto, porque la forma de los datos sale directamente de cómo se publicaron estos crates. Mantengo un montón de bibliotecas y herramientas de Rust: fin-primitives (piezas básicas para trading), tokio-prompt-orchestrator (un proxy de LLM con deduplicación y circuit breaker), proof-engine (un motor de juegos en OpenGL) y CoreScout, un servidor MCP dividido en un workspace de 33 crates.
Salieron en tres tandas: 51 versiones en marzo de 2026, 116 en septiembre y 68 en octubre, 235 versiones en total. La tanda de octubre fue una sola gran publicación el 4 de octubre, después de una pasada en la que agentes de programación con IA actualizaron todos los crates y yo lo publiqué todo de golpe al final. Ese único día importa mucho más adelante.
Total histórico cuando lo consulté, a las 7:10 AM ET del 17 de octubre: 4.815 descargas. La cifra de "recent downloads" de crates.io (últimos 90 días) era 3.677. Mi objetivo para estos crates es 100.000, así que la pregunta honesta es cuánto de esas 4.815 corresponde a personas.
Obtén las cifras tú mismo en 40 líneas
crates.io tiene una API JSON pública. No tiene un versionado formal, pero es la que llama la propia web, y la política de acceso a datos pide dos cosas: como máximo una petición por segundo y un User-Agent que diga quién eres. Tres endpoints te dan todo:
/api/v1/crates?user_id=N: todos los crates de un usuario, con totales históricos y de 90 días./api/v1/crates/<name>/downloads: descargas diarias de los últimos 90 días, desglosadas por versión (las versiones antiguas se agrupan enextra_downloads)./api/v1/crates/<name>/reverse_dependencies: qué crates publicados dependen de este.
Este es el script que ejecuté esta mañana (pull.py, recortado solo en la selección de campos del JSON). Se detiene en seco ante un 429 en lugar de reintentar, porque un scraper educado no discute con un límite de frecuencia:
UA = "tensorust-deepdive-research (contact: hello@tensorust.com)"
last = [0.0]
def get(path):
wait = 1.05 - (time.time() - last[0]) # stay under 1 request/second
if wait > 0:
time.sleep(wait)
last[0] = time.time()
req = urllib.request.Request("https://crates.io" + path, headers={"User-Agent": UA})
try:
with urllib.request.urlopen(req, timeout=30) as r:
return json.load(r)
except urllib.error.HTTPError as e:
if e.code == 429:
print("429 - stopping"); sys.exit(2)
raise
user = get("/api/v1/users/mattbusel")["user"]
crates = get(f"/api/v1/crates?user_id={user['id']}&per_page=100")["crates"]
for c in crates:
n = c["name"]
dl = get(f"/api/v1/crates/{n}/downloads")
vers = get(f"/api/v1/crates/{n}/versions?per_page=100")
rev = get(f"/api/v1/crates/{n}/reverse_dependencies?per_page=100")
# ... store dl["version_downloads"], dl["meta"]["extra_downloads"], versions, rev
69 crates por tres llamadas, una por segundo, tardaron unos tres minutos y medio. Después hizo falta una segunda pasada de 69 llamadas para asociar los ID de versión con los números de versión y las fechas de publicación, porque el endpoint de descargas etiqueta cada fila con un ID numérico de versión, no con "2.15.0".

Si tienes más de unos cientos de crates (o quieres todos los crates del registro), no sobrecargues la API: crates.io publica un volcado de la base de datos cada 24 horas (static.crates.io/db-dump.tar.gz) que incluye la tabla de descargas por día y por versión de los últimos 90 días.
Lo que te muestra la página de crates.io
Este es el final de la página de fin-primitives, mi crate más descargado. Mira el gráfico antes de leer las cifras: una ondulación baja de 0 a 3 al día durante el verano y, después, picos altos en la última semana de septiembre y la primera de octubre, cada pico de un color distinto. Cada color es una versión.

Ese gráfico es honesto, pero es por crate. Con 69 crates no puedes revisar a ojo 69 gráficos, así que clasifiqué cada día de cada crate dentro de la ventana de 90 días en tres grupos.
Los tres tipos de día de descarga
La regla es sencilla y totalmente mecánica:
- Ventana de publicación: ese crate publicó una versión ese día UTC o el día anterior.
- Día de barrido: sin publicación, pero al menos la mitad de todos mis crates existentes se descargaron ese mismo día.
- Tranquilo: todo lo demás.
El núcleo del clasificador, de analyze.py:
for n, c in C.items():
for v in c['downloads']['version_downloads'] + c['downloads']['meta']['extra_downloads']:
d = dt.date.fromisoformat(v['date'])
if any(0 <= (d - p).days <= 1 for p in pub[n]):
cat[v['date']][0] += v['downloads'] # publish window
elif v['date'] in sweeps:
cat[v['date']][1] += v['downloads'] # sweep day
else:
cat[v['date']][2] += v['downloads'] # quiet
Y el resultado del 20 de julio al 16 de octubre de 2026 (89 días UTC completos, 3.676 descargas):

2.945 descargas (80,1%) llegaron en una ventana de publicación. 392 (10,7%) llegaron en seis días de barrido. 339 (9,2%) fueron descargas de días tranquilos. El mayor día fue el 4 de octubre, el de la gran publicación: 68 versiones publicadas, 1.195 descargas.
Dicho de otra forma: si nunca hubiera publicado esas versiones de septiembre y octubre, la cifra de 90 días habría rondado las 730, no las 3.676.
Una versión nueva recibe unas 13 descargas y luego nada
Para ver cuánto vale una publicación por sí sola, tomé todas las versiones publicadas dentro de la ventana con al menos una semana de datos posteriores (181 versiones) y alineé sus descargas según los días transcurridos desde la publicación.

Media de descargas el día 0: 13,45 (mediana 10). Día 1: 1,21. Día 2: 0,02. El 86,9% de las descargas de la primera semana de una versión llega el día 0 o el día 1. El total más bajo de día 0 más día 1 de cualquier versión fue 8, el más alto 66 y la mediana 12.
El mínimo es lo que lo delata. Entre las 235 versiones publicadas, el recuento histórico más bajo de una sola versión es 9. La mediana es 18. Tengo 19 crates que solo han tenido una versión, incluidos crates internos de fontanería como corescout-cli y corescout-lineage, que nadie fuera de este proyecto tiene motivos para conocer. Sus totales históricos van de 10 a 28, con mediana 15. Algo descarga cada versión nueva a las pocas horas de publicarse, la lea o no un humano en el README.
¿Qué es ese algo? Los datos no lo dicen. Mi suposición, y es solo eso: mirrors del registro y granjas de compilación que siguen el índice de crates.io y descargan las versiones nuevas en cuanto aparecen, además de escáneres de seguridad y de licencias. El filtro de user agent de 2025 se escribió para descartar mirrors, así que lo que lo supera es o bien cargo o bien un cliente que no envía user agent. docs.rs también genera documentación para cada versión nueva automáticamente; no pude confirmar en la documentación pública si esa descarga se cuenta, así que no afirmo que sí.
La consecuencia es muy práctica: en crates.io, el número de versiones que publicas predice tus descargas mejor que cualquier cosa del código. En mis 69 crates, la correlación entre número de versiones y descargas históricas es de 0,82. Por eso fin-primitives (13 versiones) va en cabeza y mis crates realmente más interesantes van por detrás.
Días de barrido: cuando todos los crates reciben descargas a la vez
El segundo grupo me sorprendió más. El 9 de octubre no se publicó nada y, aun así, los 69 crates se descargaron el mismo día, 184 descargas en total. El 13 de octubre: 56 de 69 crates, la mayoría con una descarga cada uno. Eso no es una persona. Una persona instala una herramienta y su árbol de dependencias, no un crate de estadística, uno de trading, un motor de juegos y un asesor de TFT en la misma tarde.

Seis días de la ventana encajan con el patrón: 3 de agosto (17 de los 17 crates que existían entonces), 29 de septiembre y 5, 9, 13 y 15 de octubre. Algunos de los últimos tiran hacia la familia CoreScout: el 6 y el 15 de octubre los crates más descargados fueron corescout-core, corescout-mirror y corescout-memory, que es exactamente lo que verías si algo resolviera el árbol de dependencias de un binario de CoreScout. Y eso nos lleva al multiplicador del que nadie habla.
Los workspaces multiplican el recuento
CoreScout es un workspace de Cargo, y cuando publicas un workspace en crates.io, cada miembro se convierte en un crate propio. Este es el Cargo.toml raíz real (extracto):
corescout-core = { version = "1.2.0", path = "crates/core" }
corescout-mirror = { version = "1.2.0", path = "crates/mirror" }
corescout-substrate = { version = "1.2.0", path = "crates/substrate" }
corescout-memory = { version = "1.2.0", path = "crates/memory" }
corescout-represent = { version = "1.2.0", path = "crates/represent" }
corescout-science = { version = "1.2.0", path = "crates/science" }
corescout-core tiene 25 dependientes, todos ellos sus propios hermanos. Según los datos de dependencias inversas, corescout-mcp tiene 16 de mis otros crates en algún punto de su árbol de dependencias, así que un solo cargo install corescout-mcp en una máquina limpia debería aparecer como hasta 17 descargas repartidas en 17 páginas de crates. En los 69 crates, la API de dependencias inversas lista 178 versiones dependientes, y todas son mías.
Esa es la parte cruel. Los crates con más dependientes parecen los más "usados" (11 crates con cinco o más dependientes tuvieron una mediana de 6 descargas tranquilas; los 25 crates sin dependientes tuvieron una mediana de cero en 89 días), y todo es cableado mío.
La línea base tranquila: la única cifra que significa personas
Quita las ventanas de publicación y los barridos y te quedan 339 descargas en 89 días, unas 3,8 al día entre los 69 crates. Es lo más parecido a "alguien, en algún sitio, compiló hoy con mi código". No es cero, y ha ido subiendo: el portafolio promedió 1,7 descargas tranquilas al día a finales de julio, 3,4 en agosto, 2,8 en septiembre y 8,1 en la primera mitad de octubre (con muchos más crates, así que toma octubre con cautela).
Un solo crate hace la mayor parte del trabajo. Solo fin-primitives suma 128 de las 339 descargas tranquilas (38%), una o dos casi todos los días desde julio, mucho antes de la avalancha de publicaciones de este otoño. Apuesto a que un puñado de personas o un pipeline de CI compila contra él con regularidad. Es una señal real, y es justo lo que un "son bots del día de publicación" tiraría a la basura junto con el ruido.
Y la cifra que zanja cualquier discusión: dependencias inversas externas, 0. Ningún crate publicado fuera de los míos usa ninguno de los 69. El índice de crates.io de ecosyste.ms es una buena segunda fuente para esto, porque también registra repositorios que dependen de un crate sin publicar uno.
Haz esto con tus propios crates
- Lee tu cifra como tres cifras. Ventana de publicación, barrido y tranquilo. Ejecuta el clasificador de arriba (o simplemente mira los colores por versión en la página de tu crate); solo la línea tranquila habla de usuarios.
- Cuenta con unas 10 a 15 descargas gratis por versión. Si un crate recién publicado muestra 12 descargas el primer día, todavía no lo ha encontrado nadie, y no pasa nada. Si muestra 12 un martes cualquiera tres semanas después, probablemente alguien sí.
- No publiques versiones para inflar el recuento. Funciona (acabamos de medir que funciona), y precisamente por eso el recuento no sirve como indicador de popularidad, y por eso quien evalúe tu crate mirará los dependientes y la actividad reciente.
- Cuenta dependientes, no descargas. La pestaña Dependents de crates.io, la API de dependencias inversas y el "Used by" de GitHub son donde se ve la adopción real. Un crate en el árbol de dependencias de otra persona vale más que mil descargas del día de publicación, porque cada ejecución de su CI descarga también el tuyo, para siempre.
- Ten en cuenta que un workspace infla según su anchura. Dividir una herramienta en 30 crates hace que cada instalación parezca 30 descargas. Si quieres un titular honesto, da la cifra del crate binario.
- Vuelve a extraer los datos periódicamente. La API solo guarda 90 días de datos diarios por crate. Si quieres una tendencia, guarda el JSON cada mes; cuando un día sale de la ventana, su desglose diario se pierde para siempre.
Todas las cifras
| Medida (API de crates.io, consultada el 17 oct 2026, 7:10 AM ET) | Valor |
|---|---|
| Crates / versiones | 69 / 235 |
| Descargas históricas | 4.815 |
| Descargas del 20 jul al 16 oct (89 días) | 3.676 |
| En una ventana de publicación | 2.945 (80,1%) |
| En días de barrido | 392 (10,7%) |
| Tranquilas | 339 (9,2%), 3,8/día |
| Descargas por versión nueva, día 0 (media / mediana) | 13,45 / 10 |
| Proporción de descargas de la primera semana en el día 0 o 1 | 86,9% |
| Recuento histórico más bajo de cualquier versión | 9 |
| Correlación, versiones frente a descargas | 0,82 |
| Dependencias inversas externas | 0 |
Que quede claro: este no es un artículo de "las descargas son falsas". Las reglas de recuento son públicas y razonables, y la línea base tranquila es real y crece. Es un artículo de "sé qué parte de la cifra estás mirando". El próximo hito que me importa no son las 10.000 descargas, sino el primer crate con un dependiente externo. Volveré a extraer los datos dentro de 30 días y publicaré la diferencia.
Si mantienes crates: ¿cómo es tu línea base de días tranquilos comparada con tu total? Me gustaría de verdad saber si un 80% en ventana de publicación es normal en crates pequeños o si mis hábitos de publicación lo empeoraron.
Más de los mismos proyectos: la caché semántica dentro de tokio-prompt-orchestrator, 20 agentes de programación en un solo PC (los agentes que actualizaron estos crates) y instancing en Bevy con 639.000 unidades.
Publicado originalmente aquí, en tensorust.com, el 17 de octubre de 2026. También en dev.to. Relacionado: Analiza cualquier crate: descargas reales frente a bots del día de publicación, Los 69 crates en crates.io, Herramientas para trabajar con agentes de programación, La caché semántica de tokio-prompt-orchestrator.
Lee a continuación
- Dev · 23 oct 2026 · 13 min de lecturaElige una biblioteca UUIDv7 que mantenga el orden: 10 probadas, .NET falla el 50%
- Juegos · 19 oct 2026 · 18 min de lecturaEl archivo de guardado de Balatro se ejecuta como código. 1 de cada 5 partidas corruptas carga igualmente
- Dev · 18 oct 2026 · 14 min de lecturaConstruir una base de datos en Rust: la IA pasó 866K tests y luego falló en ROLLBACK