Contagem de downloads do crates.io: 80% dos nossos chegaram junto com uma versão nova

Resumo: Em 17 de outubro de 2026 eu puxei todos os números diários de downloads que o crates.io tem para os meus 69 crates Rust. Em 89 dias eles registraram 3.676 downloads, e 80,1% deles caíram no dia em que uma versão nova subiu ou no dia seguinte. Uma versão nova junta cerca de 13 downloads nas primeiras 24 horas, não importa o que tenha dentro, e depois fica no zero. Crates de terceiros que dependem de algum dos 69: zero. O número que realmente diz se as pessoas usam o seu crate é a linha de base dos dias calmos, e no nosso caso foram 339 downloads, cerca de 3,8 por dia.
Resposta curta para quem chegou pela busca. A contagem de downloads do crates.io é o número de vezes que o arquivo .crate do crate foi baixado da CDN do crates.io, contado a partir dos logs de requisição da CDN (o crates.io passou a contar pelos logs em março de 2024). Desde 29 de outubro de 2025, só contam as requisições que parecem vir do cargo (ou que não mandam user agent nenhum). Ela não é uma contagem de usuários, instalações ou projetos. O CI de um único desenvolvedor que roda cargo build numa máquina limpa 30 vezes por dia soma 30 downloads por dia; uma pessoa que instala o seu crate uma vez e o mantém no cache local soma um, e pronto.
Então, o que existe de fato dentro do número de um crate pequeno? Abaixo estão uma medição nova num portfólio real, o script que puxa os dados (copie e rode nos seus próprios crates) e como ler o seu gráfico sem mentir para si mesmo em nenhuma das duas direções.

De onde vieram os 69 crates
Um pouco de contexto, porque o formato dos dados vem direto de como esses crates foram publicados. Eu mantenho uma pilha de bibliotecas e ferramentas em Rust: fin-primitives (blocos básicos para trading), tokio-prompt-orchestrator (um proxy de LLM com deduplicação e circuit breaker), proof-engine (uma engine de jogos em OpenGL) e o CoreScout, um servidor MCP dividido num workspace de 33 crates.
Eles saíram em três levas: 51 versões em março de 2026, 116 em setembro e 68 em outubro, 235 versões no total. A leva de outubro foi uma única grande rodada de releases em 4 de outubro, depois de uma passada em que agentes de programação com IA atualizaram todos os crates e eu publiquei tudo de uma vez no final. Esse único dia pesa muito mais adiante.
Total histórico quando puxei os dados, às 7h10 (ET) de 17 de outubro: 4.815 downloads. O número de "recent downloads" do crates.io (últimos 90 dias) era 3.677. A minha meta para esses crates é 100.000, então a pergunta honesta é quanto desses 4.815 é gente.
Puxe os números você mesmo em 40 linhas
O crates.io tem uma API JSON pública. Ela não é versionada formalmente, mas é o que o próprio site chama, e a política de acesso a dados pede duas coisas: no máximo uma requisição por segundo e um User-Agent que diga quem você é. Três endpoints dão tudo de que você precisa:
/api/v1/crates?user_id=N: todos os crates de um usuário, com totais históricos e de 90 dias./api/v1/crates/<name>/downloads: downloads diários dos últimos 90 dias, separados por versão (as versões mais antigas ficam agrupadas emextra_downloads)./api/v1/crates/<name>/reverse_dependencies: quais crates publicados dependem deste.
Este é o script que rodei hoje de manhã (pull.py, cortando só a parte que seleciona os campos do JSON). Ele para na hora num 429 em vez de tentar de novo, porque um scraper educado não discute com um rate limit:
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 vezes três chamadas, uma por segundo, levou cerca de três minutos e meio. Depois veio uma segunda passada de 69 chamadas para mapear os ids de versão para números de versão e horários de publicação, porque o endpoint de downloads rotula cada linha com um id numérico de versão, não com "2.15.0".

Se você tem mais do que algumas centenas de crates (ou quer todos os crates do registro), não martele a API: o crates.io publica um dump do banco de dados a cada 24 horas (static.crates.io/db-dump.tar.gz) que inclui a tabela de downloads por dia e por versão dos últimos 90 dias.
O que a página do crates.io mostra
Aqui está o fim da página do fin-primitives, o meu crate mais baixado. Olhe o gráfico antes de ler os números: uma oscilação baixa de 0 a 3 por dia durante o verão, depois picos altos na última semana de setembro e na primeira semana de outubro, cada pico de uma cor diferente. Cada cor é uma versão.

Esse gráfico é honesto, mas é por crate. Com 69 crates não dá para analisar 69 gráficos no olho, então classifiquei cada crate-dia da janela de 90 dias em três grupos.
Os três tipos de dia de download
A regra é simples e totalmente mecânica:
- Janela de publicação: aquele crate publicou uma versão neste dia UTC ou no dia anterior.
- Dia de varredura: nenhuma publicação, mas pelo menos metade de todos os meus crates que existiam foram baixados no mesmo dia.
- Calmo: todo o resto.
O núcleo do classificador, tirado do 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
E o resultado de 20 de julho a 16 de outubro de 2026 (89 dias UTC completos, 3.676 downloads):

