← back to Cli Printing Press
fix(cli): default cookie HTML scrapes to browser transport (#822)
7a1d83ad26f96b81e877831f0a43000eaa37a85c · 2026-05-09 11:35:11 -0700 · Trevin Chow
Files touched
M internal/generator/generator_test.goM internal/spec/spec.goM internal/spec/spec_test.goM skills/printing-press/SKILL.md
Diff
commit 7a1d83ad26f96b81e877831f0a43000eaa37a85c
Author: Trevin Chow <trevin@trevinchow.com>
Date: Sat May 9 11:35:11 2026 -0700
fix(cli): default cookie HTML scrapes to browser transport (#822)
---
internal/generator/generator_test.go | 42 ++++++++++++++++++++++++++++++++++++
internal/spec/spec.go | 12 +++++++++++
internal/spec/spec_test.go | 25 +++++++++++++++++++++
skills/printing-press/SKILL.md | 15 +++++++++++++
4 files changed, 94 insertions(+)
diff --git a/internal/generator/generator_test.go b/internal/generator/generator_test.go
index ecd16e7e..2a1e87d8 100644
--- a/internal/generator/generator_test.go
+++ b/internal/generator/generator_test.go
@@ -1421,6 +1421,48 @@ func TestGenerateBrowserHTTPTransportDisablesHTTP2(t *testing.T) {
assert.NotContains(t, gomod, "github.com/enetx/surf")
}
+func TestGenerateCookieHTMLDefaultsBrowserChromeTransport(t *testing.T) {
+ t.Parallel()
+
+ apiSpec := minimalSpec("cookiehtml")
+ apiSpec.BaseURL = "https://www.example.com"
+ apiSpec.Auth = spec.AuthConfig{
+ Type: "cookie",
+ Header: "Cookie",
+ In: "cookie",
+ CookieDomain: ".example.com",
+ EnvVars: []string{"COOKIEHTML_COOKIES"},
+ }
+ apiSpec.Resources = map[string]spec.Resource{
+ "diary": {
+ Description: "Read diary pages",
+ Endpoints: map[string]spec.Endpoint{
+ "get_day": {
+ Method: "GET",
+ Path: "/food/diary",
+ Description: "Read a diary page",
+ ResponseFormat: spec.ResponseFormatHTML,
+ HTMLExtract: &spec.HTMLExtract{
+ Mode: spec.HTMLExtractModePage,
+ },
+ },
+ },
+ },
+ }
+
+ outputDir := filepath.Join(t.TempDir(), "cookiehtml-pp-cli")
+ require.NoError(t, New(apiSpec, outputDir).Generate())
+
+ gomod := readGeneratedFile(t, outputDir, "go.mod")
+ assert.Contains(t, gomod, "github.com/enetx/surf")
+
+ clientGo := readGeneratedFile(t, outputDir, "internal", "client", "client.go")
+ assert.Contains(t, clientGo, `"github.com/enetx/surf"`)
+ assert.Contains(t, clientGo, "Impersonate()")
+ assert.Contains(t, clientGo, "Chrome()")
+ assert.NotContains(t, clientGo, `req.Header.Set("User-Agent", "cookiehtml-pp-cli/0.1.0")`)
+}
+
func TestGenerateHTMLExtractionEndpoint(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
diff --git a/internal/spec/spec.go b/internal/spec/spec.go
index f7160c0e..6745d439 100644
--- a/internal/spec/spec.go
+++ b/internal/spec/spec.go
@@ -297,6 +297,9 @@ func (s *APISpec) EffectiveHTTPTransport() string {
case HTTPTransportStandard, HTTPTransportBrowserHTTP, HTTPTransportBrowserChrome, HTTPTransportBrowserChromeH3:
return s.HTTPTransport
}
+ if s.usesBrowserAuthForHTML() {
+ return HTTPTransportBrowserChrome
+ }
switch s.SpecSource {
case "community", "sniffed":
return HTTPTransportBrowserChrome
@@ -305,6 +308,15 @@ func (s *APISpec) EffectiveHTTPTransport() string {
}
}
+func (s *APISpec) usesBrowserAuthForHTML() bool {
+ switch strings.ToLower(strings.TrimSpace(s.Auth.Type)) {
+ case "cookie", "composed":
+ return s.HasHTMLExtraction()
+ default:
+ return false
+ }
+}
+
func (s *APISpec) UsesBrowserHTTPTransport() bool {
switch s.EffectiveHTTPTransport() {
case HTTPTransportBrowserChrome, HTTPTransportBrowserChromeH3:
diff --git a/internal/spec/spec_test.go b/internal/spec/spec_test.go
index 0a724dca..cd3daba6 100644
--- a/internal/spec/spec_test.go
+++ b/internal/spec/spec_test.go
@@ -2479,6 +2479,31 @@ func TestHTTPTransportValidationAndDefaults(t *testing.T) {
assert.Equal(t, HTTPTransportStandard, override.EffectiveHTTPTransport())
require.NoError(t, override.Validate())
+ cookieHTML := base
+ cookieHTML.Auth.Type = "cookie"
+ cookieHTML.Resources = map[string]Resource{
+ "pages": {
+ Endpoints: map[string]Endpoint{
+ "show": {Method: "GET", Path: "/page", ResponseFormat: ResponseFormatHTML},
+ },
+ },
+ }
+ assert.Equal(t, HTTPTransportBrowserChrome, cookieHTML.EffectiveHTTPTransport())
+
+ composedHTML := cookieHTML
+ composedHTML.Auth.Type = "composed"
+ assert.Equal(t, HTTPTransportBrowserChrome, composedHTML.EffectiveHTTPTransport())
+
+ jsonCookie := cookieHTML
+ jsonCookie.Resources = map[string]Resource{
+ "items": {Endpoints: map[string]Endpoint{"list": {Method: "GET", Path: "/items"}}},
+ }
+ assert.Equal(t, HTTPTransportStandard, jsonCookie.EffectiveHTTPTransport())
+
+ cookieHTMLOverride := cookieHTML
+ cookieHTMLOverride.HTTPTransport = HTTPTransportStandard
+ assert.Equal(t, HTTPTransportStandard, cookieHTMLOverride.EffectiveHTTPTransport())
+
runtime := base
runtime.HTTPTransport = "browser-runtime"
assert.Equal(t, HTTPTransportStandard, runtime.EffectiveHTTPTransport())
diff --git a/skills/printing-press/SKILL.md b/skills/printing-press/SKILL.md
index 193f5edf..705779d4 100644
--- a/skills/printing-press/SKILL.md
+++ b/skills/printing-press/SKILL.md
@@ -1731,6 +1731,21 @@ resources:
# no_auth defaults to false — placing an order needs auth
```
+#### Cookie/composed HTML transport
+
+For specs with `auth.type: cookie` or `auth.type: composed` and any
+`response_format: html` endpoint, treat browser fingerprint compatibility as
+the safe default. The generator emits Surf-backed Chrome transport for that
+shape unless the spec explicitly says `http_transport: standard`.
+
+Before setting an explicit standard opt-out, run
+`printing-press probe-reachability` against a representative HTML GET endpoint.
+If the probe returns `standard_http`, record `http_transport: standard` in the
+spec. If it returns `browser_http`, leave the default or set `http_transport:
+browser-chrome`. If it returns `browser_clearance_http`, return to the
+browser-clearance flow above so the generated CLI has both browser-compatible
+HTTP and reusable browser auth proof.
+
### Pre-Generation MCP Enrichment
Before generating, count the spec's MCP tool surface and decide whether to opt
← 9bb46da6 fix(cli): correct HTTP Basic auth env vars (#810)
·
back to Cli Printing Press
·
fix(catalog): Align Google Flights catalog with Flight Goat' 19702102 →