This was a controlled test in headless Chrome 154.0.8037.93 on Windows, on 4 October 2026. Two temporary HTTP servers used localhost:62237 and localhost:62238, bound to the loopback interface. The values were harmless demonstration strings; we did not log into a real account or test an authentication framework. We recorded the Cookie headers received by each server. The opening image is a generated illustration.
One app replaces the other’s cookie
Both servers used the cookie name session, Path=/, HttpOnly and SameSite=Lax. We omitted Domain, making the cookie host-only. The browser context was new, with no existing user cookies.
The replacement is specified behaviour. RFC 6265’s storage algorithm replaces an existing cookie with the same name, domain and path. Its weak-confidentiality section explicitly states that cookies do not provide isolation by port. A server listening on another port of the same host can receive and replace the cookie.
That is a plausible cause when signing into one development app disturbs another. A Spring Boot project issue describes that symptom and proposes unique development cookie names. Our fixture confirms the underlying cookie replacement, rather than claiming to reproduce a particular framework’s login failure.
Meanwhile, a localStorage value called marker stayed separate. We wrote A on the first origin; the second origin initially returned null. After writing B there, returning to the first still returned A. localStorage belongs to the document’s origin, and the origin includes the port.

HttpOnly did not change that result. document.cookie returned an empty string, yet the server received session=B. The attribute restricts access from JavaScript; it does not prevent the browser from attaching the cookie to eligible HTTP requests.
A shared cookie can still be absent from fetch
From the first app’s page, a default fetch to the second app’s /echo endpoint arrived with an empty Cookie header. We could read its JSON response because the endpoint supplied suitable CORS headers. Repeating the request with credentials: "include" sent session=B, and we could still read the response.
The Fetch Standard makes same-origin the default credentials mode. These two ports produce different origins, so the default excludes the cookie even though its host scope covers the destination. The setting controls this request; it does not create a separate cookie store for each port.
const api = "http://localhost:62238/echo";
await fetch(api);
await fetch(api, { credentials: "include" });
Those were the two calls in our temporary fixture; its servers have been closed. For a comparison in your own app, substitute an endpoint you control and inspect the received Cookie header as well as the browser result. include does not override the cookie’s host, path, Secure or SameSite rules. Our test keeps both endpoints on HTTP localhost and uses a simple GET.
A CORS error can follow a received request
Next, we made that same simple GET with credentials: "include" to a route that omitted the CORS response headers. Chrome rejected the fetch with TypeError. The second server’s log nevertheless contained the request and session=B.
The server had received a credentialed request; the page was denied access to its response. The Fetch Standard’s CORS protocol requires an explicitly allowed requesting origin and Access-Control-Allow-Credentials: true for sharing this credentialed response. For our requesting page, the allowed origin was http://localhost:62237. A wildcard origin would not meet that requirement.
This observation is limited to a simple GET. A request that requires a preflight can fail before the intended operation reaches the endpoint. A console error alone therefore cannot tell you whether an operation happened. Use the server log or a harmless test endpoint to establish that separately.
For a same-name cookie collision between development apps, give each app a distinct cookie name. We tried appA_session and appB_session: both survived, and both appeared in the header sent to the first app. Naming prevents this overwrite; it does not stop the other port receiving cookies for the same host.
Host-only separation is another, different choice. Navigating to 127.0.0.1 on the second server sent none of the localhost cookies in our fixture. The browser treats those hostnames separately even when they reach the same machine. Keep application URLs and authentication callbacks consistent when choosing hosts; this test does not verify an OAuth setup.
Keep adjacent failures separate too. A public web app calling a local device needs the destination-permission checks covered in our Chrome guide. Reading browser storage during a server-rendered page’s first render has hydration consequences. Stale cached responses can obscure a changed server reply; our fixture returned Cache-Control: no-store to avoid that confounder.
Start with the observable failure: a changed cookie value calls for collision handling; an absent cookie calls for a sending-policy check; a received request with an unreadable reply calls for response-sharing checks. Adding CORS headers cannot recover the cookie value that the other app has already replaced.




