Tutorials Logic
Tutorials Logic, IN info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Website Development
Practice
Quiz Challenge Interview Questions Certification Practice
Tools
Online Compiler JSON Formatter Regex Tester CSS Unit Converter Color Picker
Compiler Tools

CORS in AJAX — Cross-Origin Requests Explained

What is CORS?

CORS (Cross-Origin Resource Sharing) is a browser security mechanism that controls how web pages can request resources from a different origin (domain, protocol, or port) than the one that served the page.

The Same-Origin Policy (SOP) is the underlying rule: by default, a script on https://app.example.com cannot make AJAX requests to https://api.other.com. CORS is the standard way to relax this restriction in a controlled manner.

An "origin" is defined as the combination of: protocol + hostname + port. Any difference makes it cross-origin.

CORS Headers

HeaderDirectionPurpose
Access-Control-Allow-OriginResponseWhich origins are allowed (* or specific origin)
Access-Control-Allow-MethodsResponseAllowed HTTP methods (GET, POST, PUT, DELETE)
Access-Control-Allow-HeadersResponseAllowed request headers
Access-Control-Allow-CredentialsResponseWhether cookies/auth headers are allowed
Access-Control-Max-AgeResponseHow long to cache preflight results (seconds)
OriginRequestThe origin of the requesting page
Enabling CORS in PHP
// api.php - Enable CORS headers

// Allow a specific origin (recommended over *)
$allowedOrigins = ['https://app.example.com', 'https://www.example.com'];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';

if (in_array($origin, $allowedOrigins)) {
    header("Access-Control-Allow-Origin: $origin");
} else {
    // Or allow all origins (less secure, fine for public APIs)
    // header('Access-Control-Allow-Origin: *');
}

header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
header('Access-Control-Allow-Credentials: true'); // required for cookies/auth
header('Access-Control-Max-Age: 86400');           // cache preflight for 24 hours

// Handle preflight OPTIONS request
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204); // No Content
    exit;
}

// Continue with normal request handling...
header('Content-Type: application/json');
echo json_encode(['message' => 'CORS-enabled response']);

Simple vs Preflight Requests

Simple requests do not trigger a preflight. They must use GET, HEAD, or POST with only safe headers (Content-Type: application/x-www-form-urlencoded, multipart/form-data, or text/plain).

Preflight requests are automatically sent by the browser as an HTTP OPTIONS request before the actual request. They occur when the request uses a non-simple method (PUT, DELETE, PATCH), a non-simple Content-Type (like application/json), or custom headers (like Authorization).

Enabling CORS in Node.js / Express
// npm install cors
const express = require('express');
const cors = require('cors');
const app = express();

// Option 1: Allow all origins (public API)
app.use(cors());

// Option 2: Allow specific origins with full config
app.use(cors({
  origin: ['https://app.example.com', 'https://www.example.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,   // allow cookies and auth headers
  maxAge: 86400        // cache preflight for 24 hours
}));

// Option 3: Dynamic origin validation
app.use(cors({
  origin: function (origin, callback) {
    const whitelist = ['https://app.example.com'];
    if (!origin || whitelist.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  }
}));

app.get('/api/data', (req, res) => {
  res.json({ message: 'CORS-enabled response' });
});

app.listen(3000);
Proxy Approach and JSONP (Legacy)
// ---- PROXY APPROACH (recommended modern solution) ----
// Your own server proxies the request to the third-party API
// Client -> Your Server -> Third-Party API -> Your Server -> Client
// No CORS issue because the server-to-server call is not browser-restricted

// Client code (calls your own server)
fetch('/proxy/weather?city=London')
  .then(res => res.json())
  .then(data => console.log(data));

// Your server (proxy.php or Express route) forwards to the real API:
// $response = file_get_contents("https://api.weather.com/v1/city=London&key=SECRET");
// echo $response;

// ---- JSONP (legacy - only GET, avoid in new code) ----
// JSONP works by injecting a <script> tag - not a real AJAX request
// The server wraps the response in a callback function call

function handleWeatherData(data) {
  console.log('Temperature:', data.temp);
}

// Dynamically create a script tag
const script = document.createElement('script');
script.src = 'https://api.example.com/weather?city=London&callback=handleWeatherData';
document.head.appendChild(script);
// Server responds with: handleWeatherData({"temp": 22, "city": "London"})
// The browser executes it as JavaScript, calling our function

// NOTE: JSONP is a security risk and only supports GET.
// Use CORS or a proxy instead.

Level Up Your Ajax Skills

Master Ajax with these hand-picked resources

10,000+ learners
Free forever
Updated 2026

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.