MENU

CORSエラーの直し方:ブラウザでAPI通信が止まる理由と確認手順

CORSエラーの直し方:ブラウザでAPI通信が止まる理由と確認手順

CORSエラーの直し方:ブラウザでAPI通信が止まる理由と確認手順

ブラウザ上のJavaScriptから別ドメインのAPIを呼び出したときに通信が止まるなら、多くの場合はAPIサーバー側のCORS設定を確認します。fetch() の書き方だけを変えても、サーバーが許可ヘッダーを返さなければブラウザはレスポンスをJavaScriptへ渡しません。

CORSは「別のオリジンから来たブラウザのリクエストを、サーバーが読むことを許可する仕組み」です。WordPressのテーマや管理画面カスタマイズ、静的サイト、フロントエンドアプリから外部APIを読む場面でよく出ます。

この記事では、2026年7月時点のMDN Web DocsとFetch Standardを前提に、ブラウザで起きるCORSエラーの見方、最小の設定例、やってはいけない対応を整理します。

  • CORSエラーは、APIが落ちているエラーとは限らない
  • 許可するのは、リクエストを送る側ではなくAPIを返すサーバー側
  • Access-Control-Allow-OriginOPTIONS、認証情報の扱いを分けて見る
  • APIキーやCookieを使う場合は、安易に * を使わない
目次

CORSエラーは「ブラウザが止めている」エラー

CORSエラーの核心は、通信先サーバーのレスポンスをブラウザがJavaScriptへ渡してよいか判定している点です。

たとえば、次のような構成を考えます。

  • 表示中のページ: https://example.com
  • 呼び出したいAPI: https://api.example.net/items
  • 実行するコード: ブラウザ上の fetch()
fetch("https://api.example.net/items")
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error(error));

このとき、example.comapi.example.net はオリジンが異なります。オリジンは、ざっくり言えば次の3つの組み合わせです。

  • スキーム: httpshttp
  • ホスト: example.com などのドメイン
  • ポート: 4433000 など

MDNは、CORSをHTTPヘッダーにもとづく仕組みとして説明しています。サーバーは「このオリジンからのブラウザ読み取りを許可する」とレスポンスヘッダーで示します。

ここがポイント: CORSは「APIにリクエストできるか」だけでなく、「ブラウザ上のJavaScriptがレスポンスを読めるか」を制御します。

まず見るべきエラーメッセージ

最初に見る場所は、ブラウザの開発者ツールです。JavaScriptの catch だけでは詳しい理由が分かりにくいため、ConsoleとNetworkを両方確認します。

よく見るメッセージは次のようなものです。

Access to fetch at 'https://api.example.net/items'
from origin 'https://example.com' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.

この場合、見るべき点は明確です。

  • 呼び出し元のオリジンは https://example.com
  • 呼び出し先は https://api.example.net/items
  • APIレスポンスに Access-Control-Allow-Origin がない
  • そのためブラウザがレスポンスの読み取りを止めている

Networkタブでは、対象リクエストを開いて次を確認します。

  • Request Headers に Origin が付いているか
  • Response Headers に Access-Control-Allow-Origin があるか
  • ステータスコードが 200204401403500 のどれか
  • OPTIONS リクエストが先に送られていないか

CORSエラーに見えても、実際には認証エラーやサーバーエラーが先に起きていることがあります。ただし、サーバーエラー時にもCORSヘッダーが返っていないと、ブラウザの画面上ではCORSエラーに見えます。

基本対応はAPIサーバーで許可ヘッダーを返すこと

最小の対応は、APIサーバーのレスポンスに Access-Control-Allow-Origin を付けることです。

公開してよい読み取り専用APIなら、次のように全オリジンを許可する場合があります。

Access-Control-Allow-Origin: *

ただし、実務では許可するオリジンを絞ることが多いです。

Access-Control-Allow-Origin: https://example.com

NG例: フロント側だけで直そうとする

次のように、ブラウザ側の fetch() にレスポンスヘッダーを書いてもCORS設定にはなりません。

fetch("https://api.example.net/items", {
  headers: {
    "Access-Control-Allow-Origin": "*"
  }
});

Access-Control-Allow-Origin は、APIサーバーがレスポンスで返すヘッダーです。ブラウザからリクエストヘッダーとして送るものではありません。

改善例: サーバー側で返す

PHPで簡易APIを作っているなら、レスポンスを返す前にヘッダーを出します。

<?php
header('Access-Control-Allow-Origin: https://example.com');
header('Content-Type: application/json; charset=utf-8');

echo json_encode([
    'status' => 'ok',
    'items' => ['apple', 'orange']
]);

入力例として、https://example.com のブラウザからこのAPIを呼び出します。

const response = await fetch("https://api.example.net/items.php");
const data = await response.json();
console.log(data);

期待される出力は次の形です。

{
  "status": "ok",
  "items": ["apple", "orange"]
}

WordPressサイトから外部APIを読む場合も考え方は同じです。テーマやブロック側のJavaScriptで外部APIを直接呼ぶなら、外部API側がそのWordPressサイトのオリジンを許可している必要があります。

外部APIのCORS設定を変更できない場合は、WordPressのサーバー側でAPIを呼び、ブラウザには自サイトのREST APIやAjaxエンドポイントとして返す方法を検討します。これは「ブラウザから外部APIへ直接読む」形ではなく、「自サイトのサーバーが外部APIと通信する」形に変える対応です。

