CORSエラーってなに?なぜこの記事が必要なのか
JavaScriptで外部のAPIと連携しようとしたとき、次のようなエラーを見たことがありませんか?
Access to fetch at 'https://api.example.com/data' from origin 'http://localhost:3000' has been blocked by CORS policy
「APIにアクセスしようとしただけなのに、なんでブロックされるの?」
「CORSってよく聞くけど、どうすれば直せるの?」
そんな疑問やモヤモヤに応えるために、この記事では「CORSエラーの意味・原因・確認ポイント・解決方法」まで、実際のコード付きでわかりやすく解説します。
CORSの基本とJavaScriptでのエラー例
CORSをざっくり解説
CORS(Cross-Origin Resource Sharing)とは、「異なる場所にあるWebサービスとのやりとりを、制限付きで許可する仕組み」です。
-
「異なる場所」=オリジンが異なることを指します。
※オリジンとは、「プロトコル(http/https)・ドメイン名・ポート番号」のセットのこと。
たとえば、あなたのWebアプリが「http://localhost:3000」にあり、外部APIが「https://api.example.com」にある場合、これは異なるオリジンです。
Webブラウザは、セキュリティのために「違うオリジンからのデータ取得」を制限します。これがCORSエラーの元です。
具体的なCORSエラー例と原因
以下のようなメッセージが出た場合、それはCORSに関連しています。
No 'Access-Control-Allow-Origin' header is present on the requested resource.
主なCORSエラーの原因
-
サーバーが許可していない
APIサーバー側が「どのオリジン(アクセス元)を許可するか」をレスポンスヘッダーで明示していないと、ブラウザが通信をブロックします。 -
プリフライトリクエストが失敗している
特定の条件(例:カスタムヘッダー付きのPOST)では、事前確認のためのOPTIONSリクエスト(プリフライト)が送られます。このリクエストに対してサーバーが正しく応答しないと、実際の通信も拒否されます。 -
認証情報付きリクエストの制限
クッキーやトークンを含むリクエストを送信する場合、credentials: ‘include’ などの設定が必要です。さらにサーバー側でも Access-Control-Allow-Credentials: true の設定が必要です。 -
オリジンが一致していない
リクエストを送る元のURLと、APIのURLのドメイン・ポート・プロトコルが1つでも異なると、オリジンが異なると判断されます。これがCORSチェックの対象になります。
対処法とコード例
✅方法1:サーバー側で「許可」を明示する
最も確実なのはAPIのサーバー側で「このサイトからのアクセスを許可します」と設定することです。
Node.js(Express)の場合:
const express = require('express');
const app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000'); // 許可したいURL
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
app.get('/api/data', (req, res) => {
res.json({ message: 'データ取得成功' });
});
補足:
-
Access-Control-Allow-Origin … どのオリジンを許可するか(*も可。ただし制限あり)
-
Access-Control-Allow-Credentials … 認証情報(クッキーなど)付きの場合に必要
開発中は「プロキシ」で回避する
開発中に自分で管理できないAPIを使いたい場合は、「同一オリジンに見せかける」プロキシを使うのも手です。
例:React(Vite)での設定(vite.config.js)
server: {
proxy: {
'/api': {
target: 'https://api.example.com',
changeOrigin: true,
rewrite: path => path.replace(/^/api/, '')
}
}
}
仕組み:
あなたのReactアプリ(localhost:3000)
↓
ローカルで `/api/xxx` にリクエスト
↓
Viteが裏で https://api.example.com に転送(CORSを回避)
fetchで認証付き通信を行う場合
fetch('https://api.example.com/data', {
method: 'GET',
credentials: 'include' // 認証情報を含める設定
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error('エラー発生:', err));
注意点:
-
サーバー側でも Access-Control-Allow-Credentials: true が必要になります。
-
この場合、Access-Control-Allow-Origin を * にできません。オリジンを明示する必要があります。
まとめ
-
CORSは、異なるサイト間のデータ取得を制限する仕組み。
-
JavaScriptでAPI連携する場合、CORSの制約で通信がブロックされることがある。
-
サーバー側の設定 or 開発中はプロキシで対応するのが基本。
-
認証情報付きの通信には、追加設定が必要。
【外部リンク】
MDN Web Docs: CORS(クロスオリジンリソースシェアリング)
MDN Web Docs: Access-Control-Allow-Origin
【内部リンク】
JavaScriptのAjax完全入門|fetchの使い方・CORSエラーの対処・非同期通信の基本を解説
JavaScriptでよく発生するエラー「ReferenceError」「SyntaxError」などの原因と対策を具体例付きで解説