django-cors-headers

Configurable CORS headers middleware for Django applications

Library
PyPI
v4.9.0
5,585 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
64 /100 Good
Development Activity 60
Maintenance 24
Community 72
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
79 /100 Good
Architecture 78
Code Quality 90
Innovation 62
Learning Curve 85

django-cors-headers is a Django application that adds Cross-Origin Resource Sharing (CORS) headers to HTTP responses, allowing in-browser requests to reach your Django backend from other origins. It ships as a single middleware class plus a small settings surface (allow-lists, regex origin matching, credential support, private-network access) so teams can expose an API to a separate frontend domain, a mobile app, or third-party integrations without hand-rolling header logic.

Originally created in 2013 and now maintained by Adam Johnson with contributions from 70+ people, it has become the de facto standard for CORS in the Django ecosystem, used by hundreds of thousands of projects that separate their API from their frontend (React/Vue SPAs, mobile clients, partner integrations).

What You Get

  • A single CorsMiddleware class supporting both sync and async Django request/response cycles
  • Exact-match (CORS_ALLOWED_ORIGINS) and regex-match (CORS_ALLOWED_ORIGIN_REGEXES) origin allow-lists
  • A Django signal (check_request_enabled) for fully custom, per-request CORS logic (e.g. DB-backed multi-tenant origin lists)
  • Support for credentials, exposed headers, custom allowed headers/methods, preflight cache duration, and Private Network Access preflight handling
  • Built-in Django system checks that catch misconfigured settings (wrong types, malformed origins) at startup rather than at request time

Common Use Cases

  • Serving a Django REST/GraphQL API to a separately-hosted single-page app (React, Vue, Svelte) during local development and in production
  • Allowing a mobile app or third-party partner service to call a Django-backed API from a browser-based origin
  • Multi-tenant SaaS platforms that need to allow CORS from arbitrary customer subdomains via regex or a DB-driven signal handler
  • Locking down which origins, methods, and headers are permitted for security-sensitive internal APIs

Under The Hood

Architecture - The library is a single Django “app” (corsheaders) with a clean separation of concerns: middleware.py holds the one public entry point (CorsMiddleware), which reads all behavior from a lazily-evaluated conf.Settings object (conf.py) that shadows Django’s settings module with defaults from defaults.py. Preflight (OPTIONS) requests are short-circuited in check_preflight() before hitting the view, while normal responses get headers appended in add_response_headers() after the view runs — origin checks flow through exact allow-list, regex allow-list, and finally an opt-in Django Signal (check_request_enabled in signals.py) for fully custom logic, giving three escalating levels of configurability without ever touching the middleware’s code.

Tech Stack - Pure Python (100%) with a minimal dependency footprint: only asgiref>=3.6 (for iscoroutinefunction/markcoroutinefunction sync/async detection) and django>=5.2. Build tooling is modern and lightweight — setuptools build backend, ruff for linting (with isort, pyupgrade, flake8-bugbear rule sets enabled), mypy --strict for type-checking, and uv for dependency/test-matrix management across Django 5.2/6.0/6.1 and Python 3.10-3.14.

Code Quality - The tests/ directory (749 lines across 6 files) exercises the middleware extensively in test_middleware.py (467 lines covering allow-list matching, regex matching, signals, credentials, preflight, and private-network headers) plus a dedicated test_checks.py (159 lines) that validates every Django system-check error path (corsheaders.E001-E015). The project advertises 100% coverage via CI badge, uses mypy --strict with warn_unreachable and redundant-expr enabled, and every public function carries type hints — a strong quality bar with no unaddressed technical debt visible in the source.

API Design - The public surface is deliberately tiny: add one middleware class to MIDDLEWARE, add corsheaders to INSTALLED_APPS, and set 1-2 settings (CORS_ALLOWED_ORIGINS or CORS_ALLOW_ALL_ORIGINS). Settings names are self-documenting and mirror Django’s own naming conventions, with backwards-compatible aliases retained for renamed settings (e.g. CORS_ORIGIN_WHITELIST still works as an alias for CORS_ALLOWED_ORIGINS). The README documents every setting with defaults and examples, and startup-time system checks fail fast with actionable error messages when a setting is misconfigured, minimizing the debugging loop for new users.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers