Come risolvere gli errori CORS (e perché si verificano)
Un errore CORS significa che la tua pagina web ha provato a leggere una risposta da un'altra origine (un altro dominio, porta o protocollo), e quel server non ha inviato intestazioni che lo consentono. I browser bloccano la risposta per proteggere gli utenti. Lo risolvi sul server, restituendo un'intestazione Access-Control-Allow-Origin per l'origine del tuo sito e gestendo le richieste preflight OPTIONS, oppure lo eviti inviando la richiesta tramite il tuo back end sulla stessa origine.
È uno degli errori più confusi dello sviluppo web, perché la richiesta spesso arriva al server senza problemi. Questa guida spiega cosa succede e come risolvere ciascuna variante.
Cosa significa "origine"
Un'origine è la combinazione di protocollo, dominio e porta:
| URL | Origine |
|---|---|
https://miaapp.com/dashboard | https://miaapp.com |
https://api.miaapp.com/users | https://api.miaapp.com (sottodominio diverso, quindi origine diversa) |
http://localhost:5173 | http://localhost:5173 |
http://localhost:3000 | http://localhost:3000 (porta diversa, quindi origine diversa) |
I browser seguono la same-origin policy: il JavaScript di una pagina può leggere liberamente le risposte della propria origine, ma non quelle di altre. CORS (Cross-Origin Resource Sharing) è il sistema che permette a un server di acconsentire: "le risposte da me possono essere lette dalle pagine di queste origini".
Due conseguenze sorprendono molti:
- La richiesta spesso arriva al server. CORS di solito impedisce al tuo codice di leggere la risposta, non impedisce al server di ricevere la richiesta. Un POST può essere stato salvato anche se hai visto un errore.
- Solo i browser lo applicano. curl, Postman e il codice lato server ignorano completamente CORS. Per questo "funziona in Postman" non dice nulla su CORS.
Passo 1: leggi l'errore esatto
Apri gli strumenti per sviluppatori (clic destro → Ispeziona), vai alla Console e leggi il messaggio completo. La formulazione di Chrome ti dice quale problema hai:
| Il messaggio contiene | Cosa non va |
|---|---|
No 'Access-Control-Allow-Origin' header is present | Il server non ha inviato affatto l'intestazione, oppure la richiesta è fallita prima di raggiungere il tuo codice CORS (per esempio un 404 o un 500) |
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin | Il server consente un'origine diversa dalla tua |
Response to preflight request doesn't pass access control check | La richiesta preflight OPTIONS è fallita |
...must not be the wildcard '*' when the request's credentials mode is 'include' | Stai inviando cookie, e il server ha risposto con * |
Request header field authorization is not allowed | Il server non ha elencato quell'intestazione in Access-Control-Allow-Headers |
Poi apri la scheda Rete, trova la richiesta che fallisce (e le eventuali richieste OPTIONS prima di essa), e guarda il suo codice di stato e le intestazioni della risposta.
Controlla prima il codice di stato. Molti "errori CORS" sono in realtà un errore del server travestito. Se il server va in crash o restituisce un 404, la sua risposta d'errore spesso non ha intestazioni CORS, quindi il browser segnala CORS invece del vero problema. Correggi il 500 o il 404, e l'errore CORS può sparire.
Passo 2: decidi se dovresti chiamare quell'API dal browser
Prima di aggiungere intestazioni, chiediti: il browser dovrebbe chiamare direttamente questa API?
- Un'API di terze parti che richiede una chiave segreta (OpenAI, la chiave segreta di Stripe, la maggior parte dei servizi email) non dovrebbe mai essere chiamata dal browser. La chiave sarebbe visibile a ogni visitatore. Chiamala dal tuo back end, e il problema CORS scompare, perché le richieste server-to-server non sono soggette a CORS. Vedi come proteggere le chiavi API.
- Un'API di terze parti che non controlli e che non invia intestazioni CORS non può essere risolta dal tuo lato. Chiamala dal tuo back end.
- La tua API può essere risolta configurandola correttamente. Continua sotto.
Passo 3: correggi il server
Il server deve aggiungere le intestazioni giuste alle sue risposte, incluse quelle d'errore.
Per la richiesta vera, invia:
Access-Control-Allow-Origin: https://miaapp.com(l'origine esatta del tuo front end, senza slash finale)Vary: Origin, se il valore dipende da quale origine ha fatto la richiesta
Per la richiesta preflight OPTIONS, rispondi con uno stato di successo (200 o 204) e:
Access-Control-Allow-Origin: https://miaapp.comAccess-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETEAccess-Control-Allow-Headers: Content-Type, Authorization(ogni intestazione personalizzata che invii)- Facoltativo
Access-Control-Max-Age: 600, così il browser mette in cache il preflight per un po'
La maggior parte dei framework ha un pacchetto o un'impostazione che fa questo. In Express, il pacchetto cors; in FastAPI, CORSMiddleware; in ASP.NET Core, AddCors; in Spring, @CrossOrigin o una configurazione CORS. Un esempio tipico con Express:
import cors from "cors";
app.use(cors({
origin: ["https://miaapp.com", "http://localhost:5173"],
credentials: true,
}));
Metti la gestione CORS prima delle tue route e dell'autenticazione, così le richieste preflight (che non portano alcun login) non vengono respinte con un 401.
Con un builder AI, descrivi la configurazione con precisione:
Il front end su
https://miaapp.comchiama l'API suhttps://api.miaapp.come riceve "Response to preflight request doesn't pass access control check". Configura CORS sull'API per consentire esattamentehttps://miaapp.come l'origine dell'anteprima, consenti GET, POST, PATCH, DELETE con le intestazioni Content-Type e Authorization, gestisci OPTIONS prima dell'autenticazione, e includi le intestazioni CORS anche nelle risposte d'errore.
Passo 4: gestisci cookie e credenziali
Se il front end invia cookie (per esempio una sessione di login) a un'altra origine, entrambi i lati devono essere d'accordo:
- Il front end imposta
credentials: "include"sufetch, oppurewithCredentials: truein axios. - Il server invia
Access-Control-Allow-Credentials: true. - Il
Access-Control-Allow-Origindel server deve essere l'origine esatta, non*.
I cookie cross-site richiedono anche SameSite=None; Secure sul cookie, e alcuni browser limitano ulteriormente i cookie di terze parti. È un altro motivo per preferire l'approccio del passo 5.
Passo 5: evita CORS con una configurazione same-origin
Spesso la soluzione più pulita è non fare affatto richieste cross-origin. Servi l'API dalla stessa origine della pagina, per esempio su https://miaapp.com/api/...:
- In sviluppo, la maggior parte dei dev server può fare da proxy. L'opzione
server.proxydi Vite può inoltrare/apial tuo back end su un'altra porta, così il browser parla sempre con una sola origine. - In produzione, instrada
/apiverso il back end tramite le impostazioni di rewrite o proxy del tuo host, oppure servi front end e API dallo stesso server.
Il front end chiama poi un percorso relativo come fetch("/api/orders"). Non c'è alcuna richiesta cross-origin, nessun preflight tra origini e nessun problema di cookie. Significa anche che non scrivi nel codice un dominio API che cambia tra anteprima e produzione.
Cambia il front end perché chiami il back end con percorsi relativi /api invece di un URL completo, e imposta un proxy di sviluppo così che /api inoltri al server API. Poi rimuovi le impostazioni CORS che non servono più.
Cosa non fare
mode: "no-cors"infetch. Non aggira nulla; ti dà una risposta vuota e illeggibile.- Estensioni del browser che disattivano CORS. Cambiano solo il tuo browser. Ogni visitatore vede comunque l'errore.
- Servizi pubblici di "proxy CORS" per app reali. Possono leggere e modificare tutto ciò che passa attraverso di loro, e a volte vanno giù.
Access-Control-Allow-Origin: *su un'API che usa login. Non funziona comunque con le credenziali, ed è il default sbagliato per i dati privati.- Riflettere qualsiasi header
Originindietro con le credenziali consentite. Permette a qualsiasi sito di fare richieste autenticate per conto dei tuoi utenti. Usa una lista di origini consentite.
Cause comuni nelle app create con l'AI
| Situazione | Soluzione |
|---|---|
| Il front end chiama un'API di terze parti con una chiave segreta | Sposta la chiamata nel back end |
| Funziona nell'anteprima, non sul dominio pubblicato | Aggiungi alla lista consentita le origini del dominio pubblicato e di quello personalizzato, oppure usa percorsi relativi /api |
| Errore solo su POST, PUT o DELETE | Preflight non gestito; aggiungi la gestione di OPTIONS e le intestazioni consentite |
| L'errore è comparso dopo aver aggiunto il login | Le credenziali richiedono un'origine esatta e Allow-Credentials |
| "Errore CORS" ma la scheda Rete mostra 500 | Correggi prima l'errore del server |
URL dell'API fisso su localhost | Usa percorsi relativi o un'impostazione per ambiente |
CORS in Mythex
Quando un progetto Mythex ha un sito e un server API, entrambi girano come servizi nello stesso progetto, e puoi passare dall'uno all'altro nell'anteprima. Chiedere all'agente di far chiamare al front end il back end tramite un percorso relativo /api, con proxy in sviluppo, evita la maggior parte dei problemi CORS. Se hai davvero bisogno di chiamate tra origini, fornisci all'agente l'errore esatto della console e le origini coinvolte. Verifica il risultato anche sull'app pubblicata, perché il suo indirizzo è diverso dall'anteprima. Vedi Servizi multipli e Back end API nella documentazione, e le nostre guide su come fare debug di un'app creata con l'AI e front end contro back end.
Checklist CORS
- Letto il messaggio completo della console e il codice di stato della richiesta che fallisce
- Escluso un 404 o un 500 nascosto
- API con chiave segreta chiamate dal back end, non dal browser
- Il server invia
Access-Control-Allow-Origincon le origini esatte consentite - Preflight
OPTIONSgestito con metodi e intestazioni consentiti, prima dell'autenticazione - Intestazioni CORS presenti anche nelle risposte d'errore
- Credenziali: origine esatta,
Allow-Credentials: true, impostazioni dei cookie corrette - Origini dell'anteprima, del pubblicato e del dominio personalizzato tutte coperte, oppure percorsi relativi
/apiusati - Nessuna scorciatoia con
no-cors, proxy pubblici o riflessione di qualsiasi origine
Domande
Cosa significa un errore CORS?
La tua pagina, caricata da un'origine, ha provato a leggere una risposta da un'altra origine, e quel server non includeva le intestazioni che lo consentono. Il browser impedisce al tuo codice di leggere la risposta. La soluzione è sul server, o nel modo in cui la richiesta viene instradata, non nel codice front end.
Posso risolvere un errore CORS dal front end?
Non in modo corretto. Impostazioni come mode: 'no-cors' nascondono soltanto la risposta al tuo codice. Lo risolvi facendo inviare al server l'intestazione Access-Control-Allow-Origin corretta, oppure chiamando l'API dal tuo back end o da un proxy sulla stessa origine.
Access-Control-Allow-Origin: * è sicuro?
Va bene per dati pubblici che chiunque può leggere, come un'API pubblica senza login. Non può essere usata con cookie o altre credenziali, e per le API private dovresti elencare le origini esatte consentite.
Perché la richiesta funziona in Postman o curl ma non nel browser?
CORS è applicato solo dai browser. Strumenti come Postman e curl non lo applicano, quindi una richiesta può andare a buon fine lì e comunque essere bloccata quando il JavaScript della pagina la invia.
Cos'è una richiesta preflight?
Per le richieste non semplici, come un POST JSON o una richiesta con un'intestazione Authorization, il browser invia prima una richiesta OPTIONS per chiedere al server quali metodi e intestazioni sono consentiti. Se quella richiesta OPTIONS fallisce o non ha le intestazioni giuste, la richiesta vera non viene mai inviata.