Skip to content

Add support for setting and getting cookies#1681

Open
tkattkat wants to merge 5 commits intomainfrom
Add-support-for-setting-and-getting-cookies
Open

Add support for setting and getting cookies#1681
tkattkat wants to merge 5 commits intomainfrom
Add-support-for-setting-and-getting-cookies

Conversation

@tkattkat
Copy link
Collaborator

@tkattkat tkattkat commented Feb 11, 2026

Why

Browser automation workflows frequently need to manage authentication state, persist sessions across runs, and handle cookie-based features. Currently, users have no direct API to read, write, or clear cookies in Stagehand, forcing workarounds through raw CDP commands or page-level JavaScript injection.

What Changed

Cookie Management APIs

Added cookie management methods that mirror the familiar Playwright BrowserContext API:

On context instance:

  • context.cookies(urls?) — Get all browser cookies, optionally filtered by URL(s)
  • context.addCookies(cookies) — Set one or more cookies in the browser context
  • context.clearCookies(options?) — Clear all cookies or selectively by name/domain/path (supports RegExp)

Types Added

  • Cookie — Cookie object returned by the browser
  • CookieParam — Parameters for setting a cookie (supports url OR domain+path)
  • ClearCookieOptions — Filter options for selective cookie clearing

Test Plan

Cookie Management

  • context.cookies() returns all cookies when no URLs provided
  • context.cookies(url) filters cookies by single URL
  • context.cookies([url1, url2]) filters cookies by multiple URLs
  • context.addCookies([...]) successfully sets cookies
  • context.addCookies() validates cookie params (requires url OR domain+path)
  • context.addCookies() rejects sameSite: "None" without secure: true
  • context.addCookies() throws on browser rejection (checks CDP success flag)
  • context.clearCookies() clears all cookies atomically via single CDP call
  • context.clearCookies({ name: "session" }) clears by exact name
  • context.clearCookies({ domain: /\.example\.com/ }) clears by regex
  • Selective clear only deletes matching cookies, leaves others untouched

@changeset-bot
Copy link

changeset-bot bot commented Feb 11, 2026

🦋 Changeset detected

Latest commit: aa4b462

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@browserbasehq/stagehand Patch
@browserbasehq/stagehand-evals Patch
@browserbasehq/stagehand-server Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 11, 2026

Greptile Overview

Greptile Summary

Added comprehensive cookie management APIs mirroring Playwright's interface, enabling users to get, set, clear, and persist cookies across browser sessions.

Key changes:

  • Added cookies(), addCookies(), and clearCookies() methods to the Stagehand class
  • Added storageState() and setStorageState() methods to V3Context for cookie persistence
  • Implemented robust validation including sameSite: "None" with secure: true enforcement
  • Improved upon Playwright's clearCookies() by using selective deletion instead of nuke-and-re-add pattern
  • Automatically filters expired cookies when restoring storage state
  • Comprehensive test coverage with 100+ test cases

Implementation quality:

  • Well-structured helper functions with clear separation of concerns
  • Thorough error handling with descriptive messages including cookie names
  • Edge cases handled correctly (localhost secure cookies, domain matching, path prefixes)
  • Type-safe with proper TypeScript interfaces exported

Confidence Score: 5/5

  • This PR is safe to merge with high confidence
  • The implementation is production-ready with excellent code quality: comprehensive test coverage (100+ test cases), robust validation and error handling, proper TypeScript types, and improvements over Playwright's approach. The code follows best practices with clear separation of concerns and handles all edge cases correctly.
  • No files require special attention

Important Files Changed

Filename Overview
packages/core/lib/v3/understudy/cookies.ts New file implementing cookie types and helper functions with comprehensive validation and filtering logic
packages/core/lib/v3/understudy/context.ts Adds five cookie management methods to V3Context: cookies(), addCookies(), clearCookies(), storageState(), and setStorageState()
packages/core/lib/v3/v3.ts Adds three cookie management proxy methods to Stagehand class delegating to context: cookies(), addCookies(), clearCookies()
packages/core/tests/cookies.test.ts Comprehensive test suite covering all cookie helper functions and V3Context methods with 100+ test cases

Sequence Diagram

