Visit theCORS tutorial at web.dev for background on how to use CORS.
After configuring CORS on your server, it's important to verify that your configuration works correctly. This guide covers multiple testing approaches to ensure your CORS setup is working as expected.
The curl command-line tool is the quickest way to test CORS headers. Here are common test scenarios:
Test a basic GET request with an Origin header:
# Test with allowed origincurl -H "Origin: https://example.com" \ -I https://your-api.com/endpoint# Expected response headers:# Access-Control-Allow-Origin: https://example.com# Vary: Origin
For requests with custom headers or methods like PUT/DELETE, browsers send a preflight OPTIONS request:
# Test preflightcurl -H "Origin: https://example.com" \ -H "Access-Control-Request-Method: POST" \ -H "Access-Control-Request-Headers: Content-Type, Authorization" \ -X OPTIONS \ -I https://your-api.com/endpoint# Expected response headers:# Access-Control-Allow-Origin: https://example.com# Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS# Access-Control-Allow-Headers: Content-Type, Authorization# Access-Control-Max-Age: 86400
After preflight succeeds, test the actual request:
# POST request with custom headerscurl -H "Origin: https://example.com" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer token123" \ -X POST \ -d '{"test":"data"}' \ https://your-api.com/endpointVerify that unauthorized origins are rejected:
# Test with disallowed origincurl -H "Origin: https://evil.com" \ -I https://your-api.com/endpoint# Should NOT return Access-Control-Allow-Origin header
If your API supports credentials (cookies, auth):
# Test with credentialscurl -H "Origin: https://example.com" \ --cookie "session=abc123" \ -I https://your-api.com/endpoint# Expected response headers:# Access-Control-Allow-Origin: https://example.com# Access-Control-Allow-Credentials: true# Vary: Origin
Browser developer tools provide detailed CORS debugging information:
Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-HeadersAccess-Control-Allow-CredentialsVary: OriginThe browser console displays helpful CORS error messages. Common patterns:
Quickly test CORS from the browser console:
// Simple GET requestfetch('https://your-api.com/endpoint', { method: 'GET', headers: { 'Content-Type': 'application/json' }}).then(response => response.json()).then(data => console.log('Success:', data)).catch(error => console.error('CORS Error:', error));// POST with credentialsfetch('https://your-api.com/endpoint', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer token123' }, body: JSON.stringify({test: 'data'})}).then(response => response.json()).then(data => console.log('Success:', data)).catch(error => console.error('CORS Error:', error));Cause: Server is not sending CORS headers.
Solution: Configure your server to send theAccess-Control-Allow-Origin header. See the server-specific guides for your platform.
Cause: CORS headers are being set in multiple places (e.g., both application code and web server config).
Solution: Choose one configuration method and remove the duplicate. Check both your application code and web server configuration.
Cause: UsingAccess-Control-Allow-Origin: * withAccess-Control-Allow-Credentials: true.
Solution: Specify exact origin instead of wildcard when using credentials:
Access-Control-Allow-Origin: https://example.comAccess-Control-Allow-Credentials: true
Cause: The HTTP method you're using is not listed inAccess-Control-Allow-Methods.
Solution: Add the method to your CORS configuration:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Cause: Custom header is not listed inAccess-Control-Allow-Headers.
Solution: Add the header to your CORS configuration:
Access-Control-Allow-Headers: Content-Type, Authorization, X-Custom-Header
Cause: Server is redirecting the OPTIONS preflight request.
Solution: Ensure preflight OPTIONS requests return 204 No Content without redirects. Check for trailing slash redirects or authentication redirects on OPTIONS requests.
A properly configured CORS server should return these headers:
Access-Control-Allow-Origin: https://example.comVary: Origin
Access-Control-Allow-Origin: https://example.comAccess-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONSAccess-Control-Allow-Headers: Content-Type, AuthorizationAccess-Control-Max-Age: 86400Vary: Origin
Access-Control-Allow-Origin: https://example.comAccess-Control-Allow-Credentials: trueVary: Origin
If your API returns custom headers that the client needs to access:
Access-Control-Expose-Headers: X-Custom-Header, X-Total-Count
If CORS isn't working, check these common issues:
Vary: Origin when dynamically setting the origin* withAccess-Control-Allow-Credentials: trueThe content on this site stays fresh thanks to help from users like you! If you have suggestions or would like to contribute,fork us on GitHub.
Save 39% on CORS in Action with promotional codehossainco atmanning.com/hossain