Sweet Cookie is a TypeScript library, CLI, and Chrome exporter for turning an approved cookie
source into an HTTP Cookie: header or a browser-compatible JSON artifact. Inline payloads work on
every supported platform. Local Chrome, Edge, Firefox, and Safari reads use built-in Node.js or Bun
SQLite support, so the package does not add a native Node addon.
The target URL, extra origins, cookie-name allowlist, source order, profile, and output format stay explicit. Non-fatal source problems appear as warnings without raw cookie values.
Distribution boundary: Upstream
@steipete/sweet-cookie0.4.3 and later include the host-only, partitioned-cookie, and isolation fixes this fork carries. New projects can install upstream from npm. This repository does not publish the Hraness fork to npm, and its Git tag v0.4.4 is a different artifact from npm 0.4.4.
Install the exact Hraness Git source release. Node.js 22 or newer is required.
npm install github:hraness/sweet-cookie#v0.4.4Then prove the filter and output contract with an inline payload. This command does not read a browser database, invoke an operating-system credential helper, or make a network request.
$ ./node_modules/.bin/sweet-cookie example.com --inline-json \
'[{"name":"session","value":"demo","domain":"example.com","path":"/"}]' --format header
Cookie: session=demoInline JSON, base64, and file inputs run first. The first inline source that yields cookies returns before any local browser backend runs.
| Interface | Use it when | Observable result |
|---|---|---|
| CLI | A local process needs a Cookie: header or JSON artifact |
Cookie output on stdout and bounded warnings on stderr |
| TypeScript library | An application needs cookie objects, source control, and warnings in process | { cookies, warnings } plus toCookieHeader() |
| Chrome exporter | App-Bound Encryption, a remote runtime, or another browser boundary prevents a database read | User-triggered JSON, base64, or file output from the current Chrome profile |
The operator chooses the source, origin scope, cookie names, profile, and destination. Sweet Cookie does not discover a broader authorization scope, send the output, drive a browser, or decide which service should receive a credential.
A bare domain becomes an HTTPS URL. Add --origin for a known OAuth or multi-domain flow, and
repeat --name to keep the exported credential set narrow.
./node_modules/.bin/sweet-cookie app.example.com \
--origin https://accounts.example.com \
--name session --name csrf \
--browser chrome \
--format headerProfile selectors accept a display name, profile directory, or cookie database path. Use
ALL_PROFILES through the library when every discovered profile is an intentional input.
./node_modules/.bin/sweet-cookie example.com \
--browser chrome \
--chrome-profile "Work" \
--format jsonThe JSON contains complete cookie values. Create it with private permissions, pass it through a bounded local channel, and delete it when the receiving task is complete.
(
umask 077
./node_modules/.bin/sweet-cookie app.example.com \
--name session --format json > ./sweet-cookie.cookies.json
)The CLI prints provider warnings to stderr. --debug adds provider diagnostics, but warnings never
contain raw cookie values.
import { getCookies, toCookieHeader } from "@steipete/sweet-cookie";
const { cookies, warnings } = await getCookies({
url: "https://app.example.com/",
origins: ["https://accounts.example.com/"],
names: ["session", "csrf"],
browsers: ["chrome", "firefox"],
});
for (const warning of warnings) console.warn(warning);
const header = toCookieHeader(cookies, { dedupeByName: true });getCookies() returns browser-compatible cookie objects with source metadata. toCookieHeader()
sorts valid name/value pairs and can retain the first value for each name.
urlis required and includes a protocol. Set the target URL before selecting any source.originsadds extra origins; omit it when the target alone is enough. Add only origins approved for the same handoff.nameslimits the result to a nonempty allowlist. Omitted names,[], and lists containing only empty or whitespace entries mean no name filter. Reject or short-circuit an empty computed allowlist before callinggetCookies()if your task requires specific names.browsersselects the browser-provider order, not inline handoffs. Inline JSON, base64, and file sources are tried first; the first inline source returning cookies ends the read. Without a browser override, the default is Chrome, Safari, then Firefox, configurable through the environment.includeExpireddefaults tofalsefor browser providers. It does not filter expiry in inline JSON, base64, or file handoffs, even when explicitlyfalse; check expiry in the caller before using those cookies. Include expired browser cookies only when your task requires them.
See the usage reference for profile selection, merge behavior, and environment overrides. A returned cookie is a credential, not permission to use it against an unrelated service.
The Manifest V3 extension in apps/extension reads only the current Chrome
profile. The popup starts with the active tab URL, accepts explicit extra origins and a cookie-name
allowlist, then requests host permission when you select an export action.
It makes no network requests and stores only the extra-origin and allowlist settings. Its preview shows names, counts, and domains with every value fully masked. Clipboard and downloaded outputs contain complete cookie values and must be handled as credentials.
Pass an exported file back through the inline path:
const { cookies, warnings } = await getCookies({
url: "https://app.example.com/",
inlineCookiesFile: "/private/path/sweet-cookie.cookies.json",
});| Boundary | Current behavior |
|---|---|
| Inline input | JSON, base64, then file. The first non-empty inline result wins and skips local browsers. |
| Local browser databases | Chromium and Firefox databases are copied to a temporary snapshot before SQLite queries. Safari binary cookies are parsed directly. |
| Credential helpers | macOS Keychain, Windows DPAPI, and Linux keyring helpers run locally with bounded timeouts. |
| Extension permission | Chrome host access is requested for the entered origins only after an export action. The extension cannot read another Chrome profile. |
| Extension storage | Only extra-origin and allowlist settings persist. Exported cookie values do not. |
| Output | CLI stdout, clipboard content, and downloaded JSON contain live credential values. Sweet Cookie does not transmit or retain them for you. |
| Isolation | Partitioned Chromium cookies and partitioned or container-scoped Firefox cookies are excluded because ordinary replay cannot preserve their isolation context. |
| Source | macOS | Windows | Linux |
|---|---|---|---|
| Inline payload | Yes | Yes | Yes |
| Chrome / Chromium | Yes | Yes | Yes |
| Edge | Yes | Yes | Yes |
| Firefox | Yes | Yes | Yes |
| Safari | Yes | No | No |
Without an inline result, local backends run in the declared order. The default is Chrome, Safari,
then Firefox. mode: "merge" combines results. mode: "first" stops after the first backend that
returns cookies. Host-only and domain cookies remain distinct during filtering and deduplication.
No. The library, CLI, and extension contain no cookie transport. The caller chooses what receives stdout, an in-process return value, clipboard content, or a downloaded file.
A missing profile, inaccessible database, or undecryptable cookie does not always invalidate other sources. Sweet Cookie returns readable cookies and bounded warnings. Raw values are excluded from warnings.
The output shape cannot preserve their isolation context. Sweet Cookie excludes them instead of turning a context-bound cookie into an ordinary replayable credential.
Use it when the current Chrome profile can access cookies that a local database reader cannot, such as some Windows App-Bound Encryption cases. It remains a user-triggered current-profile export, not a cross-profile or background extractor.
- Usage, API, environment, and CLI reference
- Cookie extraction and extension specification
- Package API types
- Git source release procedure
Repository development requires Node.js 22.13 or newer and pnpm 11.18.
pnpm install --frozen-lockfile
pnpm check
pnpm build
pnpm test
pnpm test:bunMIT. See packages/core/LICENSE.