X API自動投稿の罠。ローカルでは動くのにGitHub Actions経由だと403エラーに・・

以前、X(Twitter)の自動投稿ツールを作って運用していたのですが、そこでめちゃくちゃ足止めを食らいました。

いわゆる 「403 Forbidden」エラー。しかも突然に!!

一番謎だったのが、「自分のPC(ローカル)だと完璧に動くのに、GitHub Actionsに載せると速攻でエラーになる」っていう現象です。

トークンやキーの設定ミスかな?と思って、GitHubのSecretsを何度も入れ直したり、Xの管理画面で「Read and Write」を再確認したりしたんですけど、どこを見ても設定は合ってる。ローカルでは今も普通に投稿できているのに、GitHub上のサーバーからだけ「お前はダメだ」って拒否されるんです。

そう思って調べてみたら、どうやらGitHub Actionsが使っている「IPアドレス」そのものが、X側からマークされている説(拒否されている)が浮上、自分ではどうしようもない壁にぶつかっていたみたいです。

今回は、この「設定は合ってるのになぜか動かない問題」の正体と、これって実はシャドバンの原因にもなってたんじゃない?という実体験ベースの考察をまとめておこうと思います。

目次

403 Forbiddenエラーの「基本」をおさらい

まず、X APIを触っていて403が出たときに「真っ先に疑うべき定番の原因」を整理しておきます。本来、設定ミスで詰まっているなら以下のどこかに原因があるはずです。ここを完璧に潰しておかないと、その先の「IP制限説」にも確信が持てませんからね。

403エラーが出た時に確認するポイント
  • App Permissions(権限)の確認ミス
    XのDeveloper Portalにある「User authentication settings」の設定です。デフォルトでは『Read(読み取り専用)』になっていることが多く、このままだと投稿(Post)は絶対にできません。まずはここが『Read and Write(読み取りと書き込み)』、あるいはそれ以上の権限に設定されているかを再確認する必要があります。
  • 権限変更後のトークン再生成忘れ(これ、一番の罠です)
    実は、管理画面で権限を『Read and Write』にポチッと変更しただけでは、設定は反映されません。変更した後に「Keys and Tokens」タブを開き、Access TokenとSecretを 「Regenerate(再生成)」 し直さなければいけないんです。古いトークンは「Read権限」しか持っていない古い情報のままなので、これを使っている限り、どれだけ設定を変えてもXからは「お前、書き込み許可持ってないだろ」と403で拒否され続けます。
  • APIプランとエンドポイントの不一致
    現在のAPIプラン(特にFreeプラン)は、昔に比べてかなり制限がキツいです。例えば、他人のツイートを検索したり、過去のタイムラインを遡ったりするエンドポイントは、Freeプランでは許可されていないことが多いです。「投稿はできるけど、検索は403になる」という場合は、コードが叩いているAPIが自分のプランで許されているものか、公式のドキュメントと照らし合わせる必要があります。
  • 環境変数の読み込み失敗(Secretsの設定)
    GitHub Actions特有のポイントですが、GitHubの「Secrets」に登録した名前と、コード内(Pythonなど)で呼び出している名前が1文字でもズレているとアウトです。TWITTER_API_KEYX_API_KEY のように、ちょっとした名前の取り違えで中身が「空」のままリクエストが飛び、結果として「認証が不完全」=403エラーになる、というパターンもよく見かけます。

でも、私の場合、これらはすべて完璧にクリアしていました。なんせ 「ローカル(自分のPC)では1回も失敗せずに動いている」 のですから。キーやトークンも書き換えた記憶は一切ない!
設定自体に間違いがないことは、自分のPCでの成功実績が証明してくれていたんです。

ではなぜローカルで動いてGitHub Actionsでは動かないのか?

設定もコードも正しい。自分のPC(ローカル)からは、何度試しても投稿に成功する。それなのに、GitHub Actionsのボタンを押した途端に403エラーで叩き落とされる――。

この矛盾を前にして私がたどり着いた推測は、原因はコードの中身ではなく、「どこからリクエストを送っているか」という物理的な場所の違いにあるのではないか、ということでした。

結局、私の場合は「設定」が原因ではなかった(と思う)

GitHubのSecretsを何度も入力し直し、.yml ファイルのインデント一つまで疑って書き換えましたが、状況は1ミリも変わりませんでした。ここに至ってようやく、「自分側にミスがある」という前提を一度横に置いて、消去法で残った可能性に目を向けることになったんです。それが、「GitHub ActionsのIPアドレスそのものが、X側から制限されているのではないか」 という説です。

共有IPが招く「もらい事故」の可能性

