CORS stands for Cross-Origin Resource Sharing. It is a browser security mechanism that controls whether a web application can make requests to a server from a different origin.
CORS allows a server to specify which origins are permitted to access its resources from a browser.
Browser Application
↓
Cross-Origin Request
↓
REST API
↓
CORS Rules
↓
Allow or Reject
The server sends special HTTP response headers that tell the browser whether the request is allowed.
An origin is made up of three main parts:
https://example.com:443
Protocol → https
Domain → example.com
Port → 443
If any of these parts changes, the browser may consider the request to be cross-origin.
Suppose your website and API are hosted on the same origin:
Website:
https://example.com
API:
https://example.com/api/students.php
These URLs use the same protocol, domain, and port, so the request is same-origin.
A request becomes cross-origin when the origin is different.
Website:
https://myapp.com
API:
https://api.example.com/students.php
The browser treats these as different origins because the hostnames are different.
Browsers implement same-origin protections to prevent a website from freely reading sensitive information from another origin.
CORS provides a controlled way for a server to say:
"This origin is allowed to access my API."
Therefore, CORS is part of browser security rather than an authentication system.
The most important CORS response header is:
Access-Control-Allow-Origin
For example:
Access-Control-Allow-Origin: https://example.com
This tells the browser that requests from the specified origin may be allowed to access the response.
A server can use the wildcard:
Access-Control-Allow-Origin: *
This means the response is available to requests from any origin, subject to other browser and request restrictions.
For private APIs, avoid using a wildcard automatically. Configure the policy according to your application's requirements.
A simple PHP API can send a CORS response header:
<?php
header(
"Access-Control-Allow-Origin: https://example.com"
);
header(
"Content-Type: application/json"
);
echo json_encode([
"success" => true
]);
?>
The browser uses the CORS header when deciding whether JavaScript can read the response.
You generally do not send multiple origins in a single
Access-Control-Allow-Origin header.
Instead, the server can inspect the request's Origin header
and return the matching origin when it belongs to an allowlist.
$allowedOrigins = [
"https://example.com",
"https://admin.example.com"
];
This provides more control than blindly allowing every origin.
PHP can read the request's Origin header:
$origin =
$_SERVER['HTTP_ORIGIN']
?? '';
The API can then compare this value against a predefined allowlist.
$allowedOrigins = [
"https://example.com",
"https://admin.example.com"
];
$origin =
$_SERVER['HTTP_ORIGIN']
?? '';
if (in_array(
$origin,
$allowedOrigins,
true
)) {
header(
"Access-Control-Allow-Origin: "
. $origin
);
}
An allowlist is useful when only specific browser applications should access the API.
CORS can also specify which HTTP methods are allowed.
header(
"Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS"
);
This tells the browser which methods the server is prepared to accept for cross-origin requests.
The server can specify which request headers may be used.
header(
"Access-Control-Allow-Headers: Content-Type, Authorization"
);
This is especially useful for APIs that receive JSON and use Bearer tokens.
A React or browser application may send JSON data using:
Content-Type: application/json
The API can explicitly allow the Content-Type request header:
Access-Control-Allow-Headers:
Content-Type, Authorization
JWT-protected APIs commonly receive:
Authorization: Bearer YOUR_TOKEN
A browser-based application may require the server to allow this request header through CORS.
header(
"Access-Control-Allow-Headers: "
. "Content-Type, Authorization"
);
For some cross-origin requests, the browser first sends an
OPTIONS request to ask the server whether the actual
request is permitted.
Browser
↓
OPTIONS Request
↓
API
↓
CORS Permission
↓
Actual Request
This is called a CORS preflight request.
A PHP API can handle the OPTIONS request before processing the actual API operation.
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
The required CORS headers should be sent before this check.
<?php
$origin =
$_SERVER['HTTP_ORIGIN']
?? '';
$allowedOrigins = [
"http://localhost:3000",
"https://example.com"
];
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(
"Content-Type: application/json"
);
if (
$_SERVER['REQUEST_METHOD']
=== 'OPTIONS'
) {
http_response_code(204);
exit;
}
?>
A PHP REST API commonly returns JSON:
header(
"Content-Type: application/json"
);
echo json_encode([
"success" => true,
"message" => "API working"
]);
CORS headers and JSON response headers can be sent together.
A browser-based React application may call a different API origin:
React App
http://localhost:3000
↓
PHP API
http://localhost/api/
The PHP server must provide an appropriate CORS policy if the browser is expected to allow the frontend to read the API response.
React Native is not running JavaScript inside a normal browser page in the same way as a web application.
Therefore, browser CORS restrictions generally do not apply to React Native networking in the same way they apply to browser-based JavaScript.
React Native
↓
HTTP Request
↓
PHP REST API
↓
JSON Response
Even so, it is useful to configure CORS correctly if the same API will also be consumed by web applications.
fetch(
"https://api.example.com/students.php"
)
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.log(error);
});
If the API's CORS policy does not allow the browser's origin, the browser may block the JavaScript application from reading the cross-origin response.
A browser may show a message similar to:
Access to fetch at
'https://api.example.com/...'
from origin
'https://myapp.com'
has been blocked by CORS policy.
This usually means the API's CORS response does not satisfy the browser's requirements for that request.
CORS should not be used as a replacement for authentication.
CORS
↓
Controls Browser Access
Authentication
↓
Identifies User
Authorization
↓
Checks Permissions
A protected API should still verify JWTs or another authentication mechanism.
CORS does not protect your database from SQL injection.
Your API should still use:
CORS is only one part of the overall API security configuration.
Postman can be useful for testing API endpoints and headers. However, Postman is not a browser and therefore does not enforce browser CORS restrictions in the same way.
You can inspect the API response headers:
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
For actual browser behavior, test the API from a browser-based application as well.
In production, define the origins that actually need access.
$allowedOrigins = [
"https://app.example.com",
"https://admin.example.com"
];
Avoid copying development settings such as localhost origins into production without reviewing them.
Browser / Web App
↓
Cross-Origin Request
↓
PHP REST API
↓
Check Origin
↓
CORS Response Headers
↓
Authentication
↓
Validation
↓
Database
↓
JSON Response
↓
Browser
A correctly configured CORS policy allows the browser to communicate with the API while other API security controls continue to protect the application.
CORS controls cross-origin browser access to REST APIs. PHP can send
CORS response headers such as
Access-Control-Allow-Origin,
Access-Control-Allow-Methods, and
Access-Control-Allow-Headers.
For React Native applications, browser CORS restrictions generally do not work the same way, but the same API may also need CORS support for web clients.
CORS
↓
Browser Cross-Origin Control
↓
Allowed Origin
↓
Allowed Methods
↓
Allowed Headers
↓
REST API
Access-Control-Allow-Origin controls allowed origins.Access-Control-Allow-Methods specifies allowed methods.Access-Control-Allow-Headers specifies allowed request headers.Question: Which HTTP response header is primarily used to specify which origin can access a resource through a browser?