How to check cookie flags with curl
Two different reads. curl -s -o /dev/null -D - URL prints the Set-Cookie lines the server sent, attributes included. curl -c jar.txt URL writes what curl decided to keep, and -b jar.txt sends it back. The jar records Secure and HttpOnly in columns and drops SameSite completely.
Why check this
Reading cookies from the command line is how you take the browser out of a bug report. The browser shows you the cookies that survived its own rules, so a cookie it rejected is invisible in DevTools and looks like a server that never set it. curl shows the header as sent, which separates "the application did not set it" from "the browser threw it away". Run this the moment a login works for one tester and not another.
Prerequisites
- curl 8.0 or later, any build. No TLS features are needed beyond reaching the host. See the curl cookie documentation.
- A writable directory for the jar file. Delete it between runs or you will read yesterday's session.
- A request that sets the cookie.
https://httpbin.org/cookies/set?name=valueis used below and sets exactly what you ask it to.
Steps
- Step 1.
Print the response headers and read what the server sent.
curl -s -o /dev/null -D - 'https://httpbin.org/cookies/set?sid=abc123&theme=dark' | grep -i -E '^HTTP/|^set-cookie|^location'HTTP/2 302 location: /cookies set-cookie: sid=abc123; Path=/ set-cookie: theme=dark; Path=/Two cookies with
Pathand nothing else. NoSecure, noHttpOnly, noSameSite. This is the raw header, before any client rule is applied. - Step 2.
Write the cookie jar to stdout with
-c -instead of a filename.curl -s -o /dev/null -c - 'https://httpbin.org/cookies/set?sid=abc123&theme=dark'# Netscape HTTP Cookie File # https://curl.se/docs/http-cookies.html # This file was generated by libcurl! Edit at your own risk. httpbin.org FALSE / FALSE 0 theme dark httpbin.org FALSE / FALSE 0 sid abc123Seven tab-separated columns: host, whether subdomains are included, path, the
Secureflag, the expiry as a Unix timestamp, the name, the value.0in the expiry column marks a session cookie. - Step 3.
Run step 2 again with
-c jar.txtso the jar lands in a file, then send that file back.curl -s -b jar.txt https://httpbin.org/cookies{ "cookies": { "sid": "abc123", "theme": "dark" } }-cwrites,-breads. Pass both on the same command to keep a session alive across several requests. - Step 4.
Point the jar at a host that sets real attributes, and read the flag columns without the values.
curl -s -o /dev/null -c - https://www.cloudflare.com/ | grep -v '^#\s' | grep . | cut -f1,2,3,4,6#HttpOnly_.www.cloudflare.com TRUE / TRUE __cf_bm www.cloudflare.com FALSE / TRUE kndctr_8AD56F28618A50850A495FB6_AdobeOrg_identity #HttpOnly_www.cloudflare.com FALSE / TRUE cfz_adobe #HttpOnly_www.cloudflare.com FALSE / TRUE cfz_google-analytics_v4 www.cloudflare.com FALSE / FALSE _gaHttpOnlybecomes a#HttpOnly_prefix on the host column, andSecureis the fourth column.SameSiteappears nowhere, because the file format has no column for it. - Step 5.
Send a cookie you typed yourself, with no jar involved.
curl -s -b 'sid=abc123; theme=dark' https://httpbin.org/cookies{ "cookies": { "sid": "abc123", "theme": "dark" } }-btreats an argument containing=as cookie data and anything else as a filename. This is how you replay one value from a bug report without reproducing the login.
How to read the result
| What you see | What it means | What to do |
| --- | --- | --- |
| #HttpOnly_ prefix on the host column | The server sent HttpOnly | Nothing. This is the jar's way of recording it. |
| TRUE in the fourth column | The server sent Secure | Nothing. Compare with the header if it surprises you. |
| 0 in the fifth column | A session cookie with no expiry | It survives in the file, which is not what a browser does at close. |
| A leading dot on the host, as in .www.example.com | The cookie was set with a Domain attribute | Check whether every subdomain should receive it. |
| No SameSite anywhere in the file | The format cannot store it | Read the attribute from the Set-Cookie header instead. |
| The jar is empty after a request that set a cookie | curl rejected it, usually a Domain that does not match | Compare with step 1. The header will show what was sent. |
Common mistakes
What to check next
- How to check if cookies are secure and HttpOnly: what those two columns defend against, and when each one is required.
- How to check SameSite cookie attribute: the attribute the jar cannot store, read from the header instead.
- How to check HTTP response headers with curl:
-D,-oand-i, and when each one is right. - How to test API with curl: carrying a session into an API call once the jar holds it.
- Security headers checker: the response headers that sit alongside
Set-Cookie.
FAQ
How to check the Set-Cookie header?
Step 1. -D - writes the response headers to stdout and -o /dev/null discards the body, so grep sees only headers. Add -L to include the headers of every hop in a redirect chain.
What is the cookie jar file format?
The Netscape format: one cookie per line, seven tab-separated fields, comment lines starting with #. HttpOnly is encoded as a #HttpOnly_ prefix on the host field, which is why those lines look like comments.
Why does the browser show fewer cookies than curl sent?
The browser drops cookies that break its rules, SameSite=None without Secure among them, and hides HttpOnly cookies from document.cookie. curl reports the header as received and leaves the rules alone.
Can I edit the jar by hand?
Yes, the file is plain text with tab separators. Keep the tabs. A jar edited with spaces is read as a malformed line and skipped without a warning.
How do I keep a session across several curl calls?
Pass -b jar.txt -c jar.txt on every request. Reading and writing the same file is what makes a rotated session token survive to the next call.
Verified
Verified by Maks Vernycurl 8.21.0
Each output block is what the command above it printed on that date, on the host named in the step. Figures read from a live site move between runs. Compare the shape of the answer rather than the digits, and see the methodology for how a page is re-verified.
Related on this site
basic5 minpublished updated Maks Verny