CORS issue when calling an external API

Loading

What is CORS?

CORS (Cross-Origin Resource Sharing) is a security feature in web browsers that blocks requests made from one domain (origin) to another unless explicitly allowed by the server. It prevents malicious scripts from accessing data on a different origin.

How CORS Works

When a frontend (e.g., https://example.com) makes an API request to a different backend (e.g., https://api.external.com), the browser checks whether the backend allows requests from the frontend’s origin. If not, the request is blocked.


1. Why Does a CORS Issue Occur?

A CORS error occurs when:

  • The external API does not allow requests from your origin.
  • The API does not include the proper CORS headers.
  • A preflight request (OPTIONS) fails.
  • The browser blocks the request due to security policies.

Example CORS Error Message:

Access to fetch at 'https://api.external.com/data' from origin 'https://mywebsite.com' 
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

2. Understanding CORS Headers

The server must include specific HTTP headers to allow cross-origin requests.

HeaderPurpose
Access-Control-Allow-OriginSpecifies which origins are allowed (e.g., * or https://example.com).
Access-Control-Allow-MethodsLists allowed HTTP methods (GET, POST, PUT, DELETE).
Access-Control-Allow-HeadersSpecifies allowed headers (Content-Type, Authorization).
Access-Control-Allow-CredentialsAllows sending cookies and credentials.

Example of a valid CORS response from the API server:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization

3. How to Fix a CORS Issue

A) Fixing CORS from the Backend

If you control the API server, add CORS headers in the response.

For Express.js (Node.js)

const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors()); // Enables CORS for all routes

app.get('/data', (req, res) => {
res.json({ message: 'CORS enabled' });
});

app.listen(3000, () => console.log('Server running on port 3000'));

For Python (Flask)

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app) # Enables CORS for all routes

@app.route('/data')
def data():
return {'message': 'CORS enabled'}

if __name__ == '__main__':
app.run(port=5000)

B) Using a Proxy Server

If you cannot modify the API server, use a proxy to add CORS headers.

1. Using a CORS Proxy

A free service like CORS Anywhere can help:

fetch('https://cors-anywhere.herokuapp.com/https://api.external.com/data')

However, free proxies may be slow or unreliable.

2. Setting Up Your Own Proxy (Node.js)

const express = require('express');
const request = require('request');
const cors = require('cors');

const app = express();
app.use(cors());

app.get('/proxy/:url', (req, res) => {
const url = decodeURIComponent(req.params.url);
request(url).pipe(res);
});

app.listen(4000, () => console.log('Proxy server running on port 4000'));

Now, call your proxy instead:

fetch('http://localhost:4000/proxy/https://api.external.com/data')

C) Configuring CORS in Nginx

If your backend runs on Nginx, add the following in the config:

location /api/ {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
}

Restart Nginx:

sudo systemctl restart nginx

D) Handling Preflight Requests

For POST, PUT, or DELETE requests, the browser first sends an OPTIONS request (preflight).

If your API does not handle it, add a response:

app.options('*', (req, res) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.sendStatus(200);
});

4. Workarounds if You Can’t Fix CORS on the Backend

  1. Use JSONP (for GET requests only)
    function fetchJSONP(url, callback) { const script = document.createElement('script'); script.src = `${url}?callback=${callback}`; document.body.appendChild(script); } fetchJSONP('https://api.external.com/data', 'handleData'); (Note: JSONP is outdated and not recommended.)
  2. Disable CORS in the Browser (for testing) Run Chrome with CORS disabled:
    chrome.exe --disable-web-security --user-data-dir="C:/ChromeDev" (Not recommended for production use!)
  3. Use a Browser Extension

Leave a Reply

Your email address will not be published. Required fields are marked *