@rester159/blacktip 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -1
- package/README.md +4 -0
- package/dist/akamai-sensor.d.ts +128 -0
- package/dist/akamai-sensor.d.ts.map +1 -0
- package/dist/akamai-sensor.js +190 -0
- package/dist/akamai-sensor.js.map +1 -0
- package/dist/blacktip.d.ts +34 -0
- package/dist/blacktip.d.ts.map +1 -1
- package/dist/blacktip.js +35 -0
- package/dist/blacktip.js.map +1 -1
- package/dist/browser-core.d.ts +10 -0
- package/dist/browser-core.d.ts.map +1 -1
- package/dist/browser-core.js +49 -0
- package/dist/browser-core.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/tls-rewriter.d.ts +74 -0
- package/dist/tls-rewriter.d.ts.map +1 -0
- package/dist/tls-rewriter.js +203 -0
- package/dist/tls-rewriter.js.map +1 -0
- package/dist/tls-side-channel.d.ts +13 -4
- package/dist/tls-side-channel.d.ts.map +1 -1
- package/dist/tls-side-channel.js +9 -2
- package/dist/tls-side-channel.js.map +1 -1
- package/dist/types.d.ts +31 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/docs/akamai-sensor.md +183 -0
- package/docs/tls-rewriting.md +121 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,38 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.5.0] — 2026-04-10
|
|
10
|
+
|
|
11
|
+
The "best in the world" release. v0.5.0 closes both remaining gaps from the v0.4.0 wrap-up: full TLS rewriting (every browser request, not just the gating one) and Akamai sensor challenge automation. Both shipped, both validated end-to-end against live targets.
|
|
12
|
+
|
|
13
|
+
### Added — full TLS rewriting via CDP Fetch interception
|
|
14
|
+
|
|
15
|
+
- **`BlackTipConfig.tlsRewriting: 'all' | 'off'`** — when `'all'`, every browser request is intercepted via Chrome DevTools Protocol's `Fetch.enable` and forwarded through the Go-based `bogdanfinn/tls-client` daemon. The browser never opens an upstream TCP connection — every wire request presents real Chrome TLS via Go.
|
|
16
|
+
- **No cert installation.** Avoids the OS-specific cert-store hell of a TCP-level MITM proxy by working at the CDP layer instead. Same end-state ("every wire request gets real Chrome TLS via Go"), dramatically more shippable.
|
|
17
|
+
- **`bt.getTlsRewriterStats()`** — observability for the rewriter: intercepted/fulfilled/fell-through counts, WebSocket leaks, average daemon round-trip. Lets you verify the rewriter is doing what you expect.
|
|
18
|
+
- **Auto-disables QUIC** — adds `--disable-quic` to Chrome launch args when rewriting is on, because Chrome handles QUIC at a layer below CDP Fetch and would otherwise bypass the rewriter entirely.
|
|
19
|
+
- **Validated end-to-end against tls.peet.ws via the browser.** JA4 reaching the upstream is `t13d1516h2_8daaf6152771_d8a2da3f94cd` (textbook Chrome 133), first cipher `TLS_GREASE (0x3A3A)` with proper rotation, HTTP/2 fingerprint `1:65536;2:0;4:6291456;6:262144|15663105|0|m,a,s,p` (exact Chrome match) — and this is the JA4 the upstream sees when the BROWSER navigates, proving the upstream connection was opened by Go, not Chrome.
|
|
20
|
+
- **Cross-platform UA spoofing restored.** v0.2.0's L016 fix removed the broken context-level UA override; the rewriter restores cross-platform spoofing safely because the daemon controls every header on the wire.
|
|
21
|
+
- **Honest limitations** documented in `docs/tls-rewriting.md`: WebSocket leaks (Fetch.enable can't intercept the upgrade), streaming responses must be fully buffered (Fetch.fulfillRequest takes a complete body), 5–10ms per-request overhead (acceptable for stealth-critical use cases, not for high-throughput crawling).
|
|
22
|
+
- **`src/tls-rewriter.ts`** — the rewriter itself, separated from `browser-core.ts` so it's testable in isolation. Strips request headers Chrome owns (`Host`, `Content-Length`, `Connection`, etc.), strips response headers Chrome re-computes (`Content-Length`, `Content-Encoding`), handles multi-valued `Set-Cookie` correctly.
|
|
23
|
+
- **4 new integration tests** in `tests/tls-rewriter.integration.test.ts` — navigation success, JA4 fingerprint match via browser navigation, stats reporting, subresource interception via Hacker News (proves no native-Chrome leaks on subresources).
|
|
24
|
+
|
|
25
|
+
### Added — Akamai sensor challenge solver
|
|
26
|
+
|
|
27
|
+
- **`bt.solveAkamaiChallenge(url)`** — drives a real BlackTip browser session through Akamai's sensor challenge for `url`, polls until `_abck` reaches a definitive state, and returns the validated cookies plus a pre-built header set ready to inject into TLS-daemon replay calls. The cost amortization is real: **5x speedup over per-call browser usage with zero detection cost** (15s solve + 100×0.6s replays = 75s vs 400s for browser-per-call on 100 calls).
|
|
28
|
+
- **Architecture rationale** documented in `docs/akamai-sensor.md`: not a pure-Go solver because reverse-engineering bm.js would be a 1-2 week project that rots in 6 weeks. The shipped pattern ("solve once with the real browser, replay N times via the daemon") is more sustainable AND faster in practice.
|
|
29
|
+
- **`AkamaiChallengeResult.recommendedHeaders`** — pre-built header object containing Cookie + User-Agent + Accept-Language + Sec-Ch-Ua + Sec-Ch-Ua-Mobile + Sec-Ch-Ua-Platform + Sec-Fetch-Dest + Sec-Fetch-Mode + Sec-Fetch-Site + Sec-Fetch-User + Upgrade-Insecure-Requests. Empirically validated: replays without these headers 403 even with valid cookies, because Akamai validates the full request shape, not just the cookie jar.
|
|
30
|
+
- **`parseAbckState(abckValue)`** — pure-function helper that decodes the `_abck` validation state from the cookie value. Returns `0` (validated), `-1` (sensor not enforced — Akamai admitted on TLS/IP/behavior signals), `1` (flagged as bot), or `null` (no cookie). Both `0` and `-1` count as "session usable" because empirically Akamai admits real-Chrome residential sessions without ever requiring sensor validation.
|
|
31
|
+
- **8 new unit tests** in `tests/akamai-sensor.test.ts` covering all `parseAbckState` paths.
|
|
32
|
+
- **2 new integration tests** in `tests/akamai-sensor.integration.test.ts` against the live OpenTable booking endpoint: solver returns the full Akamai cookie set + recommended headers, and 3 consecutive daemon replays via `bt.fetchWithTls(solved.recommendedHeaders)` all return 200 with real content.
|
|
33
|
+
|
|
34
|
+
### Test suite
|
|
35
|
+
|
|
36
|
+
- **94 → 102 unit tests passing** (+8 Akamai parser), zero regressions.
|
|
37
|
+
- **Plus 6 new integration tests** total: 4 TLS rewriter, 2 Akamai sensor.
|
|
38
|
+
|
|
39
|
+
[0.5.0]: https://github.com/rester159/blacktip/compare/v0.4.0...v0.5.0
|
|
40
|
+
|
|
9
41
|
## [0.4.0] — 2026-04-10
|
|
10
42
|
|
|
11
43
|
The "close the remaining gaps" release. v0.4.0 ships everything that had been accumulated since v0.2.0 plus three new pieces that close out the gaps named in the v0.3.0 wrap-up: a Kasada-validated pass on a real armed endpoint (Twitch), an `IdentityPool` for long-running session and identity rotation, and a launch-time IP reputation gate. There is no separate v0.3.0 release on npm — the v0.3.0 work was developed in the same release cycle and rolls into 0.4.0 as one shipment.
|
|
@@ -184,7 +216,7 @@ Real-target validation:
|
|
|
184
216
|
- Real Chrome must be installed on the host for the preferred `channel: 'chrome'` path. patchright's bundled Chromium is the fallback.
|
|
185
217
|
- Scoped-name fix: the initial planned unscoped name `blacktip` was blocked by npm's anti-typosquatting policy (too similar to the pre-existing `black-tip` package). Released as `@rester159/blacktip` instead.
|
|
186
218
|
|
|
187
|
-
[Unreleased]: https://github.com/rester159/blacktip/compare/v0.
|
|
219
|
+
[Unreleased]: https://github.com/rester159/blacktip/compare/v0.5.0...HEAD
|
|
188
220
|
[0.4.0]: https://github.com/rester159/blacktip/compare/v0.2.0...v0.4.0
|
|
189
221
|
[0.2.0]: https://github.com/rester159/blacktip/compare/v0.1.0...v0.2.0
|
|
190
222
|
[0.1.0]: https://github.com/rester159/blacktip/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -181,8 +181,12 @@ See `AGENTS.md` for the full agent-facing reference, including the decision tree
|
|
|
181
181
|
| `bt.testAgainstAntiBot(url)` | Multi-vendor probe — detects Akamai, DataDome, Cloudflare, PerimeterX, Imperva, Kasada, Arkose, plus vendor signals on a passing page (v0.2.0) |
|
|
182
182
|
| `bt.fetchWithTls(req)` | Perform an HTTP request via a Go-based `bogdanfinn/tls-client` daemon with a real Chrome TLS ClientHello, H2 frame settings, and frame order. Use for first-request edge gating and cross-platform UA spoofing. Requires the daemon binary at `native/tls-client/` (build with `go build .`) (v0.3.0) |
|
|
183
183
|
| `bt.injectTlsCookies(resp, targetUrl?)` | Inject cookies returned by `fetchWithTls()` into the browser session, filtered by target eTLD+1 (v0.3.0) |
|
|
184
|
+
| `bt.solveAkamaiChallenge(url)` | Solve Akamai's sensor challenge in the browser once, return cookies + recommended headers ready for replay via `fetchWithTls()`. ~5x speedup over per-call browser usage on protected APIs. (v0.5.0) |
|
|
185
|
+
| `bt.getTlsRewriterStats()` | Stats for the TLS rewriter when `tlsRewriting: 'all'` is set — intercepted/fulfilled/fell-through counts, WebSocket leaks, average daemon round-trip. (v0.5.0) |
|
|
184
186
|
|
|
185
187
|
Plus `IdentityPool` (v0.4.0) for long-running session and identity rotation across many flows. See **[docs/identity-pool.md](docs/identity-pool.md)**.
|
|
188
|
+
|
|
189
|
+
**`BlackTipConfig.tlsRewriting: 'all'`** (v0.5.0) — when set, every browser request is intercepted via CDP `Fetch.enable` and forwarded through the Go-based `bogdanfinn/tls-client` daemon. The browser never opens an upstream TCP connection — every wire request, including subresources, presents real Chrome TLS via Go. Cross-platform UA spoofing is restored. See **[docs/tls-rewriting.md](docs/tls-rewriting.md)**.
|
|
186
190
|
| `bt.warmSession({sites?, dwellMsRange?})` | Pre-target warm-up — visit normal sites first (v0.2.0) |
|
|
187
191
|
| `bt.serve(port?)` | Start TCP command server |
|
|
188
192
|
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Akamai Bot Manager sensor challenge solver.
|
|
3
|
+
*
|
|
4
|
+
* The v0.5.0 answer to "I want to call Akamai-protected APIs from a
|
|
5
|
+
* sessionless TLS daemon, but the first request always 403s because
|
|
6
|
+
* Akamai gates everything behind a sensor data POST."
|
|
7
|
+
*
|
|
8
|
+
* Why this isn't pure Go: Akamai's bm.js is heavily obfuscated, the
|
|
9
|
+
* sensor data POST it generates is encrypted with a runtime-derived
|
|
10
|
+
* key that lives inside the obfuscated code, and the obfuscation rotates
|
|
11
|
+
* monthly. A pure-Go reimplementation would be a 1-2 week reverse
|
|
12
|
+
* engineering project and the result would rot in ~6 weeks. Bad ROI.
|
|
13
|
+
*
|
|
14
|
+
* What we do instead: launch a real BlackTip browser, navigate to the
|
|
15
|
+
* URL, let Akamai's bm.js execute naturally (real Chrome runs the JS,
|
|
16
|
+
* generates the sensor payload, POSTs it back), poll for the `_abck`
|
|
17
|
+
* cookie to transition from `~-1~` (unvalidated) to `~0~` (validated),
|
|
18
|
+
* and return the validated cookies. The caller can then inject those
|
|
19
|
+
* cookies into thousands of sessionless TLS-daemon API calls until
|
|
20
|
+
* they expire (Akamai sessions are valid for ~1 hour typically).
|
|
21
|
+
*
|
|
22
|
+
* This is NOT "no browser needed for Akamai." It IS "amortize browser
|
|
23
|
+
* cost across many subsequent API calls instead of paying it per
|
|
24
|
+
* request." For most use cases that's the same thing — you pay one
|
|
25
|
+
* browser session per hour and run hundreds of API calls in between.
|
|
26
|
+
*/
|
|
27
|
+
import type { BlackTip } from './blacktip.js';
|
|
28
|
+
export interface AkamaiChallengeResult {
|
|
29
|
+
/**
|
|
30
|
+
* Whether the session is usable. True when EITHER:
|
|
31
|
+
* - `_abck` cookie reached the validated state (`~0~`), OR
|
|
32
|
+
* - The page rendered successfully without an Akamai block.
|
|
33
|
+
*
|
|
34
|
+
* Akamai's sensor validation is only enforced when other signals
|
|
35
|
+
* (TLS, IP, behavior) look suspicious. For real-Chrome sessions on
|
|
36
|
+
* residential connections, Akamai often admits the request without
|
|
37
|
+
* ever requiring the JS-layer sensor POST. In those cases `abckState`
|
|
38
|
+
* stays at `-1` but the page works fine — that's still a successful
|
|
39
|
+
* solve from the caller's perspective.
|
|
40
|
+
*/
|
|
41
|
+
validated: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* The actual `_abck` validation state at the end of the wait window:
|
|
44
|
+
* - `0` → sensor data validated as human (gold standard)
|
|
45
|
+
* - `-1` → sensor not enforced (page admitted without it)
|
|
46
|
+
* - `1`+ → sensor data flagged as bot
|
|
47
|
+
* - `null` → no `_abck` cookie set (target may not be Akamai-protected)
|
|
48
|
+
*/
|
|
49
|
+
abckState: -1 | 0 | 1 | null;
|
|
50
|
+
/** The full `_abck` cookie value at the end of the wait window. */
|
|
51
|
+
abckValue: string | null;
|
|
52
|
+
/**
|
|
53
|
+
* Whether the rendered page looks like an Akamai block page (title
|
|
54
|
+
* `Access Denied`, body matches the standard error template).
|
|
55
|
+
*/
|
|
56
|
+
blocked: boolean;
|
|
57
|
+
/** All Akamai-related cookies on the target session, ready to inject. */
|
|
58
|
+
cookies: Array<{
|
|
59
|
+
name: string;
|
|
60
|
+
value: string;
|
|
61
|
+
domain: string;
|
|
62
|
+
path: string;
|
|
63
|
+
}>;
|
|
64
|
+
/** Final URL after any redirects. */
|
|
65
|
+
finalUrl: string;
|
|
66
|
+
/** Page title (useful for verifying we're not on an Access Denied page). */
|
|
67
|
+
title: string;
|
|
68
|
+
/** How long the solve took, ms. */
|
|
69
|
+
durationMs: number;
|
|
70
|
+
/** Free-form diagnostic notes. */
|
|
71
|
+
notes: string[];
|
|
72
|
+
/**
|
|
73
|
+
* Pre-built header set ready to pass to `bt.fetchWithTls({ url, headers })`
|
|
74
|
+
* for replay calls. Includes the Cookie header (joined from `cookies`)
|
|
75
|
+
* plus the Sec-Ch-Ua / Sec-Fetch-* / Accept-Language headers Akamai
|
|
76
|
+
* binds the session to. **Replays without these headers will 403** even
|
|
77
|
+
* with valid cookies — Akamai validates the full request shape, not
|
|
78
|
+
* just the cookie jar.
|
|
79
|
+
*
|
|
80
|
+
* Empirically validated against OpenTable: 5 consecutive replays via
|
|
81
|
+
* the TLS daemon all returned 200 with real content. Replay cost is
|
|
82
|
+
* ~600ms per call vs ~4s per browser launch.
|
|
83
|
+
*/
|
|
84
|
+
recommendedHeaders: Record<string, string>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Parse the Akamai sensor validation state from a `_abck` cookie value.
|
|
88
|
+
* Akamai encodes the state in the second `~`-delimited field:
|
|
89
|
+
* - `-1` means "sensor data not yet submitted/validated" (the value
|
|
90
|
+
* Akamai sets on the very first response).
|
|
91
|
+
* - `0` means "sensor data submitted and validated as human."
|
|
92
|
+
* - `1`+ means "sensor data submitted but flagged as bot."
|
|
93
|
+
*
|
|
94
|
+
* The validated state is what unlocks the rest of the protected paths.
|
|
95
|
+
*/
|
|
96
|
+
export declare function parseAbckState(abckValue: string | null): -1 | 0 | 1 | null;
|
|
97
|
+
/**
|
|
98
|
+
* Drive a BlackTip session through Akamai's sensor challenge for `url`,
|
|
99
|
+
* waiting until `_abck` reaches a validated state.
|
|
100
|
+
*
|
|
101
|
+
* The caller passes a launched BlackTip instance — the function does NOT
|
|
102
|
+
* launch its own. This is so the caller controls the surrounding context
|
|
103
|
+
* (TLS rewriting, IdentityPool identity, persistent profile, etc.).
|
|
104
|
+
*
|
|
105
|
+
* After this returns with `validated: true`, you can:
|
|
106
|
+
* - Inject `result.cookies` into another BlackTip session via `bt.setCookies()`
|
|
107
|
+
* - Inject them into a TLS daemon flow by setting them on the `Cookie:`
|
|
108
|
+
* header of subsequent `bt.fetchWithTls()` calls
|
|
109
|
+
* - Persist them in an IdentityPool snapshot
|
|
110
|
+
*
|
|
111
|
+
* Polls every 250ms with a default 15-second wait window. Most Akamai
|
|
112
|
+
* targets validate within 2-5 seconds; the wait is generous enough for
|
|
113
|
+
* slow targets but bounded so we don't hang on a permanently-blocked URL.
|
|
114
|
+
*/
|
|
115
|
+
export declare function solveAkamaiChallenge(bt: BlackTip, url: string, options?: {
|
|
116
|
+
/** Maximum time to wait for `_abck` to validate. Default 15s. */
|
|
117
|
+
timeoutMs?: number;
|
|
118
|
+
/** Poll interval for the cookie state. Default 250ms. */
|
|
119
|
+
pollIntervalMs?: number;
|
|
120
|
+
/**
|
|
121
|
+
* Optional human-like dwell after navigation finishes but before we
|
|
122
|
+
* start polling. Akamai's sensor data is more convincing if there's
|
|
123
|
+
* actual mouse movement / scrolling on the page. Default 1500ms; set
|
|
124
|
+
* to 0 to skip.
|
|
125
|
+
*/
|
|
126
|
+
dwellMsBeforePolling?: number;
|
|
127
|
+
}): Promise<AkamaiChallengeResult>;
|
|
128
|
+
//# sourceMappingURL=akamai-sensor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"akamai-sensor.d.ts","sourceRoot":"","sources":["../src/akamai-sensor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;OAWG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAC7B,mEAAmE;IACnE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB,yEAAyE;IACzE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9E,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;;;;;;;;OAWG;IACH,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAU1E;AAcD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IACP,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC1B,GACL,OAAO,CAAC,qBAAqB,CAAC,CA0HhC"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Akamai Bot Manager sensor challenge solver.
|
|
3
|
+
*
|
|
4
|
+
* The v0.5.0 answer to "I want to call Akamai-protected APIs from a
|
|
5
|
+
* sessionless TLS daemon, but the first request always 403s because
|
|
6
|
+
* Akamai gates everything behind a sensor data POST."
|
|
7
|
+
*
|
|
8
|
+
* Why this isn't pure Go: Akamai's bm.js is heavily obfuscated, the
|
|
9
|
+
* sensor data POST it generates is encrypted with a runtime-derived
|
|
10
|
+
* key that lives inside the obfuscated code, and the obfuscation rotates
|
|
11
|
+
* monthly. A pure-Go reimplementation would be a 1-2 week reverse
|
|
12
|
+
* engineering project and the result would rot in ~6 weeks. Bad ROI.
|
|
13
|
+
*
|
|
14
|
+
* What we do instead: launch a real BlackTip browser, navigate to the
|
|
15
|
+
* URL, let Akamai's bm.js execute naturally (real Chrome runs the JS,
|
|
16
|
+
* generates the sensor payload, POSTs it back), poll for the `_abck`
|
|
17
|
+
* cookie to transition from `~-1~` (unvalidated) to `~0~` (validated),
|
|
18
|
+
* and return the validated cookies. The caller can then inject those
|
|
19
|
+
* cookies into thousands of sessionless TLS-daemon API calls until
|
|
20
|
+
* they expire (Akamai sessions are valid for ~1 hour typically).
|
|
21
|
+
*
|
|
22
|
+
* This is NOT "no browser needed for Akamai." It IS "amortize browser
|
|
23
|
+
* cost across many subsequent API calls instead of paying it per
|
|
24
|
+
* request." For most use cases that's the same thing — you pay one
|
|
25
|
+
* browser session per hour and run hundreds of API calls in between.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Parse the Akamai sensor validation state from a `_abck` cookie value.
|
|
29
|
+
* Akamai encodes the state in the second `~`-delimited field:
|
|
30
|
+
* - `-1` means "sensor data not yet submitted/validated" (the value
|
|
31
|
+
* Akamai sets on the very first response).
|
|
32
|
+
* - `0` means "sensor data submitted and validated as human."
|
|
33
|
+
* - `1`+ means "sensor data submitted but flagged as bot."
|
|
34
|
+
*
|
|
35
|
+
* The validated state is what unlocks the rest of the protected paths.
|
|
36
|
+
*/
|
|
37
|
+
export function parseAbckState(abckValue) {
|
|
38
|
+
if (!abckValue)
|
|
39
|
+
return null;
|
|
40
|
+
const parts = abckValue.split('~');
|
|
41
|
+
if (parts.length < 2)
|
|
42
|
+
return null;
|
|
43
|
+
const stateStr = parts[1] ?? '';
|
|
44
|
+
const n = parseInt(stateStr, 10);
|
|
45
|
+
if (n === -1)
|
|
46
|
+
return -1;
|
|
47
|
+
if (n === 0)
|
|
48
|
+
return 0;
|
|
49
|
+
if (n >= 1)
|
|
50
|
+
return 1;
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
/** Cookie names we treat as "Akamai session state" for the result bundle. */
|
|
54
|
+
const AKAMAI_COOKIE_NAMES = new Set([
|
|
55
|
+
'_abck',
|
|
56
|
+
'bm_sz',
|
|
57
|
+
'bm_sv',
|
|
58
|
+
'ak_bmsc',
|
|
59
|
+
'bm_mi',
|
|
60
|
+
'bm_so',
|
|
61
|
+
'bm_s',
|
|
62
|
+
'bm_ss',
|
|
63
|
+
]);
|
|
64
|
+
/**
|
|
65
|
+
* Drive a BlackTip session through Akamai's sensor challenge for `url`,
|
|
66
|
+
* waiting until `_abck` reaches a validated state.
|
|
67
|
+
*
|
|
68
|
+
* The caller passes a launched BlackTip instance — the function does NOT
|
|
69
|
+
* launch its own. This is so the caller controls the surrounding context
|
|
70
|
+
* (TLS rewriting, IdentityPool identity, persistent profile, etc.).
|
|
71
|
+
*
|
|
72
|
+
* After this returns with `validated: true`, you can:
|
|
73
|
+
* - Inject `result.cookies` into another BlackTip session via `bt.setCookies()`
|
|
74
|
+
* - Inject them into a TLS daemon flow by setting them on the `Cookie:`
|
|
75
|
+
* header of subsequent `bt.fetchWithTls()` calls
|
|
76
|
+
* - Persist them in an IdentityPool snapshot
|
|
77
|
+
*
|
|
78
|
+
* Polls every 250ms with a default 15-second wait window. Most Akamai
|
|
79
|
+
* targets validate within 2-5 seconds; the wait is generous enough for
|
|
80
|
+
* slow targets but bounded so we don't hang on a permanently-blocked URL.
|
|
81
|
+
*/
|
|
82
|
+
export async function solveAkamaiChallenge(bt, url, options = {}) {
|
|
83
|
+
const start = Date.now();
|
|
84
|
+
const timeoutMs = options.timeoutMs ?? 15_000;
|
|
85
|
+
const pollIntervalMs = options.pollIntervalMs ?? 250;
|
|
86
|
+
const dwellMsBeforePolling = options.dwellMsBeforePolling ?? 1500;
|
|
87
|
+
const notes = [];
|
|
88
|
+
// 1. Navigate to the target. Akamai sets `_abck` on the response and
|
|
89
|
+
// schedules its bm.js to run.
|
|
90
|
+
await bt.navigate(url);
|
|
91
|
+
// 2. Brief dwell so Chrome can run bm.js and POST the sensor data.
|
|
92
|
+
// On most sites, the sensor POST happens within 100-500ms of DOM ready.
|
|
93
|
+
if (dwellMsBeforePolling > 0) {
|
|
94
|
+
await new Promise((r) => setTimeout(r, dwellMsBeforePolling));
|
|
95
|
+
}
|
|
96
|
+
// 3. Poll the cookie jar until `_abck` reaches a definitive state
|
|
97
|
+
// (validated or flagged), or the timeout window expires.
|
|
98
|
+
let lastAbck = null;
|
|
99
|
+
let lastState = null;
|
|
100
|
+
const deadline = start + timeoutMs;
|
|
101
|
+
while (Date.now() < deadline) {
|
|
102
|
+
const allCookies = await bt.cookies();
|
|
103
|
+
const abck = allCookies.find((c) => c.name === '_abck');
|
|
104
|
+
lastAbck = abck?.value ?? null;
|
|
105
|
+
lastState = parseAbckState(lastAbck);
|
|
106
|
+
if (lastState === 0) {
|
|
107
|
+
notes.push('_abck reached validated state (0) — sensor POST accepted');
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
if (lastState === 1) {
|
|
111
|
+
notes.push('_abck reached flagged state (1) — sensor POST was rejected as bot');
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
115
|
+
}
|
|
116
|
+
// 4. Collect the full Akamai cookie set for the caller.
|
|
117
|
+
const allCookies = await bt.cookies();
|
|
118
|
+
const akamaiCookies = allCookies
|
|
119
|
+
.filter((c) => AKAMAI_COOKIE_NAMES.has(c.name))
|
|
120
|
+
.map((c) => ({ name: c.name, value: c.value, domain: c.domain, path: c.path }));
|
|
121
|
+
// 5. Capture the final page state for diagnosis. We check for the
|
|
122
|
+
// Akamai Access Denied page format here so we can distinguish
|
|
123
|
+
// "page rendered fine, sensor not enforced" from "page blocked".
|
|
124
|
+
const pageState = (await bt.executeJS(`(() => ({
|
|
125
|
+
url: location.href,
|
|
126
|
+
title: document.title,
|
|
127
|
+
bodyPreview: (document.body ? document.body.innerText : '').slice(0, 600),
|
|
128
|
+
}))()`));
|
|
129
|
+
const blocked = pageState.title === 'Access Denied' ||
|
|
130
|
+
/You don't have permission to access/i.test(pageState.bodyPreview) ||
|
|
131
|
+
/errors\.edgesuite\.net/i.test(pageState.bodyPreview);
|
|
132
|
+
if (blocked) {
|
|
133
|
+
notes.push('Akamai served the Access Denied block page');
|
|
134
|
+
}
|
|
135
|
+
else if (lastState === null) {
|
|
136
|
+
notes.push('_abck cookie was never set — target may not be Akamai-protected');
|
|
137
|
+
}
|
|
138
|
+
else if (lastState === -1) {
|
|
139
|
+
notes.push('_abck stayed at -1 (sensor not enforced). Page rendered successfully — Akamai admitted the request based on TLS/IP/behavior signals without requiring JS sensor validation. Cookies are still usable for the session window.');
|
|
140
|
+
}
|
|
141
|
+
// The session is usable when the page rendered without a block,
|
|
142
|
+
// regardless of whether _abck reached the validated state. Akamai
|
|
143
|
+
// only enforces sensor validation when other signals look bad.
|
|
144
|
+
const validated = !blocked && (lastState === 0 || lastState === -1);
|
|
145
|
+
// 6. Build the recommended replay headers. These are the headers that
|
|
146
|
+
// Akamai validates alongside the cookie jar — without them, replays
|
|
147
|
+
// via the TLS daemon will 403 even with valid cookies. We include
|
|
148
|
+
// every cookie from the session in the Cookie header (not just the
|
|
149
|
+
// Akamai ones), since some sites bind to non-Akamai cookies too.
|
|
150
|
+
const cookieHeader = allCookies
|
|
151
|
+
.filter((c) => {
|
|
152
|
+
const cd = c.domain.replace(/^\./, '');
|
|
153
|
+
try {
|
|
154
|
+
const host = new URL(pageState.url).hostname;
|
|
155
|
+
return host === cd || host.endsWith('.' + cd);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
.map((c) => `${c.name}=${c.value}`)
|
|
162
|
+
.join('; ');
|
|
163
|
+
const recommendedHeaders = {
|
|
164
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
|
|
165
|
+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
|
166
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
167
|
+
'Sec-Ch-Ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
|
|
168
|
+
'Sec-Ch-Ua-Mobile': '?0',
|
|
169
|
+
'Sec-Ch-Ua-Platform': '"Windows"',
|
|
170
|
+
'Sec-Fetch-Dest': 'document',
|
|
171
|
+
'Sec-Fetch-Mode': 'navigate',
|
|
172
|
+
'Sec-Fetch-Site': 'none',
|
|
173
|
+
'Sec-Fetch-User': '?1',
|
|
174
|
+
'Upgrade-Insecure-Requests': '1',
|
|
175
|
+
'Cookie': cookieHeader,
|
|
176
|
+
};
|
|
177
|
+
return {
|
|
178
|
+
validated,
|
|
179
|
+
abckState: lastState,
|
|
180
|
+
abckValue: lastAbck,
|
|
181
|
+
blocked,
|
|
182
|
+
cookies: akamaiCookies,
|
|
183
|
+
finalUrl: pageState.url,
|
|
184
|
+
title: pageState.title,
|
|
185
|
+
durationMs: Date.now() - start,
|
|
186
|
+
notes,
|
|
187
|
+
recommendedHeaders,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=akamai-sensor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"akamai-sensor.js","sourceRoot":"","sources":["../src/akamai-sensor.ts"],"names":[],"mappings":"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"}
|
package/dist/blacktip.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { ElementFinder } from './element-finder.js';
|
|
|
6
6
|
import { Logger } from './logging.js';
|
|
7
7
|
import { type FingerprintSnapshot, type IpReputationResult, type AkamaiTestResult, type AntiBotTestResult } from './diagnostics.js';
|
|
8
8
|
import { type TlsRequest, type TlsResponse } from './tls-side-channel.js';
|
|
9
|
+
import { type AkamaiChallengeResult } from './akamai-sensor.js';
|
|
9
10
|
import type { BlackTipConfig, ProfileConfig, ActionResult, NavigateResult, ScreenshotResult, WaitResult, TabInfo, FrameInfo, ClickOptions, TypeOptions, ScrollOptions, HoverOptions, SelectOptions, PressKeyOptions, UploadFileOptions, NavigateOptions, ScreenshotOptions, WaitForOptions, WaitForNavigationOptions, ExtractTextOptions, PageContentOptions } from './types.js';
|
|
10
11
|
/**
|
|
11
12
|
* BlackTip — Stealth browser instrument for AI agents.
|
|
@@ -243,6 +244,39 @@ export declare class BlackTip extends EventEmitter {
|
|
|
243
244
|
* on an unprotected URL.
|
|
244
245
|
*/
|
|
245
246
|
testAgainstAntiBot(url: string): Promise<AntiBotTestResult>;
|
|
247
|
+
/**
|
|
248
|
+
* Return the TLS rewriter stats — intercepted/fulfilled/fell-through
|
|
249
|
+
* counts, WebSocket leaks, average daemon round-trip. Null when
|
|
250
|
+
* `BlackTipConfig.tlsRewriting` is `'off'` (the default).
|
|
251
|
+
*
|
|
252
|
+
* Use this to verify the rewriter is doing what you expect:
|
|
253
|
+
* - `intercepted > 0` confirms requests are being captured
|
|
254
|
+
* - `fulfilled === intercepted - webSocketLeaks` confirms no fallthroughs
|
|
255
|
+
* - `fellThrough > 0` indicates daemon failures (check daemon stderr)
|
|
256
|
+
*/
|
|
257
|
+
getTlsRewriterStats(): import("./tls-rewriter.js").TlsRewriterStats | null;
|
|
258
|
+
/**
|
|
259
|
+
* Drive this BlackTip session through Akamai's sensor challenge for
|
|
260
|
+
* `url`, waiting until the `_abck` cookie reaches a validated state.
|
|
261
|
+
* Returns the validated cookies for injection into other sessions
|
|
262
|
+
* (TLS daemon flows, IdentityPool snapshots, separate BlackTip
|
|
263
|
+
* instances).
|
|
264
|
+
*
|
|
265
|
+
* This is the v0.5.0 path for "make Akamai-protected API calls from a
|
|
266
|
+
* sessionless TLS daemon" — solve the challenge once via this method,
|
|
267
|
+
* cache the cookies, then run hundreds of `bt.fetchWithTls()` calls
|
|
268
|
+
* with the cached `Cookie` header until the session expires (~1h).
|
|
269
|
+
*
|
|
270
|
+
* NOT a pure-Go solver. Real Chrome runs the bm.js. We just centralize
|
|
271
|
+
* the browser usage to one primitive so the caller doesn't have to
|
|
272
|
+
* launch a full session per API call. See `docs/akamai-sensor.md` for
|
|
273
|
+
* the architecture rationale.
|
|
274
|
+
*/
|
|
275
|
+
solveAkamaiChallenge(url: string, options?: {
|
|
276
|
+
timeoutMs?: number;
|
|
277
|
+
pollIntervalMs?: number;
|
|
278
|
+
dwellMsBeforePolling?: number;
|
|
279
|
+
}): Promise<AkamaiChallengeResult>;
|
|
246
280
|
/**
|
|
247
281
|
* Perform an HTTP request through the bogdanfinn/tls-client Go daemon
|
|
248
282
|
* with a real Chrome TLS ClientHello, real H2 frame settings, and real
|
package/dist/blacktip.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blacktip.d.ts","sourceRoot":"","sources":["../src/blacktip.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"blacktip.d.ts","sourceRoot":"","sources":["../src/blacktip.ts"],"names":[],"mappings":"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"}
|
package/dist/blacktip.js
CHANGED
|
@@ -6,6 +6,7 @@ import { ElementFinder } from './element-finder.js';
|
|
|
6
6
|
import { Logger } from './logging.js';
|
|
7
7
|
import { captureFingerprint as diagnosticsCaptureFingerprint, checkIpReputation as diagnosticsCheckIpReputation, testAgainstAkamai as diagnosticsTestAgainstAkamai, testAgainstAntiBot as diagnosticsTestAgainstAntiBot, } from './diagnostics.js';
|
|
8
8
|
import { TlsSideChannel } from './tls-side-channel.js';
|
|
9
|
+
import { solveAkamaiChallenge as solveAkamaiChallengeImpl } from './akamai-sensor.js';
|
|
9
10
|
const RETRY_STRATEGIES = ['standard', 'wait', 'reload', 'altSelector', 'scroll', 'clearOverlays'];
|
|
10
11
|
/**
|
|
11
12
|
* Text patterns that suggest an action is high-importance — submit,
|
|
@@ -991,6 +992,40 @@ export class BlackTip extends EventEmitter {
|
|
|
991
992
|
this.ensureLaunched();
|
|
992
993
|
return diagnosticsTestAgainstAntiBot(this, url);
|
|
993
994
|
}
|
|
995
|
+
/**
|
|
996
|
+
* Return the TLS rewriter stats — intercepted/fulfilled/fell-through
|
|
997
|
+
* counts, WebSocket leaks, average daemon round-trip. Null when
|
|
998
|
+
* `BlackTipConfig.tlsRewriting` is `'off'` (the default).
|
|
999
|
+
*
|
|
1000
|
+
* Use this to verify the rewriter is doing what you expect:
|
|
1001
|
+
* - `intercepted > 0` confirms requests are being captured
|
|
1002
|
+
* - `fulfilled === intercepted - webSocketLeaks` confirms no fallthroughs
|
|
1003
|
+
* - `fellThrough > 0` indicates daemon failures (check daemon stderr)
|
|
1004
|
+
*/
|
|
1005
|
+
getTlsRewriterStats() {
|
|
1006
|
+
return this.core.getTlsRewriterStats();
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Drive this BlackTip session through Akamai's sensor challenge for
|
|
1010
|
+
* `url`, waiting until the `_abck` cookie reaches a validated state.
|
|
1011
|
+
* Returns the validated cookies for injection into other sessions
|
|
1012
|
+
* (TLS daemon flows, IdentityPool snapshots, separate BlackTip
|
|
1013
|
+
* instances).
|
|
1014
|
+
*
|
|
1015
|
+
* This is the v0.5.0 path for "make Akamai-protected API calls from a
|
|
1016
|
+
* sessionless TLS daemon" — solve the challenge once via this method,
|
|
1017
|
+
* cache the cookies, then run hundreds of `bt.fetchWithTls()` calls
|
|
1018
|
+
* with the cached `Cookie` header until the session expires (~1h).
|
|
1019
|
+
*
|
|
1020
|
+
* NOT a pure-Go solver. Real Chrome runs the bm.js. We just centralize
|
|
1021
|
+
* the browser usage to one primitive so the caller doesn't have to
|
|
1022
|
+
* launch a full session per API call. See `docs/akamai-sensor.md` for
|
|
1023
|
+
* the architecture rationale.
|
|
1024
|
+
*/
|
|
1025
|
+
async solveAkamaiChallenge(url, options) {
|
|
1026
|
+
this.ensureLaunched();
|
|
1027
|
+
return solveAkamaiChallengeImpl(this, url, options);
|
|
1028
|
+
}
|
|
994
1029
|
// ── TLS side-channel (v0.3.0) ──
|
|
995
1030
|
/**
|
|
996
1031
|
* Perform an HTTP request through the bogdanfinn/tls-client Go daemon
|