こんにちは。joni_momongaです。
「GASでDiscord Botを作ろうとして403 Forbiddenで絶望したことはありませんか?」
私はあります。なぜなら、この記事を書く前に実際にやろうとして困ったからです。GAS(Google Apps Script)は手軽で最強のツールですが、Discord APIからはGoogleのIPアドレス帯というだけでアクセスをブロックされる仕様になっています。
そこで実際に調べて試した結果、ピッタリの解決法が見つかったので、記事にして同じ現象で困っている方の助けになればと思い、執筆をする運びになりました。
これまでは「Glitch」などの外部無料サービスを中継させる方法が主流でしたが、2025年7月にサービス終了しています。無料の選択肢だけで構築しようとすると、結局いつか動かなくなるんです。インフラとして依存するにはどうしても不安が残ります。
そこで今回は、「ブログ運営に使っているConoHa WINGサーバーを中継地点(プロキシ)にして、安定かつ追加コストなしでGAS×Discord連携を実現する方法」を紹介します。
WordPress環境下ならではのハマりポイント(404エラー)や、セキュリティ対策もバッチリ解説しますよ!
仕組み:ConoHa WINGを「身代わり」にする
GASから直接Discordにアクセスすると弾かれます。なので、GASからのリクエストを一度ConoHa WING上のPHPファイルで受け取り、そのPHPファイルからDiscordへアクセスしてもらう形をとります。
GAS(直接だとブロックされる) → ConoHa WING(正規アクセスとして許可) → Discord API(リクエストが通る!)
これなら、ConoHa WINGのきれいなIPアドレス経由になるため、Discord側も快くデータを通してくれるわけです。
ConpHa WING そのものについて知りたい方は、以下のリンクから確認できます。
実装手順:PHPプロキシを作る
まずはConoHa WINGのファイルマネージャーを開きましょう。ログインして、サイト管理→ファイルマネージャーで開けます。
1. フォルダ作成
public_html/ドメイン名/ の下に api というフォルダを作成します。(名前は何でも良いですが、WordPressのフォルダと混ざらないように注意)
2. proxy.phpの作成

作成したフォルダの中に proxy.php を作成し、以下のコードを記述します。今回はセキュリティを考慮して、データが見えにくいPOST通信(リクエストボディ)で受け取る安全な設計にします。
your-domain.comの部分は、自分のサーバーで使っているものを入れてください(本ブログの場合、joni-momonga.comになります)。
<?php
// POSTリクエスト以外は拒否
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('Method Not Allowed');
}
// 簡易認証(セキュリティ対策)
$access_key = 'ここに自分だけの合言葉を設定';
// $_GET ではなく $_POST で受け取る
if (!isset($_POST['key']) || $_POST['key'] !== $access_key) {
http_response_code(403);
exit('Access Denied');
}
// パラメータ取得
$channel_id = $_POST['channelId'] ?? '';
$bot_token = 'ここにDiscordのBotトークンを記述';
$after_id = $_POST['after'] ?? '';
if (!$channel_id) {
http_response_code(400);
exit('No Channel ID');
}
// Discord API URL構築
$url = "https://discord.com/api/v10/channels/{$channel_id}/messages?limit=100";
if ($after_id && $after_id !== 'undefined') {
$url .= "&after={$after_id}";
}
// cURLでリクエスト
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bot {$bot_token}",
"Content-Type: application/json",
"User-Agent: DiscordBot (https://your-domain.com, 1.0)"
]);
$response = curl_exec($ch);
curl_close($ch);
// 結果をJSONで返す
header('Content-Type: application/json');
echo $response;
?>3. GAS側のコード
GAS側では、このPHPファイルを叩くだけです。
function fetchDiscordLog() {
const proxyUrl = "https://あなたのドメイン/api/proxy.php";
// POSTデータとして送る情報
const payload = {
'key': 'PHP側で設定した合言葉',
'channelId': '取得したいチャンネルID',
'after': '' // 必要なら前回のメッセージID
};
const options = {
'method': 'post', // POST送信を指定
'payload': payload,
'muteHttpExceptions': true
};
// URLにはパラメータを付けずにアクセス
const response = UrlFetchApp.fetch(proxyUrl, options);
const responseCode = response.getResponseCode();
if (responseCode !== 200) {
console.error(`Error: ${responseCode} - ${response.getContentText()}`);
return;
}
const data = JSON.parse(response.getContentText());
console.log(data); // ログが出れば成功!
}技術ポイント:なぜGETではなくPOSTを使うのか?
手軽な GET リクエスト(URLパラメータ)を使うと、Webサーバーのアクセスログに /proxy.php?key=secret123 などの履歴がバッチリ残ってしまいます。これでは、サーバーのログを見られる管理者や、万が一ログが流出した際に合言葉が第三者にバレてしまうリスクがあります。
今回紹介した POST メソッドを使えば、キーは「リクエストボディ(封筒の中身)」に入って送られるため、サーバーのアクセスログにはURL(/proxy.php)しか残りません。こうしたログに機密情報を残さないというひと工夫が、セキュリティレベルを大きく向上させます。せっかくの記録ですから、可能な範囲での対策はしておきたいものです。
【重要】ハマりポイントと解決策(トラブルシューティング)
ここからが本番です。私が実際に直面し、解決に時間を費やしたトラブルを共有します。これを知っているだけで数時間は節約できるはずです。
障害①:WordPressの干渉(404 Not Found)
現象:GASからアクセスすると、なぜかブログの「404ページ(ページが見つかりません)」のHTMLが返ってくる。PHPファイルはそこにあるのになぜ?
原因:ConoHa WINGでWordPressを使っている場合、ドメイン直下の .htaccess が全てのアクセスをWordPressで処理するという設定になっています。そのため、phpを配置した箇所へのアクセスもWordPressが横取りし、「そんな記事はないよ」とエラーを返していたのです。
解決策:api フォルダにphpファイルを配置する。もし、それでも発生する場合、フォルダの中に、新しい .htaccess ファイルを作成し、以下の一行だけ記述します。
RewriteEngine Offこれで、「このフォルダ内ではWordPressのルールを無効化する(Rewrite機能をオフにする)」という指示になり、無事にPHPファイルへ直接アクセスできるようになります。
障害②:DMが取得できない(50001 Missing Access)
現象:サーバーのチャンネルログは取れるのに、特定のDM(ダイレクトメッセージ)だけ 50001 Missing Access エラーになる。
解決策:原因は単純な鍵と部屋の不一致でした。プロキシPHP内で指定したBotトークンが、以前作った別のBotのものでした。今回の検証用にBotを作成しましたが、私の使用目的としては、以前からある方を指定すべきでした。完全に新規で作る場合は、新しいBotで問題ありません。
また、DMのチャンネルIDはサーバーのチャンネルIDとは取得方法が少し異なります。 Discordの「開発者モード」をONにし、DMのチャット欄を右クリックして「チャンネルIDをコピー」で正しいIDを取得し、トークンとセットで設定し直しましょう。
障害③:セキュリティの懸念(Open Relay)
課題:プロキシのURLがバレると、第三者に勝手にAPIを叩かれ、Botの制限回数を消費されたり、情報を抜かれたりするリスクがあります。
解決策:コード内にも書きましたが、簡易認証を実装しました。GASとPHPで共通の「合言葉(Access Key)」を決め、URLパラメータ(?key=xxx)で照合します。これが一致しない場合は即座に403エラーを返すようにしています。前述のPOSTでの対応も合わせて、最低限のセキュリティは確保できます。
障害④:URLパラメータの記述ミス
現象:proxy.php?key=xxx?channelId=yyy と書いてしまいエラーに。
解決策:初歩的ですが、2つ目以降のパラメータは & で繋ぐのが決まりです。正しくは proxy.php?key=xxx&channelId=yyy です。GASでURLを組み立てる際は注意しましょう。
実行結果&まとめ

ここまでに作成したphpとGASを元に作ったDiscordBotを使った自分用のスクリプトを動かすと、無事に弾かれることなく動きました!黒い部分はチャンネルIDなので、念のため伏せています。
このように、GAS単体では越えられない壁も、手持ちのブログサーバーを一枚挟むだけで驚くほど安定して動作します。
ブログを持っているエンジニアなら、この方法が最強の選択肢である
今回の対応を通して、私はそう確信しました。Glitchなどの無料サービスの終了や仕様変更などに怯えることもなく、自分の管理下で安定したBot運用が可能です。
もし、まだ自分のサーバーを持っていない、あるいは無料サーバーの限界を感じている方がいれば、私が使っている ConoHa WING は本当におすすめです。
WordPressのセットアップが爆速なのはもちろんですが、今回のようにちょっとした自作APIを置く場所としても非常に優秀で安定しています。
最近は、ブログ記事以外の用途でも使っており、自分で作ったWebアプリやサービスの公開場所としても活用しています。
さまじゃないLab:joni_momongaのデジタル実験場
これから技術ブログを始めたい、自分専用のAPIサーバーが欲しいという方は、ぜひ検討してみてください。
この記事が、403エラーと戦う同士の助けになれば幸いです!
疑問:なぜここまでしてログを保存するのか?
さて、ここまで403エラーと戦い、PHPプロキシを自作してまでDiscordのログを保存する方法を解説してきました。そこまでする必要があるの?と思った方もいるかもしれません。
しかし、私にはどうしてもこのシステムが必要でした。それは、日々の思考やアイデアを、全自動で『資産』に変えるためです。
最近フリーランスとして活動し始めたこともあり、思いついたブログのネタ、TRPGシナリオのギミック、開発したいアプリの構想などをDiscordの自分専用サーバーで書き込み、それを自動で自動的にスプレッドシートに蓄積し、整理可能なストック型のデータとして残す。
そこから特定の情報を引き出せるようにすることで、自分でも気が付いていない記事にできるアイデアのタネや、いつでもアイデアを引き出せる最強の保管庫を用意したかったのです。
そのための下準備としてのGAS作成で壁にぶつかりつつも解決した結果、今回の過程そのものが有用な記事になるのでは?と思い、取り纏めた次第です。
次回以降の続きとして、以下のような実践部分についても、紹介してみようと思います。
- ・スプレッドシートに溜まったログをどうやって記事にするのか?
- ・蓄積したデータの具体的な活用術は?
- ・実践してみた結果、何が変わった?
エンジニアだけでなく、ブロガーやシナリオライターの方にも役立つ創作の裏側をお見せできると思います。お楽しみに!






