crates.io のダウンロード数:私たちの80%は新バージョンと一緒にやって来た

要点:2026年10月17日、私が持っている Rust の crate 69個について、crates.io にある日次ダウンロード数をすべて取得しました。89日間の合計は 3,676ダウンロードで、その80.1%は新バージョンが公開された当日か翌日に集中していました。新バージョンは中身に関係なく最初の24時間で約13ダウンロードを集め、そのあとは横ばいになります。69個のどれかに依存している外部の crate は、ゼロでした。crate が実際に使われているかどうかを本当に示す数字は「静かな日のベースライン」で、私たちの場合は339ダウンロード、1日あたり約3.8でした。
検索で来た方のために、短い答えから。crates.io のダウンロード数とは、crate の .crate ファイルが crates.io の CDN から取得された回数で、CDN のリクエストログから数えられています(crates.io は2024年3月にログベースの集計へ移行しました)。2025年10月29日以降は、cargo から来たように見えるリクエスト(またはユーザーエージェントをまったく送らないリクエスト)だけがカウントされます。ユーザー数、インストール数、プロジェクト数ではありません。ある開発者の CI がクリーンなマシンで cargo build を1日30回実行すれば、1日30ダウンロード増えます。一方、一度インストールしてローカルキャッシュに保持している人は、後にも先にも1回分しか増やしません。
では、小さな crate の数字の中身は実際どうなっているのでしょうか。以下では、実際のポートフォリオで新たに測定した結果、データを取得するスクリプト(コピーして自分の crate で実行できます)、そしてどちらの方向にも自分をごまかさずにチャートを読む方法を紹介します。

69個の crate の出どころ
データの形は crate の公開のしかたにそのまま由来するので、少し背景を説明します。私は Rust のライブラリとツールをたくさんメンテナンスしています。fin-primitives(トレーディング用の基本部品)、tokio-prompt-orchestrator(重複排除とサーキットブレーカーを備えた LLM プロキシ)、proof-engine(OpenGL のゲームエンジン)、そして33個の crate からなるワークスペースに分割された MCP サーバー、CoreScout です。
公開は3回の集中期に分かれています。2026年3月に51バージョン、9月に116、10月に68、合計235バージョンです。10月の分は10月4日の1回の大きなリリース作業で、AI のコーディングエージェントがすべての crate をアップグレードしたあと、最後にまとめて一気に公開しました。この1日が、あとで大きな意味を持ちます。
10月17日午前7時10分(米東部時間)に取得した時点の累計は 4,815ダウンロードでした。crates.io の「recent downloads(直近90日)」の数字は3,677です。これらの crate の目標は100,000なので、正直に問うべきは「4,815のうち、どれだけが人間なのか」です。
40行で自分の数字を取得する
crates.io には公開の JSON API があります。正式にバージョン管理されてはいませんが、ウェブサイト自体が呼び出しているもので、データアクセスポリシーが求めているのは2つだけです。リクエストは1秒に1回まで、そして自分が誰かを示す User-Agent を付けること。次の3つのエンドポイントで必要なものはすべて揃います。
/api/v1/crates?user_id=N:ユーザーが所有するすべての crate と、その累計および90日間の合計。/api/v1/crates/<name>/downloads:直近90日の日次ダウンロード数をバージョン別に(古いバージョンはextra_downloadsにまとめられます)。/api/v1/crates/<name>/reverse_dependencies:この crate に依存している公開済み crate。
これが今朝実行したスクリプトです(pull.py、JSON のフィールド抽出部分だけ省略しています)。429 が返ったらリトライせずにその場で止まります。行儀のよいスクレイパーはレート制限と言い争わないからです。
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個の crate に3回ずつ、1秒に1回の呼び出しで、約3分半かかりました。そのあと、バージョン ID をバージョン番号と公開時刻に対応付けるために69回の呼び出しをもう一巡しています。downloads エンドポイントは各行に「2.15.0」ではなく数値のバージョン ID を付けているからです。

crate が数百個以上ある場合(またはレジストリ上のすべての crate が欲しい場合)は、API を叩きすぎないでください。crates.io は24時間ごとにデータベースダンプ(static.crates.io/db-dump.tar.gz)を公開していて、直近90日の日別・バージョン別ダウンロード表も含まれています。
crates.io のページに表示されるもの
こちらは、私の crate の中で最もダウンロードされている fin-primitives のページ下部です。数字を読む前にチャートを見てください。夏の間は1日0〜3の低い波が続き、9月最終週と10月第1週に背の高いスパイクが立っていて、スパイクごとに色が違います。色はそれぞれバージョンを表しています。

このチャートは正直ですが、crate ごとです。69個もあると69枚のチャートを目で追うことはできないので、90日間の「crate × 日」をすべて3つのバケットに分類しました。
ダウンロードがあった日の3つの種類
ルールはシンプルで、完全に機械的です。
- 公開ウィンドウ:その crate がその UTC 日、または前日にバージョンを公開している。
- 一斉取得日:公開はないが、その時点で存在していた私の crate の半数以上が同じ日にダウンロードされている。
- 静かな日:それ以外すべて。
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
2026年7月20日から10月16日まで(UTC で丸89日、3,676ダウンロード)の結果は次のとおりです。

