To configure CORS in Laravel 13, publish the config file with php artisan config:publish cors, then set paths, allowed_origins, allowed_methods and allowed_headers in config/cors.php. Laravel's built-in CORS middleware reads that file and answers preflight OPTIONS requests for you.
What is CORS and when do you need it?
Browsers block JavaScript on one origin (scheme, host and port) from reading responses from another origin unless the server allows it with CORS headers. You need to configure it when a separate frontend, for example a React app on http://localhost:5173, calls your Laravel API on http://localhost:8000.
What do you need before you start?
- Laravel 13 on PHP 8.3 or newer
- A frontend on a different origin that calls your API
How do you publish the CORS config?
The file is not published by default. Laravel uses sensible built-in defaults until you publish it.
php artisan config:publish corsHow do you set allowed origins?
<?php
// config/cors.php
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
'allowed_origins' => [
env('FRONTEND_URL', 'http://localhost:5173'),
],
'allowed_origins_patterns' => [],
'allowed_headers' => ['Content-Type', 'Authorization', 'Accept', 'X-Requested-With'],
'exposed_headers' => [],
'max_age' => 600,
'supports_credentials' => false,
];Only paths matching paths get CORS headers. List every origin you trust. Avoid * on authenticated APIs.
# .env
FRONTEND_URL=https://app.example.comHow do you allow cookies or credentials?
For cookie-based SPA authentication, such as Sanctum SPA mode, the response must include Access-Control-Allow-Credentials: true. Set supports_credentials to true. With credentials, the browser rejects a wildcard origin, so use explicit origins.
'supports_credentials' => true,On the frontend, enable credentials in your HTTP client, for example axios.defaults.withCredentials = true.
How does the middleware work?
Laravel registers its CORS handling in the global middleware stack, so you do not add it to routes. After editing the config, clear the cached config if you ever ran config:cache.
php artisan config:clearHow do you verify it works?
Send a preflight request with curl and look at the response headers.
curl -i -X OPTIONS http://localhost:8000/api/user \
-H "Origin: http://localhost:5173" \
-H "Access-Control-Request-Method: GET" \
-H "Access-Control-Request-Headers: Authorization"You should see Access-Control-Allow-Origin: http://localhost:5173 and the allowed methods. Then repeat with a disallowed origin and confirm the header is absent.
What are the common mistakes?
- The route is not covered by
paths - Using
*together withsupports_credentials - A trailing slash in the origin, such as
http://localhost:5173/ - Cached config hiding your changes
- Debugging a 500 error as if it were CORS. When an error response lacks CORS headers the browser reports a CORS failure, so check the Laravel log first
FAQ
Do I need a CORS package in Laravel 13?
No. Handling is built into the framework and configured with config/cors.php.
Why does the browser say CORS but curl works?
CORS is enforced by browsers only. curl ignores it, so test with the Origin header as shown above.
Can I use a pattern for many subdomains?
Yes. Use allowed_origins_patterns with a regular expression such as #^https://.*\.example\.com$#.



