How to configure CORS in Python Django

Enable Cross-Origin Resource Sharing (CORS) in a Django application using the django-cors-headers package with CORS_ALLOWED_ORIGINS in settings.py.

Configure Cross-Origin Resource Sharing (CORS) in a Python Django application using the django-cors-headers package to allow cross-origin requests from trusted origins.

Prerequisites

  • Python 3.10 or later installed.
  • A Django 4.2 or later project.
  • pip for package management.

Step-by-Step: Enable CORS in Python Django

  1. Install the django-cors-headers package. This package provides Django middleware that adds Cross-Origin Resource Sharing (CORS) response headers:

    pip install django-cors-headers
  2. Add corsheaders to the INSTALLED_APPS list in settings.py:

    INSTALLED_APPS = [
        # ...
        'corsheaders',
        # ...
    ]
  3. Add the CORS middleware to the MIDDLEWARE list in settings.py. Place CorsMiddleware as high as possible in the list, before CommonMiddleware and any middleware that generates responses:

    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        # ...
    ]
  4. Configure the allowed origins in settings.py. Choose one of the following options depending on the Cross-Origin Resource Sharing (CORS) requirements.

    Option A: Allow specific origins-- Set CORS_ALLOWED_ORIGINS to a list of trusted domains:

    CORS_ALLOWED_ORIGINS = [
        'https://app.example.com',
        'https://admin.example.com',
    ]

    Option B: Allow all origins-- Set CORS_ALLOW_ALL_ORIGINS to True for public APIs that do not use credentials. Do not use this setting in production for APIs that handle sensitive data:

    CORS_ALLOW_ALL_ORIGINS = True

    Option C: Allow origins with credentials-- Enable CORS_ALLOW_CREDENTIALS when the front-end sends cookies or authentication headers. This setting requires explicit origins in CORS_ALLOWED_ORIGINS:

    CORS_ALLOWED_ORIGINS = [
        'https://app.example.com',
    ]
    CORS_ALLOW_CREDENTIALS = True

    Option D: Allow specific headers and methods-- Customize the permitted headers and HTTP methods:

    CORS_ALLOW_HEADERS = [
        'content-type',
        'authorization',
        'x-requested-with',
    ]
    
    CORS_ALLOW_METHODS = [
        'GET',
        'POST',
        'PUT',
        'DELETE',
        'OPTIONS',
    ]
  5. Set CSRF_TRUSTED_ORIGINS if the front-end makes state-changing requests with credentials. Django's Cross-Site Request Forgery (CSRF) protection requires a separate allowlist from CORS:

    CSRF_TRUSTED_ORIGINS = [
        'https://app.example.com',
    ]

How to Verify CORS Is Working in Django

Start the Django development server and send a test request with curl to confirm Cross-Origin Resource Sharing (CORS) headers appear in the response:

curl -I -H "Origin: https://app.example.com" http://localhost:8000/api/data/

The response should include:

Access-Control-Allow-Origin: https://app.example.com

Common Issues When Configuring CORS in Django

  • Middleware order incorrect. CorsMiddleware must run before CommonMiddleware. Django processes middleware top to bottom, and a lower placement may miss the Origin header.
  • CORS_ALLOW_ALL_ORIGINS with CORS_ALLOW_CREDENTIALS.The browser rejects responses with Access-Control-Allow-Origin: * when credentials are included. Use CORS_ALLOWED_ORIGINS with explicit domains when CORS_ALLOW_CREDENTIALS = True.
  • CSRF errors on POST requests.CORS and CSRF are separate mechanisms in Django. Add the front-end origin to both CORS_ALLOWED_ORIGINS and CSRF_TRUSTED_ORIGINS.
  • Duplicate headers from reverse proxy.Nginx or Apache adds CORS headers that conflict with Django's headers. Configure CORS in one layer only.

For a detailed explanation of the CORS mechanism, see CORS tutorial: How Cross-Origin Resource Sharing works.