Connecting Angular with Backend APIs and Dealing with CORS the Right Way
TL;DR: If your Angular app and backend live in separate places and often use different technologies, this separation makes development cleaner and more scalable, but it also means your frontend and backend need to communicate smoothly. If you've ever connected an Angular app to a backend API (your own or a third-party like OpenWeather), you've probably seen CORS errors in your browser console. Interestingly, the same API call might work fine in Vue or React, the difference is usually a dev proxy. Vue/React setups often proxy API calls during development, making them *same-origin*. Configure an Angular dev proxy (or use your own backend), and the issue disappears. At first, it might look confusing, but CORS (Cross-Origin Resource Sharing) is just a browser security rule that protects users. When not configured properly, it blocks your frontend from reaching your backend. Here I explain what CORS really means, why it happens in Angular, and how to fix it on both the frontend and backend for a smoother and secure workflow.
The Issue
Calling OpenWeather like:
this.http.get('https://api.openweathermap.org/data/2.5/forecast', {
params: { q: 'Berlin', appid: environment.OWM_KEY }
});From Angular fails with CORS in the browser console, but a Vue or React app calling the same endpoint often works fine.
Why?
- •Dev Proxy in Vue/React: Vite or CRA uses a proxy, so
/apicalls are forwarded to the real API. From the browser's POV, it's *same-origin*, so CORS isn't enforced. - •Direct Cross-Origin in Angular: Calling
https://api.openweathermap.org/...directly fromhttp://<your-local-device>:4200makes the browser enforce CORS, and the remote API may not include your origin inAccess-Control-Allow-Origin. - •Extra Headers/Interceptors: Custom headers or
withCredentialstrigger a preflight (OPTIONS). If the API doesn't respond correctly, the request fails. - •HTTPS/HTTP mismatch or port differences can also trigger CORS.
The 3-Step Solution (Development Only)
Use an Angular dev proxy so your browser sees the request as same-origin during development.
Step 1: Create `proxy.conf.json` in your Angular project root
{
"/api/weather/*": {
"target": "https://api.openweathermap.org/data/2.5",
"secure": true,
"changeOrigin": true,
"pathRewrite": {
"^/api/weather": ""
},
"logLevel": "debug"
}
}Step 2: Register it in `angular.json`
{
"projects": {
"<your-project>": {
"architect": {
"serve": {
"options": {
"proxyConfig": "proxy.conf.json"
}
}
}
}
}
}Step 3: Update your call via the proxied path
this.http.get('/api/weather/weather/data/2.5/forecast', {
params: { q: 'Berlin', appid: environment.OWM_KEY }
});Now, the browser receives the response from http://<your-local-IP>:4200, no CORS error!
Why This Works
- •Browser CORS Check: Applies only to browser-to-server requests across different origins.
- •Server-to-Server: No CORS restrictions, Angular dev server forwards to OpenWeather API.
- •Same Origin: Browser sees the request as going to its own origin (
http://<your-local-device>:4200), bypassing CORS.
In short: During development, use Angular's proxy to simplify cross-origin API calls. For production, configure CORS properly on your backend or use a middleware like Nginx or API Gateway to handle headers securely.