GitHub Actionsを実行するとき、実際にプログラムを動かしているのはMicrosoft(Azure)の巨大なデータセンターにあるサーバーです。世界中の開発者が同じインフラを利用しているため、私たちが使う「IPアドレス(ネット上の住所)」は、自分専用ではなく 「共有IP」 という形になっています。

ここに、GitHub Actions特有の落とし穴があるのではないかと考えています。

ポイント
  • 連帯責任のようなブロック:
    同じIP帯域を使っている「誰か」が、もしXに対してスパム行為をしたり、過激なスクレイピングを仕掛けたりして目を付けられていたとしたら。X側のセキュリティシステムが「このあたりのIPから来るリクエストは一律で警戒対象」と判断し、その範囲のIPをまとめて制限に巻き込んでいる可能性があるんです。
  • 「外れIP」を引く確率:
    GitHubのランナーに割り当てられるIPは実行のたびに変わります。以前は動いていたのに最近ダメになった、という場合は、Xのスパム対策が厳しくなった結果、すでに「マークされている」IPを引き当ててしまう確率が上がっているのかもしれません。

導き出した一つの結論(仮説)

つまり、私のコードがどれだけ健全で、認証情報が完璧だったとしても、「GitHub Actionsという、不特定多数がシェアして使う場所」からリクエストを送っているというだけで、Xの門番(セキュリティフィルター)に中身も見られず門前払いされているのではないか……。それが、今回の403エラーの正体だと考えると、すべての辻褄が合うんです。

ローカル環境(自宅の回線)で成功するのは、そのIPアドレスが「一人の人間が使っている、信頼できるプロバイダーのもの」として、X側に受け入れられているからなのだと思います。

シャドウバンのリスクも?「共有IP」の怖さ

そして、今回の一件で一番「あ、もしかして…」とゾッとしたのが、アカウントの健康状態への影響です。

実は私、以前運用していたアカウントで、原因不明の シャドウバン(自分の投稿が検索に載らなくなったり、フォロワー以外のタイムラインに表示されなくなったりする制限) を食らった経験があります。

当時は「投稿内容が悪かったのかな?」「ハッシュタグが多すぎたかな?」と、ツイートの中身ばかり気にしていました。でも、今回の403エラー騒動を経て、別の可能性が浮上してきたんです。

それは、「GitHub Actionsという共有IPを使って、定期的に自動投稿(cron実行)を繰り返していたこと自体が、スパム判定のフラグになっていたのではないか」 ということです。

Xのアルゴリズムが「場所」を疑う可能性

Xのセキュリティシステムは、投稿内容と同じくらい「どこから(どのIPから)投稿されたか」を厳しくチェックしていると言われています。

  • 不自然なアクセスの連続: 普段、日本のスマホから使っているアカウントが、突然アメリカやヨーロッパにあるデータセンターのIPから毎日決まった時間に投稿してくる。
  • 「汚れたIP」との紐付け: 前述した通り、GitHub ActionsのIPは他人のスパム行為で汚れている可能性があります。そんな「評判の悪い場所」から投稿を繰り返せば、たとえ中身が普通の内容でも、システム側から「こいつは質の低いBotだな」と判断されてもおかしくありません。

もちろん、これも公式が認めたわけではないので、あくまで私の推測に過ぎません。ですが、もし「共有IPでの自動実行」が原因でアカウントの評価が密かに下がっていたのだとしたら……。せっかく便利にしようと思って自動化したのに、結果的に自分の大事なアカウントを傷つけていたことになります。これほどコスパの悪い話はありません。

403エラーで投稿が止まってしまったのは、ある意味「これ以上この場所から投稿するのは危ないぞ」という、X側からの最後のアラートだったのかもしれない。今はそんな風に感じています。

まとめ

今回の「ローカルでは動くのにGitHub Actionsでは403が出る」問題。 もし、設定を100回見直しても解決しないなら、それは設定の問題ではなく、X側が「GitHub Actionsという場所」に対して警戒レベルを上げているのが原因かもしれません。

「共有IP」という仕組み上、どうしても自分ではコントロールできない「もらい事故」のリスクが付きまといます。さらに、それがアカウントの信頼性にまで響く可能性があるとなると、ただのエラー以上に慎重に考えるべき問題な気がしてきました。

せっかく作った自動化ツール。これからも長く、そして安全に運用していくためには、GitHubの共有IPに頼るのを卒業して、自分のPCをそのままサーバーとして使う「セルフホストランナー」など、「信頼できるIPアドレスからの実行」を本気で検討する時期が来ているのかもしれません。

同じ悩みで頭を抱えている皆さんの、原因切り分けの参考になれば幸いです!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次