When does the browser send the Origin header? (tested)

The Origin header tells a server which site a request came from. It is the basis of CORS and a common CSRF check, but browsers do not send it on every request. We logged what Chromium actually sent.

1. What the server received

Page at http://localhost:8971. "Cross-origin" means a request to http://127.0.0.1:8972.

RequestOrigin sentReferer sent
fetch() GET, same-origin(absent)full page URL
fetch() POST, same-originhttp://localhost:8971full page URL
fetch() PUT, same-originhttp://localhost:8971full page URL
fetch() GET, cross-originhttp://localhost:8971origin only
fetch() POST, cross-originhttp://localhost:8971origin only
<form method=POST>, same-originhttp://localhost:8971full page URL
<form method=POST>, cross-originhttp://localhost:8971origin only
<form method=GET>, same- or cross-origin(absent)sent
<img>, cross-origin(absent)origin only
<img crossorigin>, cross-originhttp://localhost:8971origin only
<img crossorigin>, same-originhttp://localhost:8971full page URL
Link click (top-level navigation), cross-origin(absent)origin only

The pattern: Chromium sent Origin on every request in CORS mode (cross-origin fetch, crossorigin images) and on every non-GET request, same-origin included. It left Origin off same-origin GET fetches, GET form submissions, plain images and link clicks. So a missing Origin on a GET is normal and tells you little.

2. When Origin is the string "null"

RequestOrigin sentReferer sent
Page with Referrer-Policy: no-referrer, fetch() GET or POST (same- or cross-origin)http://localhost:8971(absent)
Page with Referrer-Policy: no-referrer, cross-origin <form method=POST>null(absent)
Sandboxed iframe (sandbox="allow-scripts"), fetch() GET or POSTnull(absent)

Referrer-Policy: no-referrer removed Referer everywhere, but it did not hide the origin from fetch(). It did turn the Origin of a cross-origin form POST into the literal string null. A sandboxed iframe has an opaque origin, so everything it sent carried Origin: null. Data: URLs and redirects across origins are documented to produce null too; we did not test those. Never put null in an Access-Control-Allow-Origin allowlist: any sandboxed iframe on any site can send it.

3. Origin is not authentication

Any non-browser client can send whatever Origin it likes. Against a small test server:

$ curl -s -H 'Origin: https://bank.example' http://127.0.0.1:8973/
Origin seen: https://bank.example

Browsers do not let page scripts set or change Origin, which is why checking it works as a CSRF defense: a malicious page can make the browser send a POST with your user's cookies, but it cannot make the Origin say your site. That protection only applies to requests from browsers. It does nothing against a script, a bot or curl, so you still need real authentication on the API.

4. Using Origin for a CSRF check

Related: allowing multiple origins in CORS, Access-Control-Allow-Credentials and the Referrer-Policy header.

Frequently asked questions

Does the browser send the Origin header on GET requests?

Only sometimes. In our Chromium 153 test, cross-origin fetch GET and img crossorigin sent it; same-origin fetch GET, GET form submissions, plain img tags and link clicks did not.

Does the browser send Origin on same-origin requests?

Yes for POST and PUT: Chromium sent Origin on same-origin fetch POST/PUT and same-origin form POST. It did not on same-origin fetch GET.

Why is my Origin header null?

In our test Origin was the string null for requests from a sandboxed iframe and for a cross-origin form POST from a page with Referrer-Policy: no-referrer. Data: URLs and some cross-origin redirects are documented to do the same (not tested).

Does Referrer-Policy: no-referrer remove the Origin header?

No for fetch: Chromium still sent the real origin on fetch GET and POST, while Referer disappeared. A cross-origin form POST from that page sent Origin: null.

Can the Origin header be spoofed?

Not by page JavaScript in a browser, which is why it works for CSRF checks. Any non-browser client can: curl -H 'Origin: https://bank.example' delivered exactly that value to our server. Do not use it as authentication.

Should I allow Origin null in CORS?

No. Any sandboxed iframe on any site sends Origin: null, so allowing it lets arbitrary pages read your responses.

Written with AI assistance. Measured on 2026-10-01 in full Chromium 153.0.8010.12 (Playwright, channel 'chromium', fresh browser context per row). The page was served from http://localhost, a second Node.js server on http://127.0.0.1 (a different origin) logged the Origin and Referer headers of every request, and the same-origin server logged them too. The curl check used curl 8.14.1. Notes on Firefox and Safari and on server frameworks are doc-based, not tested. PlainHeaders is our extension; the other methods are free.