2.945 downloads (80,1%) vieram numa janela de publicação. 392 (10,7%) vieram em seis dias de varredura. 339 (9,2%) foram downloads de dias calmos. O maior dia isolado foi 4 de outubro, a rodada de releases: 68 versões publicadas, 1.195 downloads.
Dito de outro jeito: se eu nunca tivesse publicado aquelas versões de setembro e outubro, o número de 90 dias teria ficado em algo perto de 730, não 3.676.
Uma versão nova ganha uns 13 downloads, e depois nada
Para ver quanto vale uma publicação por si só, peguei todas as versões publicadas dentro da janela com pelo menos uma semana de dados depois (181 versões) e alinhei os downloads de cada uma pelos dias desde a publicação.

Média de downloads no dia 0: 13,45 (mediana 10). Dia 1: 1,21. Dia 2: 0,02. 86,9% dos downloads da primeira semana de uma versão chegam no dia 0 ou no dia 1. O menor total de dia 0 mais dia 1 entre todas as versões foi 8, o maior 66, a mediana 12.
O piso é o que entrega tudo. Entre as 235 versões já publicadas, a menor contagem histórica de uma única versão é 9. A mediana é 18. Tenho 19 crates que só tiveram uma versão, incluindo crates internos de encanamento como corescout-cli e corescout-lineage, que ninguém fora deste projeto tem motivo para conhecer. Os totais históricos deles vão de 10 a 28, mediana 15. Alguma coisa baixa cada versão nova poucas horas depois da publicação, quer um humano leia o README ou não.
Que coisa é essa? Os dados não dizem. O meu palpite, e é só um palpite: mirrors do registro e build farms que acompanham o índice do crates.io e baixam as versões novas assim que aparecem, além de scanners de segurança e de licença. O filtro de user agent de 2025 foi escrito para descartar mirrors, então o que passa por ele é o próprio cargo ou um cliente que não manda user agent. O docs.rs também gera documentação para cada versão nova automaticamente; não consegui confirmar na documentação pública se esse download é contado, então não estou afirmando que seja.
A consequência é bem prática: no crates.io, o número de versões que você publica prevê os seus downloads melhor do que qualquer coisa no código. Nos meus 69 crates, a correlação entre número de versões e downloads históricos é 0,82. É por isso que o fin-primitives (13 versões) lidera e os meus crates genuinamente mais interessantes ficam atrás dele.
Dias de varredura: quando todos os crates são atingidos de uma vez
O segundo grupo me surpreendeu mais. Em 9 de outubro nada foi publicado, e mesmo assim todos os 69 crates foram baixados no mesmo dia, 184 downloads no total. Em 13 de outubro: 56 de 69 crates, a maioria com um download cada. Isso não é uma pessoa. Uma pessoa instala uma ferramenta e a árvore de dependências dela, não um crate de estatística, um crate de trading, uma engine de jogos e um conselheiro de TFT na mesma tarde.

