Examples of CORS in Flask API: 3 Practical Examples That Actually Match Real Apps
Let’s skip the theory and start where the pain usually begins: the browser.
You have a Flask API on http://localhost:5000 and a frontend on http://localhost:3000. You hit an endpoint from JavaScript and get something like:
Access to fetch at 'http://localhost:5000/api/data' from origin 'http://localhost:3000' has been blocked by CORS policy...
That’s the browser enforcing same-origin policy. CORS is the standard way to say, "yes, this other origin is allowed to call me".
To make this practical, we’ll walk through three anchor setups, then extend them with more real examples:
- A public JSON API that any frontend can call
- A single-page app with authentication and cookies
- A production-style locked-down configuration with per-route rules
Along the way, we’ll spin off extra examples: local dev vs. production, third‑party widgets, mobile apps, and internal tools.
Example 1: Simple public Flask API with open CORS
This first scenario is the "just make it work" development setup. Think of a public read‑only API: maybe a COVID‑19 statistics service, a weather feed, or a blog posts endpoint that doesn’t require login.
A lot of public health and research APIs, like those documented at healthdata.gov, are consumed from browsers and need CORS enabled. Your Flask API can behave the same way.
Code: Allow any origin for a read-only API
Install the CORS extension:
pip install flask-cors
Then wire it up in app.py:
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
## Example 1: Fully open CORS for all routes (development / public data)
CORS(app) # default: origins='*'
@app.route("/api/public-data")
def public_data():
return jsonify({
"source": "demo",
"items": [1, 2, 3],
})
if __name__ == "__main__":
app.run(debug=True)
With this configuration, your frontend at http://localhost:3000 or https://example-frontend.com can call:
fetch('http://localhost:5000/api/public-data')
.then(res => res.json())
.then(console.log)
.catch(console.error);
and the browser will accept the response because Flask adds headers like:
Access-Control-Allow-Origin: *
This is one of the simplest examples of CORS in Flask API code you’ll see, and it’s fine for:
- Internal prototypes
- Public, read‑only data where you don’t care who reads it
- Quick experiments with frontends in different ports
Why you should not keep this in production
The wildcard * origin is easy, but it’s a bad idea for sensitive data. It tells every website on the internet that they can call your API from a browser.
If you’re dealing with anything user-related (health, payments, private profiles), you should be thinking in the same direction as organizations like the National Institutes of Health do with their public vs. restricted datasets: public endpoints are open, private ones are tightly controlled.
We’ll tighten things up in the next example.
Example 2: SPA frontend + Flask API with cookies and auth
Most modern apps are not anonymous public APIs. They’re SPAs (React, Vue, Angular) talking to Flask with:
- Login sessions stored in cookies
Authorization: Bearer ...headers- CSRF protection
This is where you need more careful examples of CORS in Flask API: 3 practical examples isn’t enough — you also want variations that handle credentials, preflight requests, and specific methods.
Scenario: React at https://app.example.com → Flask at https://api.example.com
You want:
- Only
https://app.example.comto be allowed - Cookies or auth headers to be sent
- Only certain methods (
GET,POST, maybePUT) allowed
Code: Restrict CORS to a single frontend and allow credentials
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
## Example 2: Restrictive CORS with credentials for one frontend origin
CORS(
app,
resources={r"/api/*": {"origins": ["https://app.example.com"]}},
supports_credentials=True,
methods=["GET", "POST", "PUT"],
allow_headers=["Content-Type", "Authorization"],
)
@app.route("/api/profile")
def profile():
# # assume user is authenticated via session or token
return jsonify({
"username": "jane.doe",
"plan": "pro",
})
if __name__ == "__main__":
app.run()
On the frontend, a fetch call with credentials might look like:
fetch('https://api.example.com/api/profile', {
method: 'GET',
credentials: 'include', // cookies / auth
})
.then(res => res.json())
.then(console.log)
.catch(console.error);
Key points in this example of CORS in Flask API:
resources={r"/api/*": {"origins": [...]}}only applies CORS to/api/routessupports_credentials=TrueaddsAccess-Control-Allow-Credentials: true- Wildcard
*cannot be used with credentials, so you must list the origin(s)
Extra variants you’ll probably need
Once you have this working, real life usually demands a few more patterns. These are some of the best examples of tweaks you’ll see in production code:
Local development vs. production origins
import os
FRONTEND_ORIGINS = [
"http://localhost:3000", # local dev
"https://staging.app.example.com",
"https://app.example.com", # production
]
CORS(
app,
resources={r"/api/*": {"origins": FRONTEND_ORIGINS}},
supports_credentials=True,
)
Different rules for public vs. private endpoints
## Public data: read-only, many origins
CORS(app, resources={r"/public/*": {"origins": "*"}})
## Private data: only trusted frontend
CORS(
app,
resources={r"/private/*": {"origins": ["https://app.example.com"]}},
supports_credentials=True,
)
These variations show how real examples of CORS in Flask API often mix and match rules instead of using a single global setting.
Example 3: Production-grade CORS with per-route control
At some point, your security or compliance team will ask who can call what. If you’re handling anything sensitive (think patient data, financial records, or anything that would concern organizations like Mayo Clinic), you want CORS to be as tight and explicit as possible.
This third setup is about fine-grained control:
- Different origins for different endpoints
- Only specific headers and methods
- Explicit handling of preflight OPTIONS requests
Code: Use @cross_origin decorators for per-route rules
from flask import Flask, jsonify, request
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app, resources={}) # start with no global CORS
## Example 3a: Analytics endpoint consumed by multiple dashboards
@app.route("/api/analytics")
@cross_origin(
origins=[
"https://analytics.example.com",
"https://admin.example.com",
],
methods=["GET"],
max_age=3600, # cache preflight for 1 hour
)
def analytics():
return jsonify({"visits": 1234})
## Example 3b: Admin-only endpoint for internal tool
@app.route("/api/admin/reports", methods=["POST", "OPTIONS"])
@cross_origin(
origins=["https://internal.example.com"],
methods=["POST"],
allow_headers=["Content-Type", "X-Admin-Token"],
)
def admin_reports():
if request.method == "OPTIONS":
# # Preflight request handled by @cross_origin
return "", 204
# # Handle real POST here
return jsonify({"status": "queued"})
if __name__ == "__main__":
app.run()
This pattern highlights another set of examples of CORS in Flask API that align with real organizational boundaries:
- Public dashboards vs. internal tools
- Third‑party partners vs. first‑party frontends
- Different security levels on different endpoints
More real-world examples built on this pattern
To hit the 2024–2025 reality, here are more scenarios you’re likely to see:
Example: Mobile app + Flask API
Native mobile apps (iOS, Android) don’t use browser CORS in the same way, but if you embed web views or use hybrid frameworks, you may still see CORS. A common pattern is:
MOBILE_WEB_ORIGINS = [
"https://m.example.com", # mobile web
"https://app-shell.example.com" # PWA shell
]
CORS(
app,
resources={r"/api/mobile/*": {"origins": MOBILE_WEB_ORIGINS}},
supports_credentials=True,
)
Example: Third‑party widget embedding your data
You might expose a read‑only widget other sites can embed, similar to how health education widgets from universities or .gov sites are embedded across the web.
TRUSTED_EMBED_ORIGINS = [
"https://partner1.com",
"https://partner2.org",
]
CORS(
app,
resources={r"/widget/*": {"origins": TRUSTED_EMBED_ORIGINS}},
)
Example: Internal tools on a VPN
For internal dashboards (https://dash.corp.example.com) talking to https://api.corp.example.com:
CORS(
app,
resources={r"/corp/*": {"origins": ["https://dash.corp.example.com"]}},
supports_credentials=True,
)
All of these are real examples of CORS in Flask API setups that you can adapt with just a few lines of configuration.
2024–2025 trends: Why CORS in Flask still matters
CORS has been around for years, but it’s not going away. If anything, it’s getting more visible because of a few trends:
- More SPAs and micro frontends: Every team has its own frontend, often on its own origin.
- Security and privacy pressure: Browsers keep tightening defaults around cookies and tracking. Correct CORS headers are part of proving you’re doing things right.
- APIs everywhere: Even traditional organizations (hospitals, universities, government agencies) expose APIs that frontends consume directly.
That’s why having several concrete examples of CORS in Flask API projects — from wide‑open dev setups to strict production rules — is far more helpful than a single generic snippet.
For deeper background on browser behavior, MDN’s documentation on CORS is still one of the better references.
Common mistakes when copying CORS examples
Even the best examples can mislead if you copy them blindly. Watch out for these patterns:
Using * with credentials
Browsers will ignore Access-Control-Allow-Credentials: true if Access-Control-Allow-Origin is *. If you need cookies or auth headers, list explicit origins.
Forgetting OPTIONS in your route methods
If you manually handle methods and skip OPTIONS, preflight requests may fail. Either let Flask handle it automatically or add "OPTIONS" to your methods.
Assuming CORS is security
CORS is not an access control system. It just tells browsers what’s allowed. Your API still needs authentication, authorization, and rate limiting.
Mixing dev and prod settings
That CORS(app) with everything open is fine for local experiments, but don’t ship it to production. Split configs by environment.
When you look for examples of CORS in Flask API usage, always ask: what environment is this for — dev, staging, or production? Then adjust accordingly.
FAQ: Short answers with concrete examples
What are some real examples of CORS in a Flask API setup?
Real examples include:
- A React dashboard at
https://app.example.comtalking tohttps://api.example.comwith cookies andsupports_credentials=True. - A public stats endpoint with
CORS(app)returning read‑only JSON for any origin. - An internal admin tool at
https://admin.example.comhitting/api/admin/*endpoints restricted to that single origin.
Each of these mirrors the examples of CORS in Flask API configurations shown in the code above.
Can you show an example of limiting CORS to only GET requests?
Yes. Using @cross_origin:
@app.route('/api/read-only')
@cross_origin(origins=['https://app.example.com'], methods=['GET'])
def read_only():
...
The browser will only see CORS headers for GET, and other methods will either fail CORS or be blocked by Flask routing.
How do I debug CORS issues in a Flask API?
A practical approach:
- Open the browser dev tools → Network tab → click the failing request.
- Check the Request Headers for
Originand any custom headers. - Check the Response Headers for
Access-Control-Allow-Origin,Access-Control-Allow-Credentials, andAccess-Control-Allow-Headers. - Adjust your
CORS()or@cross_originconfiguration to match what the browser is asking for.
If you want a deeper understanding of the HTTP side, MDN’s CORS docs and general HTTP header references are worth bookmarking.
Should I use global CORS or per-route decorators in Flask?
For small apps or prototypes, global CORS is fine. For production systems with mixed sensitivity levels, per-route decorators with @cross_origin give you better control and clearer intent. Most of the best examples of CORS in Flask API practice use a hybrid: strict defaults, then explicit relaxations per route.
By now you’ve seen not just three, but multiple layered examples of CORS in Flask API: 3 practical examples expanded into real-world scenarios. Use the simple open setup for experiments, the credentialed SPA pattern for modern frontends, and the per-route configuration when you need to answer hard questions about who can call what — and prove it in code.
Related Topics
Examples of CORS in Flask API: 3 Practical Examples That Actually Match Real Apps
Real-world examples of handling CORS errors in front-end applications
Practical examples of CORS with Node.js and Koa framework
The best examples of CORS: practical examples with developer tools
Explore More Implementing CORS in APIs
Discover more examples and insights in this category.
View All Implementing CORS in APIs