Alert Document.Cookie: What It Shows and Hides

Sep 7, 2026·20 min read

You run alert(document.cookie) while debugging a sign-in page. A dialog appears with theme=midnight, but the session cookie visible in developer tools is missing.

alert(document.cookie) displays the script-readable cookies available to the current document, not every cookie stored by the browser or sent with requests.

What Does alert(document.cookie) Do?

The expression reads the current document’s available cookies and passes the resulting string to a browser dialog:

alert(document.cookie);

Three parts do the work.

  • alert refers to window.alert(), which displays an optional message in a dialog.
  • document is the browser object representing the page whose JavaScript is running.
  • cookie is an accessor property whose getter returns the cookie pairs available to that document.

The browser normally waits until the dialog is dismissed, although it may suppress the dialog or decline to wait in situations such as switching tabs. That makes alert useful for a quick demonstration and awkward for routine debugging.

The common description says this expression displays all cookies. It does not.

It displays only the cookies exposed to JavaScript for the current document. A cookie can exist in browser storage, appear in developer tools, and travel with an eligible HTTP request while remaining absent from document.cookie.

That distinction explains most surprising results.

Browser storagethememidnightsessionabc123HttpOnlyPagerulesandHttpOnlydocument.cookietheme=midnightblocked from scriptHTTP requestcan carry bothRequest rules form a separate route.
The browser exposes different cookie views to page code and network requests.

The broader Cookies and document.cookie guide covers how cookies are created and removed. Here the job is narrower: find out what the alert can see, why it cannot see the rest, and how to inspect one value without breaking it.

Where to Run the Expression

Run the expression in code belonging to a page you own, or in the DevTools Console while that authorized page is selected:

console.log(document.cookie);

The console is the dependable debugging context. It keeps the result in the log, does not interrupt the page with a modal dialog, and lets you confirm which document and frame currently receive the expression.

The same expression can appear inside a javascript: URL:

javascript:alert(document.cookie)

A javascript: URL asks the browser to evaluate JavaScript in the context of the current page if the browser permits that form of execution. Address-bar paste protections and browser behavior can interfere, so this form is a poor debugging procedure. It is also easy to run against the wrong page.

Use the console instead.

Whether the expression appears in a script, the console, or a permitted javascript: URL, it does not gain extra cookie access. It still runs with the current document’s authority and receives the same script-readable view.

Only inspect sites you own or have explicit authorization to test. Never paste JavaScript supplied by a stranger into a page containing a real account session. The developer console is powerful because it runs code as that page, which is also why untrusted snippets are dangerous.

If a page contains frames, select the intended frame in DevTools before testing. Code evaluated in an embedded document reads that document’s cookies, not whichever top-level page happens to surround it. Browser environment, specs introduces the objects that make up each browsing context.

Top documenttop.exampletheme=lightEmbeddeddocumentlogin.exampleflow=step21Selecting the iframemoves execution here.top cookie viewiframe cookie view
The selected frame determines which document receives the expression.

What document.cookie Returns and Omits

For a cookie-capable document with a non-opaque origin, reading document.cookie returns one string containing semicolon-separated name=value pairs. Access instead throws a SecurityError when the document has an opaque origin, as can occur in a sandboxed frame or some non-HTTP documents. A page might expose this string:

theme=midnight; display_name=Maya%20Chen; draft=chapter%3D4

The spaces after semicolons separate pairs for readability. They are why cookie parsing normally trims each part before matching a name.

The returned string contains names and values. It does not include attributes such as Domain, Path, Expires, HttpOnly, Secure, SameSite, or partition information. Developer tools can show those attributes because they inspect browser cookie storage rather than the restricted string presented to page JavaScript.

Think of cookie visibility as three related sets:

  • Stored cookies are records the browser currently holds, including their attributes.
  • JavaScript-readable cookies are stored cookies available to the current document after host or domain, path, scheme, partition, browser privacy policy, Storage Access, and HttpOnly restrictions are applied.
  • Request cookies are cookies the browser attaches when a particular HTTP request satisfies the relevant rules. This set can include HttpOnly cookies that JavaScript cannot read.
Stored cookies
├─ document host/path → secure connection → partition and Storage Access/privacy policy → HttpOnly gate → document.cookie
└─ request URL and context → cookie attributes and browser policy → Cookie header

These sets overlap, but they are not interchangeable. The URL of the document matters when JavaScript reads, while the destination and context of a request matter when the browser sends.

The visibility gates explain what reaches the getter:

  • The cookie’s host or Domain must cover the current host.
  • Its Path must match the current document path for cookie availability, although Path is not a security boundary against unauthorized reading.
  • A Secure cookie depends on a secure connection.
  • A partitioned cookie belongs to its matching partition context. Its partition key is typically the top-level site surrounding an embedded document.
  • Browser privacy policy may block unpartitioned third-party cookies in an embedded document unless it has Storage Access.
  • An HttpOnly cookie never reaches document.cookie.

