Why Your Axios Call Fails with a CORS Error (Even When the URL Works in the Browser)


The Bug
I was trying to fetch daily horoscopes from a public API:
https://horoscope-app-api.vercel.app/api/v1/get-horoscope/daily?sign=Virgo&day=TODAY
Pasting the URL into the browser worked perfectly. I could see a JSON response like this:
{
"data": {
"date": "Jul 28, 2025",
"horoscope_data": "It's time for you to come out of hibernation, Virgo..."
},
"status": 200,
"success": true
}
But then I tried using axios
from my frontend:
axios.get('https://horoscope-app-api.vercel.app/api/v1/get-horoscope/daily', {
params: {
sign: 'Virgo',
day: 'TODAY',
},
});
And I got hit with this:
Access to XMLHttpRequest has been blocked by CORS policy
Classic.
Debugging: Why CORS Happens
When your browser (say from http://localhost:3000
) tries to request data from another domain (https://horoscope-app-api.vercel.app
), the browser blocks the request unless the server explicitly allows it via CORS headers.
The API didn’t include:
Access-Control-Allow-Origin: *
...so the browser refused to send the request, even though you can visit the URL manually.
The Fix(that I used): Use a Node.js Proxy Server
The best solution? Bypass CORS entirely by calling the API from your own server, not from the browser.
Here's how I did it:
Setting Up the Express Proxy
import express from 'express';
import axios from 'axios';
import cors from 'cors';
const app = express();
app.use(cors()); // allow all origins
const PORT = 3001;
app.get('/api/horoscope', async (req, res) => {
const { sign = 'Virgo', day = 'TODAY' } = req.query;
if (!sign || !day) {
return res.status(400).json({ error: 'Missing parameters: sign and day' });
}
try {
const response = await axios.get(
'https://horoscope-app-api.vercel.app/api/v1/get-horoscope/daily',
{
params: { sign, day },
}
);
res.json(response.data);
} catch (error) {
console.error('Failed to fetch from API:', error.response?.data || error.message);
res.status(500).json({
error: 'Failed to fetch from upstream',
details: error.response?.data || error.message,
});
}
});
app.listen(PORT, () => {
console.log(`Proxy server: http://localhost:${PORT}`);
});
Frontend Code (Still Simple)
Now, instead of calling the real API directly, just call your local proxy:
axios.get('http://localhost:3001/api/horoscope', {
params: {
sign: 'Virgo',
day: 'TODAY',
},
}).then(res => {
console.log(res.data);
});
What I learnt?
Browsers enforce strict CORS policies, even if the API is public and accessible in the browser.
A URL working in the browser doesn’t guarantee it will work in JavaScript, especially when CORS is involved.
Debugging is smoother when you understand how data is passed (query params vs body vs headers).
Setting up a simple Node.js + Express proxy can quickly solve CORS issues and give you full control over requests.
Subscribe to my newsletter
Read articles from Akash S G directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
