How to Configure CORS Headers in a PHP API

This article provides a straightforward guide on how to configure Cross-Origin Resource Sharing (CORS) headers in a PHP API. You will learn how to enable cross-domain requests, handle preflight OPTIONS requests, and secure your API by restricting allowed origins, HTTP methods, and custom headers.

Understanding CORS in PHP

By default, web browsers block frontend applications (like React, Vue, or Angular) from making API requests to a domain different from the one they were served from. This security measure is known as the Same-Origin Policy. To allow your PHP API to accept requests from other domains, you must send specific CORS headers from your server.

In PHP, you configure these headers using the native header() function before any output is sent to the browser.

Step 1: Set the Allowed Origins

To allow web applications to access your API, you need to define the Access-Control-Allow-Origin header.

To allow access from any domain (not recommended for private or sensitive APIs):

header("Access-Control-Allow-Origin: *");

To restrict access to a specific domain (highly recommended for production):

header("Access-Control-Allow-Origin: https://www.yourfrontenddomain.com");

Step 2: Allow HTTP Methods and Headers

Next, specify which HTTP methods and headers are allowed when accessing your API resources.

// Define allowed HTTP methods
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");

// Define allowed request headers (useful if you use JWT tokens or JSON payloads)
header("Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With");

Step 3: Handle HTTP OPTIONS Preflight Requests

Browsers automatically send a “preflight” request using the OPTIONS method before sending complex requests (like POST or PUT with custom headers). Your PHP script must catch this request, send the appropriate CORS headers, and exit immediately with a 200 OK status without executing the rest of your API logic.

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    // Return standard 200 OK status for preflight
    http_response_code(200);
    exit();
}

Complete PHP CORS Implementation Example

Below is a complete, production-ready PHP snippet that handles CORS headers dynamically. Place this code at the very top of your main entry point file (e.g., index.php or api.php), before any output is rendered.

<?php
// Define allowed origins
$allowed_origins = [
    'https://www.yourfrontenddomain.com',
    'http://localhost:3000' // Local development
];

if (isset($_SERVER['HTTP_ORIGIN'])) {
    $origin = $_SERVER['HTTP_ORIGIN'];
    
    if (in_array($origin, $allowed_origins)) {
        header("Access-Control-Allow-Origin: " . $origin);
        header("Access-Control-Allow-Credentials: true");
    }
}

// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
        header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
    }
    
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
        header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
    }
    
    http_response_code(200);
    exit();
}

// Your actual API logic starts here
echo json_encode(["status" => "success", "message" => "CORS configured successfully."]);