X APIの従量課金を前に、特定アカウントのツイートをリアルタイムで取得する安い方法、つまりX APIの代替を探していませんか? Angelic Angelは、ブラウザ向けに届くX(旧Twitter)の通知を受け取り、指定したWebhookへ流します。Rust製のCLIで、3月にGitHubへ置かれ、10月4日から5日にかけて急にフォークが増えました。
試したのは、CPU1コアの使い捨てコンテナでビルドし、ダミーのCookieで register を実行したところまでです。自分のXアカウントは使っておらず、通知の受信、Webhookに届くJSON、遅延は確かめていません。それでも、Xに401で弾かれた時点でMozilla側には購読ができていたこと、設定ファイルの権限、READMEに書かれていない動きは、使う前に知っておきたい内容でした。
Angelic AngelでXの通知がWebhookに届くまで
XはWeb Pushで、Mozillaのサーバーに通知を投げる
ブラウザでXの通知を許可すると、Xはブラウザごとの中継サーバーへ通知を送ります。この仕組みがWeb Pushで、標準仕様です。中継役はブラウザで違い、ChromeはFCM、SafariはAPNs、FirefoxはMozilla AutoPushです。FirefoxはAutoPushとWebSocketでつながり続けるので、ブラウザが起動していればタブを閉じていても通知が出ます。
Angelic Angelは、このFirefoxの役を演じます。AutoPushに購読を作り、受け取った購読用URLをXに「ここへ通知を送って」と登録して、あとは待ち続ける。Xから見れば、通知の受け手はMac版Firefox1台です。
READMEによれば、届くのはフォローしていて、なおかつ投稿通知をオンにしたアカウントのツイートです。いいねやDMなど他の種類の通知が届くかは確かめていません。キーワードで探す使い方には向きません。
ECEで復号して、WEBHOOK_ENDPOINTにPOSTする
通知はWeb Pushの暗号化方式ECE(Encrypted Content-Encoding)で暗号化されていて、購読時に作った秘密鍵がないと読めません。ソースでは ece クレートで aes128gcm と旧方式の aesgcm の両方を復号しています。
復号した中身は、環境変数 WEBHOOK_ENDPOINT のURLへHTTP POSTで送られます。Xの通知の中身をそのまま渡すので、どんな項目が入るかはソースからは分かりませんでした。
再接続は、接続に失敗したときが5秒から倍々(上限5分)、つながったあとに切れたときが1秒で、close code 4774なら30分待ちます。復旧できないエラーでは listen が終了します。
ダミーのauth_tokenでregisterすると、どこで止まるのか?
cargo install --path . のビルドは6分42秒で、1回で通りました。angelic-angel init にダミーの --auth-token と --ct0 を渡すと、angelic-angel.toml ができます。
[twitter]
auth_token = "DUMMY..."
ct0 = "DUMMY..."Cookieの値が平文で並び、ファイル権限は -rw-r--r--(644)でした。共有のマシンなら、Cookieを他のユーザーに見せているのと同じです。なお既定のファイル名はリポジトリの .gitignore に入っていますが、-c で別名にすると対象外です。
続けて angelic-angel -v register を実行すると、前半のAutoPushへの登録はXの認証情報なしで通り、https://updates.push.services.mozilla.com/wpush/v2/... という購読用URLが返ってきました。ダミーのCookieでも、ここまでは進めてしまいます。止まったのは、そのURLをXの login.json へ送る後半です。
error: Twitter API error: push subscription registration failed (401 Unauthorized): {"errors":[{"code":32,"message":"Could not authenticate you."}]}ここまで約1.3秒。デバッグログでは、送信ボディの os_version と udid がどちらも "Mac/Firefox" で、ダミーのCookie値とBearerトークンの文字列は1件も出ませんでした。失敗後も status は「not registered」のままです。ソースを読むと、AutoPush側の購読だけが残り、設定ファイルに保存されないので unregister でも消せません。
Angelic AngelのREADMEに書かれていない、3つの動き
listen中もX APIを呼ぶことがある
READMEには、X APIを呼ぶのは register のときだけで、待ち受け中は呼ばないとあります。ソースでは、listen の最中にAutoPush側の購読ID(UAID)が無効になると自動で登録し直し、そのときXの登録用エンドポイントをもう一度呼んでいます。
UAIDが変わるかはAutoPush側の都合です。通知を待っているだけのはずの常駐プロセスが、いつの間にかCookieを付けてXへ接続している可能性があります。この食い違いはIssue #3でも10月5日に指摘されています。常駐させるなら、動かす場所とログを見る頻度を先に決めておくのが前提です。
Webhookが2xx以外を返しても、AutoPushには受け取ったと返す
コードを読むと、Webhookが2xx以外を返したときは警告ログを出すだけで、AutoPushには「受け取った」と返しています。READMEはこの扱いに触れていません。
not_delivered を返すのは、Webhookへ接続できない場合や WEBHOOK_ENDPOINT が未設定の場合など、復号以外の処理が失敗したときです。Webhookが500を返した通知に気づける手がかりは、警告ログだけになります。
unregisterでは、X側の登録が残る
unregister が解除するのはAutoPush側の購読だけで、Xに登録した「このFirefoxへ通知を送る」設定を消す処理はソースにありません。READMEには購読の解除とだけあります。X側に何が残るかまでは確かめていませんが、ツールにはX側を消す手段がありません。やめたつもりでも、登録は残っているかもしれません。
auth_tokenとct0は、アカウントの合鍵
auth_token はXにログインしたときに発行されるCookieで、ct0 はCSRF対策のトークンです。2つがそろうと、ログイン済みのブラウザと同じようにWeb版Xへリクエストを送れます。
ソースでは、Web版Xが使う公開のBearerトークンを固定値で埋め込み、2つのCookieと x-csrf-token を添えて送っています。開発者向けのAPIキーは使いません。欲しいのは通知だけなのに、渡しているのはアカウント全体の鍵です。
その鍵を、通知のためだけに常駐プロセスへ預けてよいでしょうか? 漏れれば、セッションが切れるまで、他人があなたのログイン状態でWeb版Xを操作する恐れがあります。
X利用規約は、このアクセスをどう書いているのか?
X利用規約の「Misuse of the Services」の項 (iii) は、Xが用意した手段以外でのアクセスを禁じています。要の部分は "other than through our currently available, published interfaces"(現在提供している公開済みのインターフェース以外の手段で)です。
これは2026年10月6日時点の現行版の条文で、10月9日に施行される次版にも同じ文があります。どちらの要約部分にも、Xが課す技術的な制限を回避しようとしてはならない、という趣旨の一文があります。
一方、Angelic Angelが叩く login.json は、開発者向けドキュメントに載っていないWeb版の内部エンドポイントです。これが違反にあたるかを、私は断定しません。Issue #3も違反とは言わず、条文を知っておくべきだという立場です。
同じくWeb Pushを使うtweet-boxは、「アカウントの BAN や IP BAN のリスクはありません」と説明しています。ただ、目立ちにくいことと規約上問題がないことは別で、凍結を決めるのはXです。
X APIの従量課金と並べたときの違い
数字は2026年10月6日時点のX APIの料金ページによります。X APIは2026年に従量課金だけの体系へ移り、同じ投稿を24時間(UTC)以内に何度読んでも1回分の課金です。
20アカウントが1日10投稿ずつなら、月6,000投稿で30ドル(約4,500円)です。あなたの用途は、この金額に収まりますか? 収まるなら、Cookieを預けるより公式の手段で取るほうが失うものは少ない、と私は考えます。
Angelic Angelを使うなら、サブアカウントと止め方を先に決める
それでも試すなら、壊れても困らない形にします。
- 対象をフォローして通知をオンにしただけのサブアカウントのCookieを使う
initの前にumask 077をかけ、angelic-angel.tomlを最初から自分だけが読める権限で作る- Webhook側は受け取った内容をまず保存し、重い処理はあとに回す
- やめるときは
unregisterで終わらせず、Xのセッション一覧から該当するログインも切る
サブアカウントにしても、規約上の扱いは変わりません。変わるのは、凍結や漏えいが起きたときに失うものの大きさです。
様子見も筋の通った選択です。v0.1.0でコミットは3月5日の3本、READMEとの食い違いを指摘したIssueもまだ開いたままです。その扱いを見てから決めても遅くありません。



コメント
ログイン か 会員登録 するとコメントできます