トラブルシュート

CORSエラーで外部データが読めないときの対処

外部APIをfetchで呼んだら「CORS policy によりブロックされた」と出てデータが取れない――よくある躓きですが、CORSはブラウザが利用者を守るための仕組みです。誰が許可を出すのかを理解すると、フロント側でできること・できないことの境界が見えてきます。仕組みと現実的な対処を整理します。

CORSは何を守っているのか

CORS(オリジン間リソース共有)は、あるオリジンのページが別のオリジンへリクエストして応答を読むことを、サーバー側の許可なしには認めない仕組みです。悪意あるサイトが、利用者がログイン中の別サービスのデータを勝手に読み取るのを防ぐためにブラウザが課しています。

重要なのは、許可を出すのはリクエストする側ではなく、リクエストされるサーバー側だという点です。サーバーが応答に Access-Control-Allow-Origin ヘッダを付けて「このオリジンからの読み取りを許可する」と示して初めて、ブラウザは応答内容をJavaScriptに渡します。許可がなければ、通信自体は届いていてもブラウザが内容を遮断します。

プリフライトとよくあるエラーの読み方

POSTでJSONを送る、独自ヘッダを付けるといった「単純でない」リクエストでは、本番リクエストの前にOPTIONSメソッドでプリフライトが飛びます。サーバーがこのプリフライトに適切なヘッダで応答しないと、本番リクエストは送られずエラーになります。エラーが出たらNetworkタブでOPTIONSの結果を確認するのが第一歩です。

コンソールのエラーメッセージは原因を示しています。Allow-Originヘッダが無い、値が一致しない、特定のヘッダやメソッドが許可されていない、など文面で切り分けられます。なお、ステータスがopaqueな失敗とCORS拒否は別物なので、応答ヘッダを実際に見て判断してください。

症状別チェック表

CORSエラーで外部データが読めないは、症状を分けずに直そうとすると原因探しが長引きます。まず「自分だけで起きるのか」「全員で起きるのか」「特定ブラウザだけか」「差し替え後だけか」を切り分けます。

確認順序を固定すると、相対パス、ファイル名、キャッシュ、認証、外部読み込みのどこで止まっているかが見えます。修正後はローカル確認だけで終わらせず、実際の共有URLで再表示して、相手と同じ条件で直ったことを確認します。

  • 自分だけ表示されない: キャッシュ、ログイン状態、ブラウザ拡張、端末幅を確認する
  • 全員で表示されない: ファイル構成、相対パス、大文字小文字、アップロード漏れを見る
  • 一部だけ崩れる: CSS/画像/JSごとに読み込みエラーを分ける
  • 差し替え後だけ古い: URL、キャッシュ、更新対象ファイルの取り違えを確認する

回避の考え方:許可を出せるのは誰か

フロントエンドのコードをいくら書き換えてもCORSは消せません。許可を出せるのはリクエスト先のサーバーだからです。対処は「自分が制御できる側に処理を寄せる」のが基本になります。

自分のAPIなら、応答に適切なAccess-Control-Allow-Originを付けて許可します。他人のAPIで制御できない場合は、自前のサーバーやプロキシを経由させてサーバー間で取得し、その結果を自分のオリジンから返す方法があります。サーバー間通信にはブラウザのCORS制約は適用されません。公開APIによってはJSONP的な手段やCORS対応のエンドポイントが用意されていることもあります。

  • 自分のAPIなら応答にAccess-Control-Allow-Originを付けて許可する
  • 制御できないAPIは自前のサーバー/プロキシ経由で取得する
  • サーバー間通信にはブラウザのCORS制約は適用されない
  • フロントのコード変更だけではCORSは解消できない

CORSエラーの切り分け手順

通信が届いているのかどうかを含め、上流から確認すると原因が見えます。次の手順で進めてください。

  1. コンソールのCORSエラー文面を読み、何が不足しているか把握する
  2. Networkタブでリクエストのステータスと応答ヘッダを確認する
  3. プリフライト(OPTIONS)が飛んでいる場合、その応答が正しいか見る
  4. 応答にAccess-Control-Allow-Originがあるか、値が自分のオリジンと一致するか確認する
  5. リクエスト先サーバーを自分で制御できるか判断する
  6. 制御できない場合はサーバー/プロキシ経由で取得する方針に切り替える

共有環境で実際のオリジンから確認する

CORSはオリジン(スキーム+ドメイン+ポート)で判定されます。ローカルのfile://やlocalhostで試したときと、実際に配信されるドメインから叩いたときで結果が変わることがあります。本番に近いオリジンで確認しておくのが確実です。

ギガサイト便にHTMLやZIPをドロップすると 〇〇.giga-site.com というサブドメインでHTTPS配信され、固定のオリジンから外部APIへのリクエスト挙動を試せます。同じURLのまま中身を差し替えられるので、リクエスト先や呼び出し方を直して再確認するのも素早く行えます。動作確認・レビュー用途の一時共有に向いています。

よくある質問

fetchでCORSエラーが出ます。フロント側のコードで直せますか。

基本的に直せません。許可を出すのはリクエスト先のサーバーで、応答にAccess-Control-Allow-Originヘッダが必要です。フロントのコードをいくら変えても、サーバーが許可していなければブラウザが応答を遮断します。

制御できない外部APIを使いたいのですが、CORSで読めません。

自前のサーバーやプロキシを経由させ、サーバー間で取得した結果を自分のオリジンから返す方法があります。サーバー間通信にはブラウザのCORS制約が適用されないためです。APIによってはCORS対応のエンドポイントが用意されていることもあります。

OPTIONSというリクエストが先に飛んでエラーになります。

これはプリフライトです。POSTでJSONを送る、独自ヘッダを付けるなど単純でないリクエストの前に送られます。サーバーがこのOPTIONSに許可ヘッダで応答していないと本番リクエストが止まります。Networkタブでその応答内容を確認してください。

ローカルでは読めたのに配信環境でCORSエラーになります。

CORSはオリジン単位で判定されるため、file://やlocalhostと実際のドメインでは結果が変わります。本番に近いオリジンで確認するのが確実です。ギガサイト便で配信URLを発行すれば、固定のオリジンからリクエスト挙動を試せます。

原因が分からないときはどこから確認すべきですか?

まず自分だけの問題か全員の問題かを分けます。次にシークレットウィンドウ、別ブラウザ、スマホで確認し、ファイル構成・相対パス・キャッシュ・認証設定を順に見ます。

関連記事

トラブルシュート

type="module"のJSが読み込めない・CORSで止まるときの対処

type=moduleにした瞬間にJSが読み込めなくなってCORSエラーに悩んでいる開発者向け。ESモジュール特有の読み込みルールが厳しい理由と、ローカルと公開環境の違いを踏まえたエラーの切り分け・解消手順をわかりやすく整理しています。

5分で読める
トラブルシュート

外部JSONの読み込みでパースエラーになるときの確認点

fetchはリクエスト成功なのにJSON.parseで落ちる、という謎のエラーに当たった方向け。Content-Typeの不一致・BOMの混入・HTMLが返ってくる状況など、パースが失敗しやすい原因をパターン別に挙げて確認手順を示します。

5分で読める
トラブルシュート

公開後にJavaScriptが動かないときの原因と直し方

ローカルでは動いていたボタンやアニメーションが公開後に反応しなくなった方向け。JavaScriptが止まる主な原因をファイルパスや読み込み順の観点で切り分け、自分で直せるかどうかを判断できます。

5分で読める
トラブルシュート

公開後に動画が再生されないときの対処

デモページや資料に埋め込んだ動画が公開後に再生されなくなった方向け。動画ファイルの添付漏れ・パスのズレ・ブラウザの自動再生制限を症状ごとに切り分け、自分でできる確認と対処を把握できます。

4分で読める
トラブルシュート

公開したHTMLのフォームが送信できないときの対処

問い合わせフォームやアンケートの送信ボタンが押せない・エラーになる方向け。静的ファイル公開ではフォームの動作に制約がある理由を理解し、外部サービス連携などの現実的な解決策を選べるようになります。

5分で読める
「トラブルシュート」の記事をもっと見る →