What is CSRF Protection?
Stop Attackers From Forging Requests As Your Users
A user can be logged into your site in one tab and visit a trap page in another. The trap page can quietly send requests to your site using that user's session, and your server has no easy way to tell those requests apart from real ones. That is CSRF, and a tiny secret solves it.
Why Would Anyone Trust a Request They Did Not Send?
CSRF Protection = a secret token your site issues with each form so the server can tell a real submission from one an attacker tricked the browser into sending.
Most frameworks ship CSRF protection as middleware that is on by default. In Django it is CsrfViewMiddleware plus the {% csrf_token %} template tag. In Express you add the csurf (or newer csrf-csrf) package. Ask your AI: "is CSRF protection turned on in my [framework] project, and are my forms including the token?" You almost never write this code by hand.
When to Use CSRF Protection
CSRF Protection isn't always the right call. Here's a quick mental model:
Any endpoint that changes state using session cookies
POST, PUT, PATCH, DELETE routes that trust a user's session cookie to authorize the action. Transfers, profile edits, password changes, posting comments, placing orders: all need CSRF protection.
You have server-rendered forms behind a login
Classic Django, Rails, or Laravel apps render HTML forms after a user logs in. These are the exact shape CSRF was designed for. Include the token in every form and let middleware verify it on submit.
Your frontend and backend share a cookie-based session
If a logged-in React or Vue app talks to your API through a session cookie (not a bearer token in the Authorization header), CSRF applies to your API too. Use the double-submit cookie pattern: server sends the token as a readable cookie, JS reads it and echoes it in a request header.
Pure read-only GET endpoints
CSRF protects against state changes. A GET that only returns data does not need a token, provided it truly is read-only. Do not perform deletes or updates inside a GET handler, some ancient code does, and CSRF cannot save you there.
Stateless APIs authenticated by bearer token in a header
If clients send an Authorization: Bearer ... header (mobile apps, server-to-server, most modern public APIs), no cookie rides along automatically, so there is no forgery to block. CSRF only bites when the browser is attaching credentials for you.
Interactive CSRF Protection Demo
Submit a real form and then simulate an attacker's forged POST from another site. Watch the server accept the first and reject the second, and see exactly which step the token check lives in.
AI Prompts for CSRF Protection
Now that you understand csrf protection, use these prompts with your AI coding agent. Copy the one that matches what you're building — the agent will handle the implementation.
Tip: These prompts work with any AI (ChatGPT, Claude, Cursor, Copilot). Just copy, paste, and fill in the [brackets]. You do not need to know the CSRF details, the AI does.
CSRF Protection in Real Applications
Online banking transfers view the HTML of any bank's transfer form and you will find a hidden input like <code><input type="hidden" name="csrf_token" value="..."></code>. Submit without it and the server returns 403. This is the pattern CSRF was originally invented to protect.
Django admin log into /admin/ and inspect any save form. Django injects a <code>csrfmiddlewaretoken</code> hidden field automatically via the <code>{% csrf_token %}</code> tag. Disable the middleware in settings and the entire admin stops accepting POSTs.
GitHub PR buttons click "Merge pull request" and the request includes an authenticity_token. GitHub's Rails backend checks it against the one it stored for your session. The token rotates per session, which is why an old HAR capture cannot be replayed.
Stripe Dashboard logout even the "log out" link in most SaaS dashboards is a POST with a CSRF token, not a GET. Otherwise an attacker could embed a logout link on another site and log users out by surprise, which is a CSRF attack even without stealing money.
Common CSRF Protection Mistakes to Avoid
Thinking HTTPS alone protects against CSRF
HTTPS encrypts the request in transit, but the attacker's page is not trying to read the traffic. It is just triggering a new, valid-looking request from the victim's browser. The connection is encrypted and the forgery still works. HTTPS stops a different attack (eavesdropping), not this one.
Adding @csrf_exempt to "just make it work"
A form breaks, the error mentions CSRF, and someone disables the check on that view to unblock the deploy. The form now ships to production with no protection. If the view changes state, it is a live CSRF hole. Fix the real cause (missing template tag, cookie domain, wrong method) instead of exempting the route.
Putting the token in the URL
Tokens belong in hidden form fields or request headers, not query strings. URLs leak into server logs, browser history, referrer headers, and analytics. A token that shows up in a log file is as good as a stolen password for the window it is valid.
Skipping CSRF for a "stateless" API that still uses cookies
If your API is authenticated by a session cookie (because your SPA talks to your same-origin backend), it is not stateless from the browser's point of view. The cookie auto-attaches, so CSRF applies. Either switch to bearer tokens in the Authorization header, or keep CSRF on and use the double-submit pattern.
Go Deeper on CSRF Protection
CSRF Protection Interview Questions →
4 common interview questions about csrf protection, with clear practical answers.
Related Building Blocks
Also known as: csrf, xsrf, cross site request forgery, csrf token, anti csrf token, samesite cookie, double submit cookie
Ready to Build Real Products?
Learn to ship MicroSaaS apps with AI in the Solo Builder course.