In order to work around cases where it wasn't possible
automatically authenticate with a website, I wanted the ability
to use an embedded Internet Explorer window for manual
authentication and then reuse the cookies. This article
describes how to read cookies indirectly using
InternetGetCookieEx or directly from a
InternetGetCookieEx Win32 API can be used to read
cookie name value pairs for a given URI. You can use it to read
all cookies or a named cookie. You can also specify which type
of cookies to include.
To use this function, we specify the URL we want to query, the
name of the cookie to lookup (or
null for all), a buffer to
store the cookie data, the length of the buffer and then flags
to describe what we want returned. The function returns
if it succeeds, otherwise
false. In line with other Win32
calls, you can use
GetLastError to get the error code in the
event of a failure.
The last part is quite important as if the buffer provided is
too small, the function will fail and calling
ERROR_INSUFFICIENT_BUFFER. In this case, the
buffer length parameter will contain the size required to
contain the data so that you can allocate a new buffer and call
the function again.
I saw a number of naïve implementations on the internet that
InternetGetCookieEx without doing any sort of error
checking; this could lead to subtle bugs in the event that the
cookies are longer than the supplied buffer as no data will be
The following function can be used to get all cookies for a
given URI. I create a buffer that will hold 1024 characters and
make a call to
InternetGetCookieEx. If it fails but the error
ERROR_INSUFFICIENT_BUFFER then I increase the buffer
size and try again.
In the example above, I'm requesting to include HTTP only cookies. The documentation states: "Do not use this flag if you expose a scriptable interface, because this has security implications. It is imperative that you use this flag only if you can guarantee that you will never expose the cookie to third-party code by way of an extensibility mechanism you provide."
According to the documentation, the
lpdwSize parameter will be
updated to specify the number of bytes required to hold the
value, however, I'm creating a buffer that uses that value in
chars to keep it simple.
Using the WebBrowser control directly
InternetGetCookieEx would be my preferred
approach, if you already have a
WebBrowser control you can
read the cookies directly from the control. The
property of a
WebBrowser control returns a
in turn contains the
Cookie property. The format of the
returned data matches that of
There is one important difference between using
HtmlDocument.Cookie- the later does not include HTTP only cookies. If you require access to all cookies for a given URI, then use
What about the cookie properties?
The methods describe above only seem to return the names and values of cookies, excluding properties such as paths and expiry dates. Unfortunately I don't know of a method of accessing these extended properties in modern versions of Windows.
Using the cookies
As Windows and browsers have evolved, there is probably little use for this particular API call. Internet Explorer is obsolete and third party browsers (and Edge) use their own cookie storage mechanisms that this API cannot access. Speaking for myself, the only use I have for this technique is to make custom requests to an internet resource after using an embedded IE window to authenticate with a website.
The following example demonstrates how you could assign cookies
HttpWebRequest. Note that the
SetCookies method of the
CookieContainer class requires the cookies to be comma
separated, rather than the semi-colon seperated values returned
by the above function.
The attached demonstration program includes a complete sample
for reading cookies either via
InternetGetCookieEx or from a
WebBrowser control, and is also available from our GitHub
I originally wrote this demonstration back in October 2018 but I delayed it while trying to find out a solution to the missing properties. I was also curious as to why Edge didn't seem to use the same system and had a vague idea looking into that. Then came the news that Microsoft have decided to drop their custom Edge engine and use Chromium instead.
This seems astonishingly short sighted to me and is a real disappointment.
While I confess I don't use Edge as my primary browser (Firefox
is my daily driver due to its extension support and excellent
developer tools), I found it to be a decent browser which didn't
let me down when I did use it. To me it is perplexing that they
are essentially ceding control to Google. It's like Windows
Phone all over again and I like my Windows Phone. It is also
frustrating as currently you can get a reasonable browsing
experience by embedding Internet Explorer via the
control into your application (with a little help) without
having to worry about shipping any dependencies and I had hopes
of doing the same with Edge for a truly modern experience.
- 2019-01-20 - First published
- 2020-11-22 - Updated formatting
Like what you're reading? Perhaps you like to buy us a coffee?