SameSite answers a different question. It controls cross-site sending, while Secure controls transmission over secure connections and HttpOnly controls script access. One attribute does not substitute for another.

Three independent questionsHttpOnlyMay pagescript readthe value?NOSecureIs theconnectionsecure?SameSiteMay thiscross-siterequest send?script accesstransportrequest context
Cookie attributes answer separate access and delivery questions.

document.cookie also behaves differently when you assign to it. Reading invokes its native getter and returns several available pairs, but one assignment sets or updates only one cookie:

document.cookie = "theme=midnight; Path=/; SameSite=Lax";

The setter consumes one cookie plus its attributes. It does not replace the entire string returned by the getter, and a Domain that does not domain-match the current document host causes the assignment to be ignored. A parent domain may match, but an unrelated domain or public suffix does not.

Getter and setter share a property name. Their jobs are asymmetric.

Cookie recordstheme=darklang=enPage codeREADone stringWRITE onemany pairsone cookieSame property name, opposite-sized operations
The cookie getter collects many pairs; the setter writes one record.

An empty dialog means the getter returned an empty string, unless the browser suppressed the dialog itself. It does not prove that browser cookie storage is empty.

Use one fixed sequence so each check narrows the cause.

  1. Open the DevTools Console for the authorized page and run console.log(document.cookie). If the console shows a value but no alert appeared, dialog suppression was the problem.

  2. Confirm the selected document and frame. An embedded sign-in frame and its top-level page can have different hosts, paths, and partition contexts.

  3. Open the browser’s cookie storage panel. If no cookie exists for the relevant site, there is nothing for the getter to return.

  4. Check HttpOnly. A cookie marked HttpOnly can appear in DevTools and be attached to eligible requests, but JavaScript cannot read its value.

  5. Compare the cookie’s domain with the current document host. A cookie for an unrelated domain is unavailable, and JavaScript cannot create one by assigning a foreign Domain.

  6. Compare its Path with the current document path. A cookie scoped to /account may be unavailable while code runs at /articles/.

  7. Compare the page scheme with the Secure attribute. An HTTP page does not receive the same Secure-cookie behavior as an HTTPS page.

  8. Check partition information when the page is embedded. Compare the cookie’s Partition Key field in DevTools—typically the top-level site under which it was stored—with the current top-level site. A cookie stored in one partition context may not be available in another.

  9. Check whether the document is embedded cross-site and the browser is blocking access to unpartitioned third-party cookies. Where supported, inspect the browser’s cookie-blocking diagnostics and run await document.hasStorageAccess() in a module or an async console context to check Storage Access.

  10. Reload or repeat the action that creates the cookie, then inspect again. The application may not have set it, or it may have updated a cookie under a different scope.

Duplicate names make the storage panel especially useful. Cookies with the same name can have different domain or path information, but the getter returns only pairs and hides those attributes. A homemade string parser cannot reconstruct information the string never contained.

The Cookies Done Right: httpOnly, SameSite, Scope guide covers those server-set protections as one design rather than isolated flags.

Say the document exposes three pairs and one value contains two equals signs:

theme=midnight; demo_session=part=a=b; display_name=Maya%20Chen

This tempting parser loses data:

const [, value] = "demo_session=part=a=b".split("=");

console.log(value);
part

Splitting at every = creates four pieces. Destructuring takes only the second one, so =a=b disappears even though equals signs are permitted inside a cookie value.

demo_session=part=a=bSplit every equals signdemo_sessionpartabkept: partlost: =a=bCut once, after the full namenamedemo_sessionwhole valuepart=a=bseparator
Only the first equals sign separates a cookie name from its value.

Match the complete name and slice away its prefix instead. This helper accepts a cookie string explicitly, which also makes it testable outside the browser:

function readCookie(cookieString, name, options = {}) {
  const { decodeValue = false } = options;
  const prefix = `${name}=`;

  const pair = cookieString
    .split(";")
    .map((part) => part.trim())
    .find((part) => part.startsWith(prefix));

  if (pair === undefined) {
    return null;
  }

  const rawValue = pair.slice(prefix.length);

  if (!decodeValue) {
    return rawValue;
  }

  return decodeURIComponent(rawValue);
}

const cookies =
  "theme=midnight; demo_session=part=a=b; display_name=Maya%20Chen";

console.log(readCookie(cookies, "theme"));
console.log(readCookie(cookies, "demo_session"));
console.log(readCookie(cookies, "display_name", { decodeValue: true }));
console.log(readCookie(cookies, "missing"));
midnight
part=a=b
Maya Chen
null