2,945ダウンロード(80.1%)は公開ウィンドウ内でした。392(10.7%)は6回の一斉取得日、339(9.2%)が静かな日のダウンロードです。単日で最も多かったのはリリース作業をした10月4日で、68バージョンを公開し、1,195ダウンロードでした。
言い換えると、9月と10月のバージョンを一切公開していなければ、90日間の数字は3,676ではなく、730前後だったはずです。
新バージョンは約13ダウンロード、あとは何もなし
公開それ自体にどれだけの価値があるかを見るために、期間内に公開され、公開後に少なくとも1週間分のデータがあるバージョンをすべて(181バージョン)取り出し、公開からの経過日数ごとにダウンロード数を並べました。

0日目の平均ダウンロード数は 13.45(中央値10)。1日目は1.21、2日目は0.02です。バージョンの最初の1週間のダウンロードのうち86.9%が0日目か1日目に届きます。0日目と1日目の合計は、最小のバージョンで8、最大で66、中央値は12でした。
決め手は下限です。これまでに公開した235バージョン全体で、1バージョンの累計の最小値は 9、中央値は18です。バージョンが1つしかない crate が19個あり、その中には corescout-cli や corescout-lineage のように、このプロジェクトの外の人が知る理由のない内部用の配管的な crate も含まれます。それらの累計は 10〜28、中央値15です。人間が README を読むかどうかに関係なく、何かが新バージョンを公開から数時間以内に取得しているのです。
その「何か」とは何でしょうか。データからはわかりません。推測、あくまで推測ですが、crates.io のインデックスを追いかけて新バージョンが出るたびに取得するレジストリのミラーやビルドファーム、それにセキュリティやライセンスのスキャナーだと思います。2025年のユーザーエージェントフィルターはミラーを除外するために作られたので、それをすり抜けるのは cargo そのものか、ユーザーエージェントを送らないクライアントのどちらかです。docs.rs も新バージョンごとに自動でドキュメントをビルドしますが、その取得がカウントされるかどうかは公開ドキュメントから確認できなかったので、カウントされているとは主張しません。
結論はとても実用的です。crates.io では、公開したバージョンの数のほうが、コードの中身の何よりもダウンロード数をよく予測します。私の69個の crate では、バージョン数と累計ダウンロード数の相関は0.82でした。fin-primitives(13バージョン)がトップで、本当はもっと面白い crate たちがその後ろにいるのはこのためです。
一斉取得日:すべての crate が同時に取得される日
2つ目のバケットには、さらに驚かされました。10月9日には何も公開していないのに、69個すべての crate が同じ日にダウンロードされ、合計184ダウンロードでした。10月13日は69個中56個で、ほとんどが1ダウンロードずつ。これは人ではありません。人がインストールするのは1つのツールとその依存ツリーであって、統計用の crate、トレーディング用の crate、ゲームエンジン、TFT のアドバイザーを同じ午後にまとめて入れたりはしません。

期間中、このパターンに当てはまる日は6日あります。8月3日(当時存在した17個中17個)、9月29日、10月5日、9日、13日、15日です。後半のいくつかは CoreScout ファミリーに偏っています。10月6日と15日の上位は corescout-core、corescout-mirror、corescout-memory で、何かが CoreScout のバイナリの依存ツリーを解決したならちょうどこう見えるはずです。ここで、誰も触れない「乗数」の話になります。
ワークスペースはカウントを掛け算する
CoreScout は Cargo ワークスペースで、ワークスペースを crates.io に公開すると、各メンバーがそれぞれ独立した crate になります。実際のルートの Cargo.toml(抜粋)です。
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 には25の依存元がありますが、すべて自分の兄弟 crate です。逆依存データによれば、corescout-mcp の依存ツリーには私のほかの crate が16個含まれているので、クリーンなマシンで cargo install corescout-mcp を1回実行すると、17個の crate ページに分散して最大17ダウンロードとして現れるはずです。69個全体で、逆依存 API には178の依存バージョンが載っていますが、そのすべてが私のものです。
ここが残酷なところです。依存元が最も多い crate ほど「使われている」ように見えます(依存元が5つ以上ある11個の crate は静かな日のダウンロードの中央値が6、依存元のない25個の crate は89日間で中央値ゼロ)。でもそれは、全部私自身の配線によるものです。
静かな日のベースライン:人を意味する唯一の数字
公開ウィンドウと一斉取得日を取り除くと、89日間で339ダウンロード、69個全体で1日あたり約3.8が残ります。これが「今日どこかの誰かが私のコードでビルドした」に最も近い数字です。ゼロではありませんし、増えてもいます。ポートフォリオ全体で、静かな日のダウンロードは7月下旬が1日平均1.7、8月が3.4、9月が2.8、10月前半が8.1でした(10月は crate の数がずっと多いので、慎重に見てください)。
大部分を担っているのは1つの crate です。fin-primitives だけで、静かな日のダウンロード339のうち128(38%)を占めています。7月以降ほとんどの日に1〜2回、この秋のリリースラッシュよりずっと前からです。私の見立てでは、少数の人か1本の CI パイプラインが定期的にこれを使ってビルドしています。これは本物のシグナルで、「公開日のボットだ」と切り捨ててしまうと、ノイズと一緒に捨ててしまうものです。
そして、あらゆる議論に決着をつける数字があります。外部からの逆依存は0です。私以外の公開済み crate で、69個のどれかを使っているものはありません。この点の2つ目の情報源としては ecosyste.ms の crates.io インデックスが便利です。crate を公開せずにある crate に依存しているリポジトリも追跡しているからです。
自分の crate でやってみる
- 自分の数字を3つの数字として読む。公開ウィンドウ、一斉取得日、静かな日です。上の分類スクリプトを実行する(または crate ページのバージョン別の色を見るだけでも)と、ユーザーに関係するのは静かな日の線だけだとわかります。
- 1バージョンあたり10〜15ダウンロードは自動的に付くと思っておく。新しい crate が初日に12ダウンロードでも、まだ誰にも見つかっていないだけで、それで問題ありません。3週間後の何でもない火曜日に12なら、たぶん誰かが見つけています。
- カウントを水増しするためにリリースしない。効果はあります(たった今それを測定しました)。だからこそ、この数字は人気の指標として信頼できず、crate を評価する人は依存元と最近の活動を見るのです。
- ダウンロード数ではなく依存元を数える。本当の採用が見えるのは、crates.io の Dependents タブ、逆依存 API、GitHub の「Used by」です。誰かの依存ツリーに入った crate 1つは、公開日の取得1,000回より価値があります。その人の CI が走るたびに、あなたの crate もずっとダウンロードされ続けるからです。
- ワークスペースはその幅の分だけ水増しされると知っておく。1つのツールを30個の crate に分割すると、インストール1回が30ダウンロードに見えます。正直な見出しにしたいなら、バイナリ crate の数字を報告しましょう。
- 定期的に取得し直す。API は crate ごとに90日分の日次データしか保持しません。推移を見たいなら毎月 JSON を保存してください。ウィンドウから外れた日の日別内訳は、二度と取り戻せません。
すべての数字
| 指標(crates.io API、2026年10月17日午前7時10分(米東部時間)取得) | 値 |
|---|---|
| crate 数 / バージョン数 | 69 / 235 |
| 累計ダウンロード数 | 4,815 |
| 7月20日〜10月16日(89日間)のダウンロード数 | 3,676 |
| 公開ウィンドウ内 | 2,945(80.1%) |
| 一斉取得日 | 392(10.7%) |
| 静かな日 | 339(9.2%)、1日あたり3.8 |
| 新バージョン1つあたりの0日目のダウンロード数(平均 / 中央値) | 13.45 / 10 |
| 最初の1週間のダウンロードのうち0日目または1日目の割合 | 86.9% |
| バージョン単位の累計の最小値 | 9 |
| 相関(バージョン数とダウンロード数) | 0.82 |
| 外部からの逆依存 | 0 |
念のため書いておくと、これは「ダウンロード数は偽物だ」という記事ではありません。集計ルールは公開されていて妥当ですし、静かな日のベースラインは本物で、しかも増えています。これは「数字のどの部分を見ているのかを知ろう」という記事です。私が次に気にしている節目は10,000ダウンロードではなく、外部の依存元を持つ最初の crate です。30日後にもう一度取得して、差分を公開します。
crate をメンテナンスしている方へ:あなたの静かな日のベースラインは、合計と比べてどれくらいでしょうか。小さな crate にとって公開ウィンドウ80%が普通なのか、それとも私のリリースの癖が悪化させたのか、ぜひ知りたいです。
同じプロジェクトからのほかの記事:tokio-prompt-orchestrator のセマンティックキャッシュ、1台の PC で20体のコーディングエージェントを動かす(これらの crate をアップグレードしたエージェントです)、639,000ユニットでの Bevy インスタンシング。
2026年10月17日に tensorust.com で初公開。dev.to にも掲載しています。関連:任意の crate をチェック:本当のダウンロード数とリリース日のボット、crates.io 上の69個すべての crate、コーディングエージェントを動かすためのツール、tokio-prompt-orchestrator のセマンティックキャッシュ。
次に読む
- 開発 · 2026年10月23日 · 13分で読めます順序を保つ UUIDv7 ライブラリの選び方:10個をテスト、.NET は50%失敗
- ゲーム · 2026年10月19日 · 18分で読めますBalatro のセーブファイルはコードとして実行される。壊れたセーブの5つに1つはそれでも読み込める
- 開発 · 2026年10月18日 · 14分で読めますRust でデータベースを作る:AI は866Kのテストに合格し、そして ROLLBACK で失敗した