Skip to the content.

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.

-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