sequenceDiagram
    participant User
    participant Stagehand
    participant V3Context
    participant CDP as Chrome DevTools Protocol

    Note over User,CDP: Getting Cookies
    User->>Stagehand: cookies(urls?)
    Stagehand->>V3Context: cookies(urls?)
    V3Context->>CDP: Network.getAllCookies
    CDP-->>V3Context: {cookies: Cookie[]}
    V3Context->>V3Context: filterCookies(cookies, urls)
    V3Context-->>Stagehand: Cookie[]
    Stagehand-->>User: Cookie[]

    Note over User,CDP: Adding Cookies
    User->>Stagehand: addCookies(cookies)
    Stagehand->>V3Context: addCookies(cookies)
    V3Context->>V3Context: normalizeCookieParams(cookies)
    loop for each cookie
        V3Context->>CDP: Network.setCookie(cookie)
        CDP-->>V3Context: {success: boolean}
        alt success === false
            V3Context-->>User: throw Error
        end
    end
    V3Context-->>Stagehand: void
    Stagehand-->>User: void

    Note over User,CDP: Clearing Cookies
    User->>Stagehand: clearCookies(options?)
    Stagehand->>V3Context: clearCookies(options?)
    V3Context->>CDP: Network.getAllCookies
    CDP-->>V3Context: {cookies: Cookie[]}
    V3Context->>V3Context: filter matching cookies
    loop for each matching cookie
        V3Context->>CDP: Network.deleteCookies(cookie)
        CDP-->>V3Context: {}
    end
    V3Context-->>Stagehand: void
    Stagehand-->>User: void

    Note over User,CDP: Storage State (Snapshot & Restore)
    User->>V3Context: storageState()
    V3Context->>CDP: Network.getAllCookies
    CDP-->>V3Context: {cookies: Cookie[]}
    V3Context-->>User: {cookies: Cookie[]}
    
    User->>V3Context: setStorageState(state)
    V3Context->>V3Context: clearCookies()
    V3Context->>V3Context: filter expired cookies
    V3Context->>V3Context: addCookies(validCookies)
    V3Context-->>User: void
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 8 files

Confidence score: 3/5

  • The cookie validation in packages/core/lib/v3/understudy/cookies.ts misses the secure undefined case, which can allow sameSite: "None" cookies without secure to slip through and behave unexpectedly for users.
  • The cookie clearing flow in packages/core/lib/v3/understudy/context.ts is O(N) roundtrips with a race window; this can leave cookies behind or impact performance when no filter is provided.
  • These are medium-severity, user-impacting behaviors, so there’s some risk despite the changes being localized.
  • Pay close attention to packages/core/lib/v3/understudy/cookies.ts and packages/core/lib/v3/understudy/context.ts - cookie validation and clearing behavior.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/core/lib/v3/understudy/cookies.ts">

<violation number="1" location="packages/core/lib/v3/understudy/cookies.ts:123">
P1: Bug: `copy.secure === false` misses the `undefined` case. When a user sets `sameSite: "None"` with `domain`+`path` but omits `secure`, this validation is skipped because `undefined === false` is `false`. Use `!copy.secure` to also catch `undefined`, matching the stated intent of preventing silent CDP failures.</violation>
</file>

<file name="packages/core/lib/v3/understudy/context.ts">

<violation number="1" location="packages/core/lib/v3/understudy/context.ts:892">
P2: When no filter is provided, use `Network.clearBrowserCookies` instead of fetching all cookies and deleting them one by one. The current approach makes O(N) CDP roundtrips and still has a race condition (cookies set between the fetch and the deletion loop will be missed). `Network.clearBrowserCookies` is a single atomic CDP call.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant User
    participant V3 as Stagehand (V3)
    participant Ctx as V3Context
    participant Util as Cookie Utils
    participant Browser as Browser (CDP)

    Note over User, Browser: Cookie Management Flow

    User->>V3: NEW: addCookies(cookies)
    V3->>Ctx: addCookies(cookies)
    Ctx->>Util: NEW: normalizeCookieParams()
    Note right of Util: Validates url OR domain/path<br/>Enforces sameSite=None + secure
    Util-->>Ctx: Normalized CookieParams
    loop Each Cookie
        Ctx->>Browser: Network.setCookie
        Browser-->>Ctx: { success: boolean }
        alt NEW: Browser rejected cookie
            Ctx-->>User: Throw Error (Explicit failure)
        end
    end
    Ctx-->>User: Done

    User->>V3: NEW: cookies(urls?)
    V3->>Ctx: cookies(urls)
    Ctx->>Browser: Network.getAllCookies
    Browser-->>Ctx: Protocol.Network.Cookie[]
    Ctx->>Util: NEW: filterCookies(cookies, urls)
    Note right of Util: Matches domain, path, and<br/>secure protocol requirements
    Util-->>Ctx: Filtered Cookie[]
    Ctx-->>User: Cookie[]

    User->>V3: NEW: clearCookies(options?)
    V3->>Ctx: clearCookies(options)
    Ctx->>Ctx: cookies()
    alt Selective Clear (options provided)
        loop Each Cookie
            Ctx->>Util: NEW: cookieMatchesFilter(cookie, options)
            Util-->>Ctx: boolean
            opt Match Found
                Ctx->>Browser: CHANGED: Network.deleteCookies
            end
        end
    else Clear All
        Ctx->>Browser: Network.deleteCookies (All)
    end
    Ctx-->>User: Done

    Note over User, Browser: Storage Persistence Flow

    User->>Ctx: NEW: storageState()
    Ctx->>Ctx: cookies()
    Ctx-->>User: { cookies: Cookie[] }

    User->>Ctx: NEW: setStorageState(state)
    Ctx->>Ctx: clearCookies()
    Ctx->>Util: Filter expired cookies
    Ctx->>Ctx: addCookies(validCookies)
    Ctx-->>User: Context Restored
Loading

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants