curl with cookies in C# (curl -b)
To send cookies with curl in C#, pass -b 'name=value' in the command string you give to Curl.ExecuteAsync. The value is sent verbatim as the Cookie request header, so several cookies are separated with ; just like on the command line. To keep cookies between requests, use a cookie jar: -c jar.txt saves them in curl’s Netscape format and -b jar.txt sends them back, exactly as with the curl CLI.
The curl command
using CurlDotNet;
var result = await Curl.ExecuteAsync(
"curl -b 'session=abc123; theme=dark' https://httpbin.org/cookies");
Console.WriteLine(result.Body); // {"cookies": {"session": "abc123", "theme": "dark"}}
-H 'Cookie: session=abc123' does exactly the same thing if you prefer a plain header. Repeating -b with name=value strings joins them with ; .
How curl reads -b decides everything else: a value containing = is a cookie string, and a value without = is the name of a cookie file to load.
Builder style
using CurlDotNet.Core;
var result = await CurlRequestBuilder.Get("https://httpbin.org/cookies")
.WithCookie("session=abc123; theme=dark")
.ExecuteAsync();
Console.WriteLine(result.Body);
Read cookies the server sets
Response cookies arrive in the Set-Cookie header. result.Headers is case-insensitive, so GetHeader finds it whatever the server’s casing:
var result = await Curl.ExecuteAsync(
"curl https://httpbin.org/cookies/set?session=abc123");
Console.WriteLine(result.StatusCode); // 302 (httpbin redirects after setting)
Console.WriteLine(result.GetHeader("Set-Cookie")); // session=abc123; Path=/
Add -L if you want to follow that redirect and see the cookie echoed back; see follow redirects.
Keep a session with a cookie jar (-c and -b FILE)
-c FILE writes every cookie the server set during the transfer to FILE when the command finishes. -b FILE loads that file on the next command and sends the cookies that match the URL. Use both on every call and the session carries on, just like a curl shell script:
// 1. Log in: the server sets a session cookie; -c saves it
await Curl.ExecuteAsync(
"curl -c jar.txt -b jar.txt https://httpbin.org/cookies/set/session/abc123");
// 2. Later requests send it back (and keep the jar up to date)
var page = await Curl.ExecuteAsync(
"curl -c jar.txt -b jar.txt https://httpbin.org/cookies");
Console.WriteLine(page.Body); // {"cookies": {"session": "abc123"}}
Within one command the cookie engine follows redirects too: a cookie set by a 302 is sent on the next hop, so curl -L -c jar.txt https://httpbin.org/cookies/set?session=abc123 ends on a page that already sees the cookie. Several URLs in one command line share one cookie store.
A file given to -b that does not exist is treated as an empty jar, as in curl, so the first call above works before jar.txt exists. -b also accepts a file of raw Set-Cookie: header lines.
What the jar file looks like
The jar is curl’s Netscape format, newest cookie first, with curl’s header comment. Cookies marked HttpOnly get the #HttpOnly_ prefix, and expiry times are capped at 400 days, as curl does:
# 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 session abc123
-c - writes the jar text into result.Body instead of a file. A jar in a directory that does not exist fails with CurlWriteErrorException (exit code 23).
Start a new browser session (-j)
-j / --junk-session-cookies drops the session cookies (those without an expiry) while loading -b FILE, the same as closing and reopening a browser. Persistent cookies stay:
await Curl.ExecuteAsync("curl -j -b jar.txt -c jar.txt https://httpbin.org/cookies");
Which cookies are sent
The engine applies curl’s rules from lib/cookie.c: domain matching (a cookie for example.com is not sent to other.com), path matching, Secure cookies only over HTTPS, the __Secure- and __Host- name prefixes, Max-Age and Expires, and curl’s ordering (longest path first). Cookies from the jar come first, followed by any -b name=value string.
Gotchas
- Cookie values with spaces or semicolons need quoting inside the command string, exactly as in a shell:
-b 'a=1; b=two words'. - A plain
-b 'name=value'string turns no cookie engine on: nothing is stored, and cookies set by the server are not sent on redirect hops. Add-c(or-b FILE) when you want that. - Each
Curl.ExecuteAsynccall is independent. Cookies only carry over between calls through a jar file (-cthen-b). - The builder’s
WithCookie(...)andWithCookieJar(path)set the same-band-cvalues.
Related
- Cookie errors
- curl -H HTTP headers in C#
- curl digest, NTLM and basic auth in C# - when the server wants credentials instead of a cookie
- Cookbook index