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

Akash S GAkash S G
2 min read

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.

0
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

Akash S G
Akash S G