OPTIONSが出るときはプリフライトを疑う

POSTPUT、独自ヘッダー、特定の Content-Type を使うと、ブラウザは本番のリクエスト前に OPTIONS リクエストを送ることがあります。これをプリフライトリクエストと呼びます。

たとえば次のコードは、Authorization ヘッダーを付けてJSONを送っています。

await fetch("https://api.example.net/orders", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer dummy-token"
  },
  body: JSON.stringify({ itemId: 123, quantity: 2 })
});

この場合、ブラウザは先に次のような確認を送ります。

OPTIONS /orders HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type

APIサーバーは、少なくとも次のように返す必要があります。

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type

ここで OPTIONS に対応していないと、本番の POST は送られません。Networkタブで POST が見えず OPTIONS だけ失敗しているなら、API本体の処理より先にプリフライト対応を確認します。

プリフライトでよくある失敗

  • サーバーやWAFが OPTIONS を拒否している
  • Access-Control-Allow-Methods に実際のメソッドがない
  • Access-Control-Allow-HeadersAuthorizationContent-Type がない
  • リダイレクト先でCORSヘッダーが消えている
  • エラー時のレスポンスだけCORSヘッダーが付いていない

特にWordPressやCMSの裏にCDN、リバースプロキシ、セキュリティプラグインがある構成では、アプリケーションコードまで届く前に OPTIONS が止まることがあります。

ログイン状態やCookieを使うAPIでは、CORS設定をより厳密にします。Access-Control-Allow-Origin: * と認証情報付きリクエストは組み合わせられません。

ブラウザ側でCookieを含める例です。

const response = await fetch("https://api.example.net/me", {
  credentials: "include"
});

この場合、サーバー側は次のように具体的なオリジンを返します。

Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

注意点は3つあります。

  • Access-Control-Allow-Origin: * にしない
  • 許可するオリジンを固定、または安全な許可リストで判定する
  • CookieやAPIキーをブラウザに置く必要があるか見直す

APIキーを使う場合、ブラウザのJavaScriptに秘密キーを直接書くのは避けます。公開ページのソースや開発者ツールから見えるためです。必要ならサーバー側でAPIを呼び出し、ブラウザには必要な結果だけを返します。

CORSとHTTPエラーを切り分ける確認手順

CORS対応では、原因を一つずつ外すのが早道です。闇雲にヘッダーを増やすより、どの段階で止まっているかを見ます。

  1. ConsoleのCORSエラー文を読む
  2. Networkで対象URLとステータスコードを見る
  3. OPTIONS があるか確認する
  4. Response Headersに Access-Control-Allow-Origin があるか見る
  5. 認証ありなら Access-Control-Allow-Credentials とCookie設定を見る
  6. APIサーバー、CDN、プロキシ、WAFのどこでヘッダーが付くか確認する

ローカル開発では、次のような組み合わせでも別オリジンになります。

  • http://localhost:3000 から http://localhost:8000
  • http://127.0.0.1:3000 から http://localhost:3000
  • http://example.com から https://example.com

同じPC上の開発環境でも、ポートやホスト名が違えばCORSの対象になります。

代表的な対応パターンの使い分け

CORSは「とりあえず全部許可」で済ませると、後で認証情報や管理系APIを扱うときに危険です。用途ごとに対応を分けます。

場面向いている対応注意点
公開データを読むだけAccess-Control-Allow-Origin: *Cookieや認証情報を使わない前提にする
自社サイトからだけ読む許可オリジンを具体的に指定本番、ステージング、開発環境のURLを分けて管理する
ログイン状態でAPIを読む具体的なオリジン + Access-Control-Allow-Credentials: true* は使わず、Cookie設定も確認する
外部APIのCORSを変更できない自分のサーバーを経由するAPIキーをサーバー側で管理し、返すデータを絞る
管理画面や社内ツール許可リスト、認証、CSRF対策を合わせて設計CORSだけをセキュリティ対策として扱わない

見落とされがちなのは、CORSは「アクセス制御のすべて」ではない点です。CORSヘッダーを絞っても、サーバーAPI自体が認証なしで重要データを返すなら危険です。逆に、CORSで止まっていても、サーバー間通信やcurlからは呼べることがあります。

すぐ使える最小チェックリスト

最後に、実務でCORSエラーを見たときの確認項目をまとめます。

  • 呼び出し元と呼び出し先のオリジンを正確に書き出す
  • APIサーバーのレスポンスに Access-Control-Allow-Origin があるか確認する
  • OPTIONS が失敗しているなら、プリフライト対応を先に直す
  • AuthorizationContent-Type: application/json、独自ヘッダーを使っているか見る
  • Cookieを使うなら credentials: "include"Access-Control-Allow-Credentials をセットで確認する
  • * でよいのは、認証情報を含まない公開APIなどに限る
  • 外部APIの設定を変えられないなら、サーバー側プロキシやバックエンド経由を検討する

CORSエラーの次の分岐点は、「APIサーバーを自分で設定できるか」です。設定できるなら、許可するオリジン、メソッド、ヘッダーを必要最小限で返します。設定できないなら、ブラウザから直接読む設計をやめ、自分のサーバー側でAPI通信を受け持たせるのが現実的な対応になります。

参照リンク

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