CORSエラー解決法:No Access-Control-Allow-Origin ヘッダー欠落の修正
A client-side web application running on Origin A (e.g., https://app.example.com) makes an asynchronous HTTP fetch() or XMLHttpRequest to an API on Origin B (e.g., https://api.example.com). The browser halts the response and logs a fatal CORS security exception.
Access to fetch at "https://api.example.com/data" from origin "https://app.example.com" has been blocked by CORS policy: No "Access-Control-Allow-Origin" header is present on the requested resource.Why does CORSエラー解決法:No Access-Control-Allow-Origin ヘッダー欠落の修正 occur?
Primary Root Cause
ブラウザの同一オリジンポリシー(SOP)により、異なるオリジンからのデータ読み取りは制限されています。サーバーが明示的なCORSヘッダーを返さない限り、ブラウザはセキュリティ保護のためレスポンスを破棄します。
When Origin A calls Origin B, the browser automatically attaches an Origin: https://app.example.com request header. The server must evaluate this header and respond with Access-Control-Allow-Origin. If this header is missing, empty, or mismatches the origin, the browser immediately discards the response payload and raises a JavaScript TypeError.
How to Confirm You Are Facing This Exact Issue
Red console error: "No Access-Control-Allow-Origin header is present on the requested resource".
The JavaScript fetch() promise rejects with a generic TypeError: Failed to fetch.
The Network tab shows the HTTP status code (e.g. 200 OK or 500 Internal Server Error), but the Response Preview is completely blank.
The API call works perfectly in Postman, curl, or Insomnia, but fails exclusively inside Chrome, Firefox, or Safari.
Explicit Diagnostic Reasoning
Follow these diagnostic rules to isolate the root cause within 60 seconds:
"If the request succeeds in Postman or curl but fails in your browser"
Your backend is functioning properly, but lacks CORS headers (Postman ignores the Same-Origin Policy; browsers enforce it).
→ Add CORS middleware to your backend API server.
"If the error occurs on an unhandled backend error (e.g. status 500 or 404)"
Your global error-handling middleware is returning an error response BEFORE your CORS middleware has a chance to attach headers.
→ Ensure CORS middleware is registered at the very top of your backend middleware pipeline.
"If the request method is POST, PUT, or DELETE and shows status 405 or 404 on an OPTIONS call"
The browser sent a CORS Preflight check that your server failed to handle.
→ Enable HTTP OPTIONS preflight handling on your route handlers.
Sends a simulated cross-origin request. Check the response headers for Access-Control-Allow-Origin. If absent, the server configuration is broken.
Long-Term Engineering Solution
APIサーバーのレスポンスに Access-Control-Allow-Origin を設定し、OPTIONS プリフライトリクエストに対して204または200で応答するよう構成します。
Architectural Pattern
Inspect the incoming Origin request header, validate it against an allowlist of approved frontend domains, and dynamically reflect that specific origin in the Access-Control-Allow-Origin header, along with Vary: Origin.
How do you fix this step-by-step?
Identify Approved Frontend Origins
Define the exact scheme, domain, and port of your frontend applications (e.g., https://app.example.com and http://localhost:5173 for local dev).
Install or Configure Backend CORS Middleware
In Node.js/Express, install the official cors package and configure origin matching. In Nginx, add header directives.
import express from 'express';
import cors from 'cors';
const app = express();
const allowedOrigins = [
'https://app.example.com',
'http://localhost:5173',
];
// MUST be declared before any route handlers
app.use(cors({
origin: (origin, callback) => {
// Allow requests with no origin (like mobile apps or curl)
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Blocked by CORS policy'));
}
},
credentials: true, // Allow cookies / Authorization headers
}));Ensure Error Handlers Attach CORS Headers
When your API throws an unhandled exception (HTTP 500), your error handler must not strip headers. In Express, ensure cors() runs before error routers.
Verify with Browser DevTools
Open the Network tab, trigger the fetch call, click the request, and verify that Access-Control-Allow-Origin: https://app.example.com appears under Response Headers.
What are common misconceptions and mistakes when fixing this?
Trying to fix the error in frontend JavaScript by adding mode: "no-cors"
失敗の原因: no-cors turns the response into an "opaque" response with status 0, preventing JavaScript from reading any response data.
✓ 推奨される修正コード: Fix the issue on the backend server by configuring Access-Control-Allow-Origin.
Using wildcard Access-Control-Allow-Origin: * with credentials: "include"
失敗の原因: Browsers strictly forbid wildcard origins when credentials (cookies or Authorization headers) are present, throwing another CORS error.
✓ 推奨される修正コード: Dynamically return the specific requesting origin instead of "*".
Adding CORS headers to the client-side fetch request headers
失敗の原因: Access-Control-Allow-Origin is a RESPONSE header sent by servers, not a request header sent by clients.
✓ 推奨される修正コード: Configure response headers on your API server.
Can this fix introduce security vulnerabilities?
Misconfiguring CORS can allow malicious third-party websites to make authenticated requests to your API and exfiltrate sensitive user data.
Security Risks If Ignored
- •Reflecting arbitrary origins without validation allows malicious domains to read private user records.
- •Combining wildcard origins with internal intranet endpoints exposes internal infrastructure.
Hardening Best Practices
- ✓Always validate the Origin header against a strict server-side allowlist.
- ✓Always include the Vary: Origin response header to prevent CDN caches from serving Origin A headers to Origin B.
Fixing Missing CORS Headers in Nginx Reverse Proxy
# BROKEN: Nginx forwards request but omits CORS headers
location /api/ {
proxy_pass http://backend_upstream;
}# FIXED: Nginx dynamically checks Origin and sets response headers
location /api/ {
if ($http_origin ~* "^https?://(app\.example\.com|localhost:5173)$") {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
add_header 'Vary' 'Origin' always;
}
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://backend_upstream;
}Frequently Asked Questions About CORSエラー解決法:No Access-Control-Allow-Origin ヘッダー欠落の修正
Why does the request work in Postman but fail in the browser?↓
Postman is a development tool that does not enforce the browser Same-Origin Policy.
The Same-Origin Policy exists strictly to protect human users navigating the web in browsers. Postman, curl, and backend servers do not run untrusted third-party code in tabs, so they ignore CORS completely.
Did my server actually process the request if a CORS error was thrown?↓
Yes! For simple GET and POST requests, your server executed the code and returned the data.
The browser received the 200 OK response, saw that Access-Control-Allow-Origin was missing, and intercepted the data before your JavaScript could inspect it.