Перейти к содержимому
Skip to content
← All articles

CORS Explained: Cross-Origin Resource Sharing Guide

Cross-Origin Resource Sharing (CORS) is a security mechanism built into web browsers that controls how web pages from one origin (domain, protocol, port) can request resources from a different origin. Without CORS, browsers enforce the Same-Origin Policy (SOP), which blocks cross-origin HTTP requests made by JavaScript. CORS provides a safe, standardized way to relax this restriction when needed.

The Same-Origin Policy

The Same-Origin Policy is one of the fundamental security mechanisms of the web. Two URLs have the same origin if they share the same protocol, domain, and port:

URL AURL BSame Origin?Reason
SSL/TLS проверку://example.com/page1https://example.com/page2YesSame protocol, domain, port
https://example.comhttp://example.comNoDifferent protocol
https://example.comhttps://API документацию.example.comNoDifferent subdomain
https://example.comhttps://example.com:8080NoDifferent port
https://example.comhttps://other.comNoDifferent domain

Without the Same-Origin Policy, any website could read data from your banking app, email, or social media accounts using JavaScript — as long as you were logged in.

How CORS Works

CORS works through HTTP headers. When a browser makes a cross-origin request, it includes an Origin header. The server responds with Access-Control-* headers indicating whether the request is allowed:

# Browser sends:
GET /api/data HTTP/1.1
Host: api.example.com
Origin: https://app.example.com

# Server responds:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app.example.com
Content-Type: application/json

{"data": "response"}

If the server does not include the appropriate CORS headers, the browser blocks the response and logs a CORS error in the console.

Simple Requests vs Preflight Requests

The browser categorizes cross-origin requests into two types:

Simple Requests

A request is "simple" if it meets all of these conditions:

Simple requests are sent directly to the server. The browser checks the response headers after the fact.

Preflight Requests

Any request that does not qualify as "simple" triggers a preflight — an automatic OPTIONS request that the browser sends before the actual request:

# Step 1: Browser sends preflight
OPTIONS /api/data HTTP/1.1
Host: api.example.com
Origin: https://app.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization

# Step 2: Server responds to preflight
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400

# Step 3: Browser sends the actual request
PUT /api/data HTTP/1.1
Host: api.example.com
Origin: https://app.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGci...

{"key": "value"}

CORS Headers Reference

HeaderDirectionPurpose
OriginRequestTells the server where the request comes from
Access-Control-Allow-OriginResponseSpecifies which origins can access the resource
Access-Control-Allow-MethodsResponseAllowed HTTP methods for preflight
Access-Control-Allow-HeadersResponseAllowed request headers for preflight
Access-Control-Allow-CredentialsResponseWhether cookies/auth headers are allowed
Access-Control-Expose-HeadersResponseResponse headers the browser can access via JS
Access-Control-Max-AgeResponseHow long to cache preflight results (seconds)
Access-Control-Request-MethodRequestMethod the actual request will use (preflight)
Access-Control-Request-HeadersRequestHeaders the actual request will use (preflight)

Common CORS Configurations

Allow a Specific Origin

# Nginx
location /api/ {
    add_header Access-Control-Allow-Origin "https://app.example.com" 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 Access-Control-Max-Age 86400 always;

    if ($request_method = OPTIONS) {
        return 204;
    }

    proxy_pass http://backend;
}

Allow Multiple Origins (Dynamic)

# Nginx — check Origin against allowed list
map $http_origin $cors_origin {
    default "";
    "https://app.example.com" $http_origin;
    "https://admin.example.com" $http_origin;
    "https://staging.example.com" $http_origin;
}

server {
    location /api/ {
        add_header Access-Control-Allow-Origin $cors_origin always;
        add_header Vary Origin always;
    }
}

PHP CORS Handler

$allowedOrigins = [
    'https://app.example.com',
    'https://admin.example.com',
];

$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowedOrigins, true)) {
    header("Access-Control-Allow-Origin: $origin");
    header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
    header('Access-Control-Allow-Headers: Content-Type, Authorization');
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');
    header('Vary: Origin');
}

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

CORS with Credentials

When requests include cookies or authorization headers, additional rules apply:

// Client-side JavaScript
fetch('https://api.example.com/data', {
    method: 'GET',
    credentials: 'include',  // Send cookies cross-origin
    headers: {
        'Authorization': 'Bearer token123'
    }
});

Common CORS Errors and Solutions

ErrorCauseSolution
No 'Access-Control-Allow-Origin' headerServer does not send CORS headersAdd CORS headers to server response
Origin not allowedServer allows different origin(s)Add your origin to the allowed list
Preflight response is not successfulOPTIONS request returns errorHandle OPTIONS method on the server, return 204
Credentials flag is true but Allow-Origin is *Wildcard not allowed with credentialsSet specific origin instead of wildcard
Request header not allowedCustom header not in Allow-HeadersAdd the header to Access-Control-Allow-Headers

Security Best Practices

CORS and Monitoring

For web monitoring, CORS affects how monitoring tools interact with APIs:

Summary

CORS is a browser security mechanism that controls cross-origin HTTP requests. It uses HTTP headers to determine whether a web page from one origin can access resources from another. Simple requests are sent directly; complex requests trigger a preflight OPTIONS check. Proper CORS configuration requires specifying allowed origins, methods, and headers — and being especially careful with credentialed requests. Understanding CORS is essential for anyone building or consuming web APIs, as misconfiguration leads to either security vulnerabilities or broken functionality.

Check your website right now

Check now →
More articles: Security
Security
Two-Factor Authentication Guide: TOTP, SMS, and Hardware Keys
16.03.2026 · 10 views
Security
HSTS and Preload List: Complete Implementation Guide
16.03.2026 · 13 views
Security
Rate Limiting Strategies for Web APIs and Applications
16.03.2026 · 10 views
Security
Content Security Policy (CSP) — A Complete Configuration Guide
12.03.2026 · 12 views