Django CSRF 🐍 Python

Forbidden (403) CSRF verification failed. Request aborted.

Django rejected a POST because the CSRF token was missing, wrong, or the request origin isn’t trusted.

Seen on: Python

Meaning

Forms need {% csrf_token %}; AJAX needs the X-CSRFToken header. Since Django 4.0, HTTPS sites behind proxies also need CSRF_TRUSTED_ORIGINS with the scheme (https://example.com).

Common causes

  • Form missing {% csrf_token %}
  • AJAX request without X-CSRFToken
  • Django 4+: origin not in CSRF_TRUSTED_ORIGINS
  • Cookies blocked / CSRF cookie missing
  • Proxy not setting X-Forwarded-Proto

⚡ Quick fix

  1. Add {% csrf_token %} inside POST forms
  2. Send the token header in fetch/axios
  3. Set CSRF_TRUSTED_ORIGINS = ["https://example.com"]
  4. Set SECURE_PROXY_SSL_HEADER behind HTTPS proxies

Detailed fix by platform

Python

  1. CSRF_TRUSTED_ORIGINS = ["https://example.com", "https://www.example.com"]

How to diagnose

  1. Reason — The debug page gives the exact reason
  2. Origin — Listed in trusted origins?

🧠 Still stuck? Analyze your error

Paste the full message, response headers or stack trace — we'll detect the platform and point to the most likely cause.