If you’ve ever yelled at your screen while battling the CORS error, congratulations, you’re officially a web developer.
Welcome to the club. Every dev hits this brick wall sooner or later: your front-end code works perfectly on localhost, but the moment you connect it to your Flask API, the browser throws a fit like an overly dramatic bouncer. “Cross-Origin Request Blocked!” it cries, leaving you scratching your head, Googling furiously, and questioning your career choices.
But don’t worry, by the end of this guide, you’ll not only understand why this error happens but also know how to fix it using Flask-CORS, saving your sanity and maybe even your weekend.
The Error
Essentially, when your front-end JavaScript code tries to fetch data from a server on a different origin (different domain, protocol, or port), the browser screams, “Stranger, danger!” It blocks the request unless the server explicitly says, “It’s cool; I know this client.”
Access to fetch at "https://mybackend.com" from origin "https://myfrontend.com" has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response servers your needs, set the request's mode to 'no-cors' to fetch the resources with CORS disabled
This policy exists to prevent malicious scripts from stealing sensitive data, but when you’re just trying to get your APIs and UI to play nice, it feels more like the browser’s auditioning for the role of unnecessary antagonist in your dev story.
Here is a simple Python application with Flask. There is only one endpoint which returns a JSON content. It seems pretty easy, no complication, but this code sample don’t even work when requesting from a browser.
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/hi")
def hello_world():
return jsonify({"message": "hi"})
The Problem
The OPTIONS request is like a cautious traveler asking, “Hey, what are the rules here before I step in?” When a browser detects that a client is making a cross-origin request (say, from http://localhost:3000 to http://myfrontend.com), it sometimes sends an OPTIONS preflight request to the server. This request asks the server, “Am I allowed to make this kind of request? If so, what methods, headers, and origins do you support?”
The server responds with a polite RSVP, detailing what’s permitted. For example, it might say:
- “Yes, I allow requests from
http://localhost:3000.” - “I support the following methods:
GET,POST, andDELETE.” - “You’re welcome to send these headers:
Authorization,Content-Type.”
If the server fails to reply appropriately, the browser won’t even bother sending your actual GET or POST request, leaving you frustrated and staring at a CORS error. Think of it as the browser doing a background check before letting your request through—it’s tedious but necessary for security.
For security reasons, the backend applications block by default the cross-origin requests.
The Solution
When using Flask, I have another dependency to add to solve this situation.
poetry add flask-cors
My sample code must change a little bit to indicate to Flask that now I accept cross-origin requests from different origins.
from flask import Flask, jsonify
app = Flask(__name__)
CORS(
app,
origins=[
"https://myfrontend.com",
"https://dev.myfrontend.com",
"https://test.myfrontend.com",
],
)
@app.route("/hi")
def hello_world():
return jsonify({"message": "hi"})
In the previous sample code, I list all the accepted origins to request my backend.
Conclusion
Before you go wild and slap '*' into your CORS configuration, let’s have a little chat about security. The CORS policy isn’t just a nuisance, it’s there to protect your users’ data. By restricting who can access your API, you prevent malicious websites from hijacking sensitive information through unauthorized requests. Using a wildcard ('*') in your CORS settings may seem like an easy fix, but it’s like leaving your front door wide open and hoping for the best. It’s fine for local development, but in production, it’s a no-go.
Instead, always specify the exact origins of your front-end applications, like http://myfrontend.com or https://admin.myfrontend.com. This ensures that only the URLs you trust can interact with your API. Sure, it takes a little extra effort, but isn’t safeguarding your users’ trust worth it? With Flask-CORS and some careful configuration, you can maintain a balance between functionality and security, proving to your browser (and yourself) that you’ve got this whole “developer” thing under control.



Leave a comment