Examples of CORS in Flask API: 3 Practical Examples That Actually Match Real Apps

If you’ve ever opened your browser console and been greeted with a wall of red CORS errors, you’re not alone. Developers hit this all the time when a React or Vue frontend talks to a Flask backend on a different origin. That’s exactly why you’re probably looking for clear, working **examples of CORS in Flask API: 3 practical examples**, not another vague explanation of headers. In this guide, we’ll walk through three realistic setups: a simple public API, a frontend talking to Flask with cookies and auth, and a locked-down production configuration. Along the way, we’ll add more than three scenarios in code so you can see how CORS behaves in real projects: local development, staging, production, and even mobile and third‑party integrations. By the end, you’ll not only have three practical examples of CORS in Flask API code, you’ll also know how to adapt them to your own stack without fighting the browser every five minutes.
Written by
Jamie
Published
Updated

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.com to be allowed
  • Cookies or auth headers to be sent
  • Only certain methods (GET, POST, maybe PUT) 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/ routes
  • supports_credentials=True adds Access-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.


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.com talking to https://api.example.com with cookies and supports_credentials=True.
  • A public stats endpoint with CORS(app) returning read‑only JSON for any origin.
  • An internal admin tool at https://admin.example.com hitting /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 Origin and any custom headers.
  • Check the Response Headers for Access-Control-Allow-Origin, Access-Control-Allow-Credentials, and Access-Control-Allow-Headers.
  • Adjust your CORS() or @cross_origin configuration 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.

Explore More Implementing CORS in APIs

Discover more examples and insights in this category.

View All Implementing CORS in APIs