What cookies are sent in an HTTP request?
Your browser stores a bunch of “cookies”.
Compared to other client-side web storage
(localStorage
, sessionStorage
, indexedDB
, ...),
the unique property of cookies is that,
when the browser makes an HTTP request,
cookies are embedded in the request sent to the server.
The cookies are included in an HTTP header called Cookie
.
For example,
in the developer tools for this page,
under “Network”,
you’ll see an HTTP request for https://jameshfisher.com/assets/jim_512.jpg
,
a picture of me.
In the HTTP headers for that request, you can see:
Cookie: _ga=GA1.2.12345.67890; _gid=GA1.2.111111.222222
But why were these cookies sent,
and not the many others stored by my browser?
The answer is not simple!
Cookies have many attributes;
among them are the domain and path attributes,
which together are called the cookie’s “scope”.
Both Google Analytics cookies above have the domain .jameshfisher.com
and the path /
.
You can see these attributes in the Application tab of Google Chrome developer tools.
These attributes are set when the cookie is set,
for example in client-side JavaScript using the API:
document.cookie = 'test_cookie=foo'
.
When setting a cookie,
the default domain is the domain of the current page,
i.e. jameshfisher.com
,
and the default path is the path of the current page,
i.e. /2020/01/01/what-cookies-are-sent-in-an-http-request
.
Note the domain attributes of these two cookies are different:
.jameshfisher.com
versus jameshfisher.com
.
The leading dot means “this is a domain suffix”;
a cookie with domain .jameshfisher.com
will match subdomain.jameshfisher.com
, too.
A cookie with domain jameshfisher.com
will only match the domain jameshfisher.com
,
and will not match subdomains.
Confusingly, whether the domain attribute is a suffix is determined by
whether you explicitly set the domain attribute when setting the cookie.
If you explicitly set a domain attribute when setting the cookie,
it will be a domain suffix (shown with leading dot).
If you don’t explicitly set a domain attribute,
it will be a fully-qualified domain,
i.e. jameshfisher.com
in this example.
A cookie is only sent in an HTTP request
if the hostname that the request is being sent to
matches the domain, or domain suffix,
in the cookie.
The browser will never send a cookie
to a hostname that doesn’t match the cookie’s domain attribute.
An HTTP origin
An HTTP request made by a browser has two relevant origins:
the origin that makes the request,
and the origin that the request is sent to.
Whether cookies are sent depends on how the request was made.
There are many APIs to invoke an HTTP request from a browser:
-
The user follows a link, i.e. clicks on an <a>
element.
Cookies are sent.
-
The user submits a form, e.g. clicks on a <button type="submit">
element.
Cookies are sent.
-
The page loads some media, e.g. an image via an <img>
element.
Cookies are sent.
-
The page loads a script from a <script>
element.
Cookies are sent, unless the element has crossorigin=anonymous
set.
-
Some JavaScript on the page invokes XMLHttpRequest
.
-
Some JavaScript on the page calls fetch
.
-
The attributes of the cookie (domain and path)
-
The domain and path of the URL the request is being made to
-
The domain and path of the page making the request (???)
To test this behavior,
I’ve set up some domains in /etc/hosts
:
$ cat /etc/hosts
...
127.0.0.1 s1.com
127.0.0.1 s2.com
127.0.0.1 sub.s2.com
And I’m running the “web servers” for s1.com
and s2.com
using nc
, like so:
$ while true; do cat response.http | nc -l 8000; done
This lets me control the full HTTP response by typing it out.
Here’s a starter page:
$ cat index.http
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
<!doctype html>
<html><body><h1>A webpage served by netcat</h1></body></html>
Then run nc
in an infinite loop to serve this file for every response:
When the browser makes an HTTP request,
it will include each cookie
whose scope matches the target URL.
Similar posts
How can I capture all crashes in a web page?
Including uncaught errors, unhandled promise rejections, image load failures, Content Security Policy violations, and console.error
calls. 2024-03-14
How do errors in a web page reach the dev console?
Errors in JavaScript cause an ErrorEvent
on window
. Preventing the default action blocks console output. Resource errors follow the capture-bubble event model. 2024-03-13
A formula for responsive font-size
Try setting the root font-size to calc(1rem + 0.25vw)
instead of using media queries with fixed breakpoints. 2024-03-12
Setting font-size based on viewing distance
Estimating viewing distance from screen size to set optimal font-size, but other factors like user mobility, long-sightedness, and short-sightedness complicate the ideal font-size calculation. 2024-03-11
How does HotJar record your screen?
“Session replay” tools record user interactions by capturing DOM changes, external resources, and viewport state, using efficient techniques like the MutationObserver API. 2024-03-09
How to replace GIF with HTML video in 2021
To replace a GIF with an HTML <video>
element in 2021, use a long list of attributes disable unwanted browser behaviors. 2021-01-19
More by Jim
What does the dot do in JavaScript?
foo.bar
, foo.bar()
, or foo.bar = baz
- what do they mean? A deep dive into prototypical inheritance and getters/setters. 2020-11-01
Smear phishing: a new Android vulnerability
Trick Android to display an SMS as coming from any contact. Convincing phishing vuln, but still unpatched. 2020-08-06
A probabilistic pub quiz for nerds
A “true or false” quiz where you respond with your confidence level, and the optimal strategy is to report your true belief. 2020-04-26
Time is running out to catch COVID-19
Simulation shows it’s rational to deliberately infect yourself with COVID-19 early on to get treatment, but after healthcare capacity is exceeded, it’s better to avoid infection. Includes interactive parameters and visualizations. 2020-03-14
The inception bar: a new phishing method
A new phishing technique that displays a fake URL bar in Chrome for mobile. A key innovation is the “scroll jail” that traps the user in a fake browser. 2019-04-27
The hacker hype cycle
I got started with simple web development, but because enamored with increasingly esoteric programming concepts, leading to a “trough of hipster technologies” before returning to more productive work. 2019-03-23
Project C-43: the lost origins of asymmetric crypto
Bob invents asymmetric cryptography by playing loud white noise to obscure Alice’s message, which he can cancel out but an eavesdropper cannot. This idea, published in 1944 by Walter Koenig Jr., is the forgotten origin of asymmetric crypto. 2019-02-16
How Hacker News stays interesting
Hacker News buried my post on conspiracy theories in my family due to overheated discussion, not censorship. Moderation keeps the site focused on interesting technical content. 2019-01-26
My parents are Flat-Earthers
For decades, my parents have been working up to Flat-Earther beliefs. From Egyptology to Jehovah’s Witnesses to theories that human built the Moon billions of years in the future. Surprisingly, it doesn’t affect their successful lives very much. For me, it’s a fun family pastime. 2019-01-20
The dots do matter: how to scam a Gmail user
Gmail’s “dots don’t matter” feature lets scammers create an account on, say, Netflix, with your email address but different dots. Results in convincing phishing emails. 2018-04-07
The sorry state of OpenSSL usability
OpenSSL’s inadequate documentation, confusing key formats, and deprecated interfaces make it difficult to use, despite its importance. 2017-12-02
I hate telephones
I hate telephones. Some rational reasons: lack of authentication, no spam filtering, forced synchronous communication. But also just a visceral fear. 2017-11-08
The Three Ts of Time, Thought and Typing: measuring cost on the web
Businesses often tout “free” services, but the real costs come in terms of time, thought, and typing required from users. Reducing these “Three Ts” is key to improving sign-up flows and increasing conversions. 2017-10-26
Granddad died today
Granddad died. The unspoken practice of death-by-dehydration in the NHS. The Liverpool Care Pathway. Assisted dying in the UK. The importance of planning in end-of-life care. 2017-05-19
How do I call a program in C, setting up standard pipes?
A C function to create a new process, set up its standard input/output/error pipes, and return a struct containing the process ID and pipe file descriptors. 2017-02-17
Your syntax highlighter is wrong
Syntax highlighters make value judgments about code. Most highlighters judge that comments are cruft, and try to hide them. Most diff viewers judge that code deletions are bad. 2014-05-11
Want to build a fantastic product using LLMs? I work at
Granola where we're building the future IDE for knowledge work. Come and work with us!
Read more or
get in touch! This page copyright James Fisher 2020. Content is not associated with my employer. Found an error? Edit this page.