harn fetch
harn fetch [options] <url>An HTTP request that writes the response body to stdout and speaks to the shared cookie jar. By default it attaches any matching cookies from ~/.cache/harnery/cookies.json to the request and persists Set-Cookie responses back (the same jar harn browse and harn cookies use). harn fetch never opens the browser profile, so a sign-in reaches it through the jar: when a harn browse --login window closes, the sign-in site’s cookies (its registrable domain and subdomains, nothing else) are read out of the profile and merged into the jar, and later harn fetch calls to that site are signed in (details). Cookies harn fetch receives flow back to later harn browse runs the same way. Hosts that compose Harnery can also inject cookies through HarneryProgramContext.extraCookies (applied before the Cookie header is built; skipped with --no-cookies). Pipe it into harn read for the canonical scrape-to-markdown flow: harn fetch <url> | harn read -.
Options
Section titled “Options”| Flag | Description |
|---|---|
-X, --method <method> |
HTTP method. Default GET. |
-H, --header <header...> |
Extra request header, format Name: value. Repeatable. |
-d, --data <body> |
Request body. |
-o, --output <file> |
Write the response body to a file instead of stdout. |
--store <path> |
Cookie store path. Default ~/.cache/harnery/cookies.json. |
--no-cookies |
Skip cookie-jar attach and persist (clean session). Also skips a host extraCookies hook. |
--no-pace |
Skip the human-pace gap between requests to the same site for this run. See Human pace. |
--redirect <mode> |
Redirect handling: follow | error | manual. Default follow. |
--timeout <ms> |
Request timeout in milliseconds. Default 30000. |
--status |
Print the status line to stderr. |
--headers |
Print response headers to stderr. |
--json |
Output the full FetchResult (status, headers, body) as JSON. |
Requests are paced like every other Harnery page load: consecutive requests to the same site wait a random 3 to 9 seconds, shared across processes through ~/.cache/harnery/pace.json, with local and private hosts exempt. --no-pace skips it for one run and HARNERY_PACE=off disables it machine-wide. The full set of controls is in Human pace.
Header policy
Section titled “Header policy”A host that composes Harnery can check every -H header through HarneryProgramContext.headerPolicy(host, name, value) before the request is sent. A refusal ends the run with the host’s message and a nonzero exit, and no flag overrides it. Only your -H headers are checked; the default User-Agent and headers the host adds through extraHeaders are not. harn on its own installs no policy.
Redirects
Section titled “Redirects”With the default --redirect follow, Harnery follows redirects itself rather than leaving them to the runtime, with or without the cookie jar. Each hop gets the jar cookies for its own host, the host’s extraHeaders for its own URL, and its own Set-Cookie persistence.
A redirect within the same origin keeps every header you passed. A redirect to a different origin keeps only User-Agent, Accept, Accept-Language, and Range; every other -H header, including Authorization, Cookie, API keys, and custom X-* headers, is dropped for the rest of the chain. A 303, or a 301 or 302 on a request other than GET or HEAD, continues as a GET without the body. A 307 or 308 to a different origin on a request other than GET or HEAD stops with an error instead of resending the body; request the new URL directly if that is what you want.
Output
Section titled “Output”The body goes to stdout by default. With --output, Harnery writes the HTTP representation bytes exactly as received, before content decoding, regardless of the file extension or Content-Type. Byte-mode requests ask the server for identity encoding and do not automatically decompress a response that still carries Content-Encoding, so --headers continues to describe the saved file. The Bun runtime supports this directly. The Node fallback fails instead of saving altered bytes if a server ignores the identity request and returns content-encoded data. Stdout and --json decode the body as UTF-8 text, so use --output for binary files and text in another encoding. --json emits the whole FetchResult ({ status, statusText, url, headers, body, cookiesSaved }) as a single JSON object. When cookies are saved back to the jar, a note is logged to stderr.
Examples
Section titled “Examples”# GET a page (cookies auto-attached and persisted)harn fetch https://example.com
# The canonical scrape-to-markdown pipelineharn fetch https://example.com | harn read -
# POST JSON with explicit headersharn fetch https://example.com/api -X POST -H 'Content-Type: application/json' -d '{"k":"v"}'
# Inspect a redirect response without following itharn fetch https://example.com/login --redirect manual --headers
# Clean session, full result as JSONharn fetch https://example.com --no-cookies --json
# Save a binary response to a fileharn fetch https://example.com/image.png -o /path/to/image.png