The helper trims each semicolon-delimited pair, searches for the full name followed by =, and removes that exact prefix. Everything after the first name separator stays in the value.

Pass document.cookie when using it in a page:

const theme = readCookie(document.cookie, "theme");

console.log(theme);

There is no fixed output for that browser example because the cookie may be absent, in which case the helper returns null.

Decoding is opt-in. Use { decodeValue: true } only when the application encoded the stored value with a matching percent-encoding convention. decodeURIComponent() can throw for malformed percent escapes, so do not apply it blindly to every cookie from every system.

This helper deliberately does not choose between duplicate names by hidden attributes. Use DevTools or an API that exposes cookie records when domain and path distinctions matter.

Why This Expression Appears in XSS Examples

Cross-site scripting, or XSS, is a vulnerability that lets untrusted content execute as script within a site’s page. The injected code receives the authority of that page, so it can perform many actions that the site’s own JavaScript can perform.

That is why security demonstrations often use this line:

alert(document.cookie);

The alert makes script execution and cookie readability visible without sending the value anywhere. If a synthetic session identifier such as demo_session appears, the example shows that page JavaScript can read it. A real script-readable session identifier can be sensitive because possession of that value may carry account authority.

Do not turn the demonstration into transmission code. The defensive question is whether untrusted input can execute and which session data the page exposes to that execution.

HttpOnly changes the cookie-disclosure part. A cookie marked HttpOnly is absent from document.cookie, so injected JavaScript cannot read that cookie value through this property. The browser can still attach it to eligible fetch() or XMLHttpRequest requests because HttpOnly restricts disclosure to JavaScript, not normal cookie use.

HttpOnly limits cookie theft through script access, but it does not prevent XSS.

Injectedpage scriptSession cookieHttpOnlycookie valuenot disclosedVisible pagecan changeSite serversession still usedauthenticatedactionThe blocked branch is only one of several script capabilities.
HttpOnly blocks one XSS capability, not the injected script itself.

Injected code still runs. Depending on what the vulnerable page permits, it may read visible page data, change the interface, or make actions using the user’s existing session. Fixing the injection path remains necessary.

That gives two separate defensive jobs. Prevent untrusted data from becoming executable code, and keep authentication cookies out of script access when the application does not need JavaScript to read them. Web Security in Depth places XSS, cookie controls, and related browser defenses in the same model.

Better Ways to Inspect and Manage Cookies

In Chrome DevTools, open Application, expand Storage, and select Cookies. The table shows names, values, domains, paths, expiration, HttpOnly, Secure, SameSite, and partition information that document.cookie omits. For an embedded cookie, compare the Partition Key field—typically the top-level site under which it was stored—with the site shown in the top-level address bar.

One stored cookie recordDevTools can inspectName: sessionValue: abc123Domain: example.comPath: /accountSecure: yesHttpOnly: yesSameSite: LaxPartition keydocument.cookiename=valueonly if readableAttributes do not passthrough this opening.A string parser cannot recover fields it never received.
DevTools exposes cookie records; page JavaScript receives only available name-value pairs.

For routine page debugging, prefer:

console.log(document.cookie);

The result remains available beside nearby logs, and no modal dialog stops the page.

For application code, document.cookie is synchronous and may block the main thread while cookie data is accessed. The Cookie Store API provides asynchronous, promise-based operations in supporting secure contexts; this top-level await example must run as a module or another context that supports top-level await:

if ("cookieStore" in window) {
  const themeCookie = await cookieStore.get("theme");
  console.log(themeCookie?.value ?? null);
}

Current compatibility information marks the API as newly available and warns that older devices or browsers may not support it, so check project requirements and keep the feature test. It does not expose HttpOnly cookies.

Cookies sit among the browser’s document, storage, request, and security APIs. The Browser Platform follows those connections through the complete course when the individual rules start crossing page boundaries.

Frequently asked questions

What does alert(document.cookie) show?
It shows the semicolon-separated cookie pairs that JavaScript can read for the current document. It does not show HttpOnly cookies or cookies that fail the current domain, path, scheme, or partition checks.
Why is document.cookie empty when cookies exist?
The stored cookies may be HttpOnly or unavailable to the current document because of their domain, path, Secure, or partition settings. The code may also be running in a different frame from the one whose cookies you inspected.
Can JavaScript read an HttpOnly cookie?
Client-side JavaScript running in the page cannot read an HttpOnly cookie through document.cookie or Cookie Store, although the browser can still attach the cookie to eligible requests.
How do I get one cookie from document.cookie?
Split the string at semicolons, trim each pair, match the complete cookie name followed by an equals sign, and slice off that prefix. Do not split the pair at every equals sign because a cookie value may contain equals signs.