Extracts and decrypts cookies from a real Chrome profile's SQLite database.
Chrome 136+ (March 2025) intentionally broke all automation approaches that
rely on Chrome's own cookie access from subprocesses. The only proven solution
is to decrypt cookies ourselves from the OS credential store and inject them
into a Playwright BrowserContext via .addCookies.
Supports macOS, Linux, and Windows:
macOS:
Linux:
Windows:
All platforms:
sqlite3 CLIReferences:
Extracts and decrypts cookies from a real Chrome profile's SQLite database. Chrome 136+ (March 2025) intentionally broke all automation approaches that rely on Chrome's own cookie access from subprocesses. The only proven solution is to decrypt cookies ourselves from the OS credential store and inject them into a Playwright BrowserContext via `.addCookies`. Supports macOS, Linux, and Windows: macOS: 1. Read Chrome Safe Storage password from macOS Keychain 2. Derive AES-128 key via PBKDF2(password, "saltysalt", 1003 iterations) 3. Decrypt cookies with AES-CBC Linux: 1. Read password from GNOME Keyring (secret-tool) or fall back to "peanuts" 2. Derive AES-128 key via PBKDF2(password, "saltysalt", 1 iteration) 3. Decrypt cookies with AES-CBC (v10 uses "peanuts", v11 uses keyring key) Windows: 1. Read encrypted_key from Local State JSON 2. Base64-decode, strip DPAPI prefix, decrypt via PowerShell DPAPI 3. Decrypt cookies with AES-256-GCM (nonce from cookie, 128-bit auth tag) All platforms: - Copy the Cookies SQLite file (Chrome locks it) - Query all cookies via `sqlite3` CLI - Map to Playwright Cookie objects References: - chrome-cookies-secure (Node.js, 172★) - yt-dlp/cookies.py - browser_cookie3 - Chromium os_crypt: os_crypt_mac.mm, os_crypt_linux.cc, os_crypt_win.cc
(export-cookies-json profile-dir domain-filter)(export-cookies-json profile-dir domain-filter include-local-storage?)Decrypts cookies and reads localStorage from a Chrome profile, returning
a Playwright-compatible storage-state JSON string. The output can be saved
to a file and loaded with --storage-state on any platform — no Chrome
profile or OS keyring needed on the target machine.
This is the portable profile export: decrypt on macOS/Linux/Windows, use anywhere.
Params:
profile-dir - String. Path to Chrome profile directory.
domain-filter - String or nil. Only include cookies/localStorage
whose domain/origin contains this string.
include-local-storage? - Boolean (default true). When true, also exports
localStorage from the profile's LevelDB.
Returns: String — Playwright storage-state JSON: {"cookies": [...], "origins": [{"origin": "...", "localStorage": [...]}]}
Decrypts cookies and reads localStorage from a Chrome profile, returning
a Playwright-compatible storage-state JSON string. The output can be saved
to a file and loaded with `--storage-state` on any platform — no Chrome
profile or OS keyring needed on the target machine.
This is the portable profile export: decrypt on macOS/Linux/Windows, use
anywhere.
Params:
`profile-dir` - String. Path to Chrome profile directory.
`domain-filter` - String or nil. Only include cookies/localStorage
whose domain/origin contains this string.
`include-local-storage?` - Boolean (default true). When true, also exports
localStorage from the profile's LevelDB.
Returns:
String — Playwright storage-state JSON:
{"cookies": [...], "origins": [{"origin": "...", "localStorage": [...]}]}(extract-cookies profile-dir)Extracts and decrypts all cookies from a Chrome profile directory.
Cross-platform: works on macOS (Keychain), Linux (GNOME Keyring/peanuts), and Windows (DPAPI + AES-GCM).
Reads the OS-specific encryption key, copies the Cookies SQLite database,
decrypts all cookie values, and returns a java.util.List<Cookie> ready
for BrowserContext.addCookies.
Params:
profile-dir - String. Path to Chrome profile directory
(e.g. "~/Library/Application Support/Google/Chrome/Profile 1"
or "C:\Users\X\AppData\Local\Google\Chrome\User Data\Profile 1")
Returns: java.util.List<Cookie> — Playwright Cookie objects with decrypted values.
Throws: ex-info on credential access failure, missing Cookies DB, or sqlite3 errors.
Extracts and decrypts all cookies from a Chrome profile directory.
Cross-platform: works on macOS (Keychain), Linux (GNOME Keyring/peanuts),
and Windows (DPAPI + AES-GCM).
Reads the OS-specific encryption key, copies the Cookies SQLite database,
decrypts all cookie values, and returns a java.util.List<Cookie> ready
for `BrowserContext.addCookies`.
Params:
`profile-dir` - String. Path to Chrome profile directory
(e.g. "~/Library/Application Support/Google/Chrome/Profile 1"
or "C:\\Users\\X\\AppData\\Local\\Google\\Chrome\\User Data\\Profile 1")
Returns:
java.util.List<Cookie> — Playwright Cookie objects with decrypted values.
Throws:
ex-info on credential access failure, missing Cookies DB, or sqlite3 errors.(inject-cookies! context profile-dir)Extracts cookies from a Chrome profile and injects them into a Playwright BrowserContext. This is the main entry point for authenticated browsing.
Cross-platform: works on macOS (Keychain), Linux (GNOME Keyring/peanuts), and Windows (DPAPI + AES-GCM).
Params:
context - BrowserContext instance.
profile-dir - String. Path to Chrome profile directory.
Returns: Number of cookies injected.
Extracts cookies from a Chrome profile and injects them into a Playwright BrowserContext. This is the main entry point for authenticated browsing. Cross-platform: works on macOS (Keychain), Linux (GNOME Keyring/peanuts), and Windows (DPAPI + AES-GCM). Params: `context` - BrowserContext instance. `profile-dir` - String. Path to Chrome profile directory. Returns: Number of cookies injected.
(read-local-storage profile-dir)Reads localStorage data from a Chrome profile directory.
Parses the LevelDB database at <profile-dir>/Local Storage/leveldb/
and returns a map of origin to localStorage key-value pairs:
{"https://x.com" {"token" "abc123", "theme" "dark"}}
Only returns the LATEST live value for each key (highest sequence number wins). Deleted keys are excluded.
Params:
profile-dir - String. Path to Chrome profile directory.
Returns: Map of origin → {script-key → value}, or empty map if dir doesn't exist.
Reads localStorage data from a Chrome profile directory.
Parses the LevelDB database at `<profile-dir>/Local Storage/leveldb/`
and returns a map of origin to localStorage key-value pairs:
{"https://x.com" {"token" "abc123", "theme" "dark"}}
Only returns the LATEST live value for each key (highest sequence number
wins). Deleted keys are excluded.
Params:
`profile-dir` - String. Path to Chrome profile directory.
Returns:
Map of origin → {script-key → value}, or empty map if dir doesn't exist.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |