The Netscape cookie file — everyone calls it cookies.txt — is the lingua franca
between browsers and command line HTTP clients. curl, wget and yt-dlp all read it, which is why
it keeps turning up decades after the browser that named it disappeared. The format is simple
enough to explain in one screen, and every problem people have with it comes from the same three
or four details.
One cookie per line, seven fields, tab-separated
domain include_subdomains path secure expires name value A real line, with the tabs shown as gaps:
.example.com TRUE / TRUE 1789200000 session_id abc123 | # | Field | Meaning |
|---|---|---|
| 1 | domain | Host the cookie belongs to. A leading dot is the historic marker for "and subdomains". |
| 2 | include_subdomains | TRUE or FALSE — uppercase. Mirrors the leading dot. |
| 3 | path | Path prefix the cookie is sent for, usually /. |
| 4 | secure | TRUE means HTTPS only. |
| 5 | expires | Unix timestamp in seconds. 0 means a session cookie. |
| 6 | name | Cookie name. |
| 7 | value | Cookie value, to the end of the line. Not quoted, not escaped. |
The header and comment lines
Most writers start the file with a magic comment, and some readers insist on it:
# Netscape HTTP Cookie File
# This file was generated by a cookie tool. Edit at your own risk.
.example.com TRUE / TRUE 1789200000 session_id abc123
Lines beginning with # are comments — with one important exception. curl marks
HttpOnly cookies with a pseudo-comment prefix:
#HttpOnly_.example.com TRUE / TRUE 1789200000 sid abc A naive parser treats that as a comment and silently drops the cookie — which is exactly the cookie you needed, since HttpOnly is what session tokens use. Any parser worth using strips the prefix and keeps the flag.
The four things that break cookies.txt files
- Spaces instead of tabs. The separator is a literal tab. Editors that convert tabs to spaces on save destroy the file, and the error message you get is usually just "no cookies loaded".
- Milliseconds in the expiry field. JavaScript timestamps are milliseconds; this format wants seconds. A 13-digit number puts the expiry roughly 50,000 years out, and some clients reject it.
- Missing trailing newline. Several readers ignore the final line without one.
- Expecting attributes that do not exist. There is no field for
SameSite, and none for HttpOnly beyond the prefix hack. Convert to JSON when you need full fidelity.
Using the file with curl and wget
# send cookies from the file, and save any new ones back
curl -b cookies.txt -c cookies.txt https://example.com/dashboard
# wget equivalent
wget --load-cookies cookies.txt --save-cookies cookies.txt \
--keep-session-cookies https://example.com/dashboard --keep-session-cookies matters: without it, session cookies (expiry
0) are dropped when the file is written, and the export you just made is useless.
Converting to and from JSON
cookies.txt is a transport format, not a storage format. For backups, fixtures or
anything involving SameSite and HttpOnly, a JSON array carries every attribute
instead of four of them. You can convert either direction in the
free online cookie converter — it runs in the page, so nothing is uploaded
— or straight from the extension's export panel.
[
{
"name": "session_id",
"value": "abc123",
"domain": ".example.com",
"path": "/",
"secure": true,
"httpOnly": true,
"sameSite": "lax",
"expirationDate": 1789200000
}
] Related reading: moving cookies between browsers, the JSON vs cookies.txt mapping, curl cookies.txt, yt-dlp cookies.txt, and the full format reference.