Seis dias da janela seguem esse padrão: 3 de agosto (17 de 17 crates que existiam na época), 29 de setembro e 5, 9, 13 e 15 de outubro. Alguns dos mais recentes pendem para a família CoreScout: em 6 e 15 de outubro os crates no topo eram corescout-core, corescout-mirror e corescout-memory, exatamente o que você veria se algo resolvesse a árvore de dependências de um binário do CoreScout. Isso nos leva ao multiplicador de que ninguém fala.
Workspaces multiplicam a contagem
O CoreScout é um workspace do Cargo, e quando você publica um workspace no crates.io, cada membro vira um crate próprio. Aqui está o Cargo.toml raiz real (trecho):
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" }
O corescout-core tem 25 dependentes, todos eles irmãos dele mesmo. Pelos dados de dependências reversas, o corescout-mcp tem 16 dos meus outros crates em algum ponto da árvore de dependências, então um único cargo install corescout-mcp numa máquina limpa deve aparecer como até 17 downloads espalhados por 17 páginas de crates. Somando os 69 crates, a API de dependências reversas lista 178 versões dependentes, e todas elas são minhas.
Essa é a parte cruel. Os crates com mais dependentes parecem os mais "usados" (11 crates com cinco ou mais dependentes tiveram mediana de 6 downloads calmos; os 25 crates sem dependentes tiveram mediana zero em 89 dias), e é tudo fiação minha.
A linha de base dos dias calmos: o único número que significa pessoas
Tire as janelas de publicação e as varreduras e sobram 339 downloads em 89 dias, cerca de 3,8 por dia somando os 69 crates. É o mais perto que existe de "alguém, em algum lugar, compilou algo com o meu código hoje". Não é zero, e vem subindo: o portfólio teve média de 1,7 download calmo por dia no fim de julho, 3,4 em agosto, 2,8 em setembro e 8,1 na primeira metade de outubro (com muito mais crates, então trate outubro com cuidado).
Um crate faz a maior parte do trabalho. Só o fin-primitives responde por 128 dos 339 downloads calmos (38%), um ou dois na maioria dos dias desde julho, muito antes da pilha de releases deste outono. A minha aposta é que um punhado de pessoas ou um pipeline de CI compila contra ele regularmente. Isso é um sinal real, e é exatamente o que um "é tudo bot de dia de publicação" jogaria fora junto com o ruído.
E o número que encerra qualquer discussão: dependências reversas externas, 0. Nenhum crate publicado fora os meus usa algum dos 69. O índice do crates.io no ecosyste.ms é uma boa segunda fonte para isso, já que ele também acompanha repositórios que dependem de um crate sem publicar nenhum.
Faça isso com os seus crates
- Leia o seu número como três números. Janela de publicação, varredura e calmo. Rode o classificador acima (ou simplesmente olhe as cores por versão na página do seu crate); só a linha calma diz respeito a usuários.
- Conte com uns 10 a 15 downloads por versão de graça. Se um crate novinho mostra 12 downloads no primeiro dia, ninguém o encontrou ainda, e tudo bem. Se mostra 12 numa terça-feira qualquer três semanas depois, provavelmente alguém encontrou.
- Não lance versões para inflar a contagem. Funciona (acabamos de medir funcionando), e é exatamente por isso que a contagem não serve como número de popularidade, e por isso que quem for avaliar o seu crate vai olhar dependentes e atividade recente.
- Conte dependentes, não downloads. A aba Dependents do crates.io, a API de dependências reversas e o "Used by" do GitHub são onde a adoção real aparece. Um crate na árvore de dependências de outra pessoa vale mais do que mil downloads de dia de publicação, porque cada execução de CI dela baixa o seu também, para sempre.
- Saiba que um workspace infla pela sua largura. Dividir uma ferramenta em 30 crates faz cada instalação parecer 30 downloads. Informe o número do crate binário se quiser uma manchete honesta.
- Puxe os dados de novo com regularidade. A API só guarda 90 dias de dados diários por crate. Se você quer uma tendência, salve o JSON todo mês; quando um dia sai da janela, a divisão por dia se perde para sempre.
Os números, todos eles
| Medida (API do crates.io, dados puxados em 17 de out. de 2026, 7h10 ET) | Valor |
|---|---|
| Crates / versões | 69 / 235 |
| Downloads históricos | 4.815 |
| Downloads de 20 de jul. a 16 de out. (89 dias) | 3.676 |
| Numa janela de publicação | 2.945 (80,1%) |
| Em dias de varredura | 392 (10,7%) |
| Calmos | 339 (9,2%), 3,8/dia |
| Downloads por versão nova, dia 0 (média / mediana) | 13,45 / 10 |
| Fração dos downloads da primeira semana no dia 0 ou 1 | 86,9% |
| Menor contagem histórica de uma versão | 9 |
| Correlação, versões vs downloads | 0,82 |
| Dependências reversas externas | 0 |
Para constar: este não é um post do tipo "os downloads são falsos". As regras de contagem são públicas e razoáveis, e a linha de base dos dias calmos é real e está crescendo. É um post do tipo "saiba qual parte do número você está olhando". O próximo marco que me importa não são 10.000 downloads, é o primeiro crate com um dependente externo. Vou puxar isso de novo daqui a 30 dias e publicar a diferença.
Se você mantém crates: como fica a sua linha de base dos dias calmos perto do seu total? Eu queria muito saber se 80% em janela de publicação é normal para crates pequenos ou se os meus hábitos de release pioraram a situação.
Mais dos mesmos projetos: o cache semântico dentro do tokio-prompt-orchestrator, rodando 20 agentes de programação num único PC (os agentes que atualizaram esses crates) e instancing no Bevy com 639.000 unidades.
Publicado originalmente aqui no tensorust.com em 17 de out. de 2026. Também no dev.to. Relacionados: Confira qualquer crate: downloads reais vs bots de dia de release, Os 69 crates no crates.io, Ferramentas para rodar agentes de programação, O cache semântico no tokio-prompt-orchestrator.
Leia também
- Dev · 23 de out. de 2026 · 13 min de leituraEscolha uma biblioteca UUIDv7 que mantenha a ordem: 10 testadas, .NET falha em 50%
- Games · 19 de out. de 2026 · 18 min de leituraO save do Balatro roda como código. 1 em cada 5 saves corrompidos carrega mesmo assim
- Dev · 18 de out. de 2026 · 14 min de leituraConstrua um banco de dados em Rust: a IA passou em 866 mil testes e depois falhou no ROLLBACK