Core Concepts
HttpOnly vs Client-Side Storage
Cookies marked HttpOnly cannot be accessed or modified by client-side JavaScript (cookieStore or document.cookie). However, the browser automatically attaches active HttpOnly cookies to outgoing HTTP request headers (Cookie).
- To inspect current
HttpOnlyvalues: Look at theCookierequest header of any outgoing HTTP request viaget_network_request. - To inspect how cookies were created or configured: Look at the
Set-Cookieresponse header of login/auth responses. - To inspect non-
HttpOnlycookies: Useevaluate_scriptwith the moderncookieStoreAPI (async () => await cookieStore.getAll()).
Session Strategy: Live Tab vs Isolated Context
Choose the right session environment to avoid state contamination (e.g., residual analytics or auth tokens):
Client-Side Capabilities & Limitations
[!WARNING] Attempting to clear an
HttpOnlycookie via JavaScript (cookieStore.deleteordocument.cookie = "...; max-age=0") will silently fail. To test in an unauthenticated or fresh state, always spawn a new isolated context usingnew_pagewithisolatedContext.
Workflow Patterns
1. Diagnosing Authentication Failures & Redirects (401 / 403)
When an authenticated page request fails, returns 401/403, or redirects to login:
- List Recent Requests: Call
list_network_requestswithincludePreservedRequests: true. - Find the Target Request: Locate the failing request (401/403) or redirect (302/307).
- Inspect Outgoing
CookieHeader: Callget_network_requestwith thereqid.- Verify if the
Cookieheader was attached and whether required tokens (e.g.SESSION_ID,auth_token) were sent.
- Verify if the
- Trigger Active Inspection (If no recent request exists):
- If the cookie was set in a previous session and no network call is listed, trigger a request:
- Use
navigate_pagewithreload: true, OR - Call
evaluate_scriptwith() => fetch(window.location.href)
- Use
- Then call
get_network_requeston the new request to inspect the activeCookieheader.
- If the cookie was set in a previous session and no network call is listed, trigger a request:
- Trace the Setting Request: If the cookie is missing or rejected:
- Check earlier login/handshake responses for
Set-Cookiedirectives:- Path mismatch: e.g.,
Path=/apiwhen the request is to/. - Domain mismatch: e.g.,
Domain=api.example.compreventing cookies onsub.example.com. - Secure flag on HTTP:
Securecookies are never sent over unencryptedhttp://. - SameSite blocking:
SameSite=Strictcookies are omitted on cross-site navigations. - Expiration: Check if
ExpiresorMax-Ageelapsed.
- Path mismatch: e.g.,
- Check earlier login/handshake responses for
2. Cookie Banner & Consent Conformance Testing
To verify that no non-essential or tracking cookies are set before consent or when declining:
- Start Clean: Open a fresh isolated context with a dedicated name:
- Record Baseline Cookies: Before interacting with the banner, run
evaluate_scriptwithasync () => await cookieStore.getAll(). - Inspect Premature Network Requests & Issues:
- Call
list_network_requeststo ensure no third-party tracking beacons fired before consent. - Call
list_console_messageswithtypes: ["issue"]to check for tracking warnings.
- Call
- Interact with Consent Banner:
- Capture snapshot with
take_snapshotto locate the "Decline" or "Reject All" buttonuid. - Click the button with
click.
- Capture snapshot with
- Verify Cookie Difference:
- Run
evaluate_scriptwithasync () => await cookieStore.getAll()after clicking to assert that only strictly necessary or consent-state cookies exist.
- Run
- Test Consent Revocation (Lifecycle Audit):
- When auditing consent withdrawal or preference changes:
- Locate and click the "Cookie Settings", "Manage Preferences", or footer privacy trigger (
take_snapshot$\rightarrow$click). - Deselect non-essential categories or click "Revoke All" / "Save Preferences".
- Re-query
cookieStore.getAll()to verify previously accepted non-essential cookies were cleared or expired. - Call
list_network_requestson subsequent actions to ensure tracking beacons are no longer fired.
- Locate and click the "Cookie Settings", "Manage Preferences", or footer privacy trigger (
- When auditing consent withdrawal or preference changes:
- Teardown Context: Call
close_pagewhen the audit is complete to prevent leftover cookies from affecting subsequent tasks.
3. Auditing Cookie Security, SameSite & CHIPS (Partitioned Cookies)
- Fast-Track: Native DevTools Issues (Recommended):
- Call
list_console_messageswith: - Check for
CookieIssueentries, such as:SameSiteNoneInsecure:SameSite=NonewithoutSecure.ThirdPartyCookiePhaseout: Third-party cookie blocked or restricted.SchemefulSameSite: Cross-scheme cookie issues.PartitionedCookies: Invalid CHIPS partitioning attributes.
- Call
- Deep Audit: Lighthouse Third-Party Cookies:
- Run
lighthouse_auditwithmode: "navigation"andoutputDirPath: "/tmp/lh-report". - Extract the specific cookie audit without loading the full report into context:
- Run
4. Client-Side Cookie Inspection & Manipulation
For client-accessible, non-HttpOnly cookies (e.g., UI preferences, non-sensitive feature flags):
- Read Cookies & Attributes:
- Use the modern asynchronous Cookie Store API:
- Fallback for insecure HTTP origins:
() => document.cookie.
- Set / Modify Cookie:
- Set client cookie via
cookieStore:
- Set client cookie via
- Delete Cookie:
- Clear client cookie:
Troubleshooting
cookieStoreis undefined:cookieStorerequires a Secure Context (https://,localhost, or127.0.0.1). On non-secure HTTP origins, use() => document.cookieor test over HTTPS.evaluate_scriptreturns empty / unresolved Promise:cookieStoremethods are asynchronous. Always wrap calls withasync () => await cookieStore.getAll().- Cookie not visible in JavaScript: The cookie is marked
HttpOnly. Trigger a network request and callget_network_requestto view it in theCookierequest header. - JavaScript deletion did not remove cookie: The cookie is
HttpOnlyor requires matchingPathandDomainparameters. Use a freshisolatedContextwithnew_pagefor a clean slate. - Cookie set in response but not sent in requests:
- Verify if page is
http://while cookie specifiesSecure. - Check if
Domainrestricts subdomains. - Check
list_console_messages(types: ["issue"])for browser rejection reasons.
- Verify if page is
- Residual cookies contaminating audits: Always use
new_pagewith a uniqueisolatedContextwhen running compliance tests, and callclose_pagewhen done.




