Build1 distinct publisher3 min readPublished
A practitioner who builds an automation browser argues bot detection fires in a fixed order, starting at the TLS handshake. The Bamberg crawl he cites found 75% of blocks on headless Chromium needed only HTTP headers.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
Take a stock Go program, set the user agent to Chrome 140, request an HTTPS page. Before any header is written, the TLS library has already sent a ClientHello whose cipher suite order, extension list, elliptic curves, ALPN and GREASE placement are the ones `crypto/tls` emits, and the server hashes exactly those features into a JA3/JA4 value [5][6]. The user agent string arrives after that. The post's word for the result is contradiction rather than heuristic, and that is the correct word: nothing needs to be scored, because two assertions about the same client cannot both be true [6].
This is why the most common remediation is aimed at the wrong place. The author numbers `navigator.webdriver` patching as a layer-4 fix applied to a stack that already rejected the client at layer 1 [11]. Patch scripts run in the page. The page only runs after the handshake, the HTTP/2 SETTINGS exchange and the header inspection have all been passed [10].
The Bamberg figure is the strongest evidence in the piece and the one to hold loosely. Their crawl reported that 75% of the blocks observed against headless Chromium could be triggered on HTTP header signals alone, with no JavaScript executed [9]. Invert it and at most a quarter of those blocks needed anything past the headers [20]. For the 75% to describe your workload, your targets have to look like the crawl's: Tranco Top 1M properties, unauthenticated navigation, headless Chromium as the client, and whatever mix of detection vendors those sites happened to run in that sample [9]. A single authenticated vendor portal is a sample size of one, and it is not in that population.
The consistency argument is the more portable part. The post enumerates eight agreements that hold on a real desktop Chrome, running from TLS-to-UA at one end to timezone-versus-exit-IP and language-list-versus-`Intl` at the other, and requires all of them to survive being asked from a Web Worker or an iframe instead of the main thread [13][14]. That is a conjunction, not a checklist you can partially satisfy. The `navigator.connection` case shows the cost of getting it wrong at one node: real Chrome derives `rtt`, `downlink` and `effectiveType` from one measurement, so `effectiveType: '4g'` next to `rtt: 0` is a pair Chrome never emits [18]. The author says his browser measures the actual round trip through the proxy and runs it through Chromium's own effective-connection-type thresholds so the three fields agree by construction [19]. A defender who needs to find two mutually exclusive claims has a cheaper job than a builder who needs eight simultaneous ones, which is an unusual arrangement in this business.
In my context the conclusion is not to build a better disguise. If the job is one portal and one invoice, the coherent fingerprint you already own is a real desktop browser profile on a real desktop, and the cheaper engineering is a credentialed feed. Fleet-scale automation is where you accept the maintenance: someone owns the whole bundle, derives it from measurements rather than field by field, and re-checks it every time the container image changes [13][19].
Ranked by verification strength, evidence, and original report placement.
The author gave an agent a job: log into a vendor portal, download last month's invoice PDF, rename it and drop it in a folder. It worked on his laptop and failed on the server.
The server-side failure was silent and took a full day to understand: the page loaded, the DOM and login form were present, and the credentials were rejected with a generic error. There was no CAPTCHA and no block page.
The author states that he builds a browser for this problem and has read a lot of block pages.
The post argues bot detection is not a single check but a stack whose layers fire in order, and that the layer which blocks you is almost never the one you are looking at.
Before any of the page's JavaScript runs, the server already has the TLS handshake: cipher suite order, extensions, elliptic curves, ALPN and GREASE placement, hashed into a JA3/JA4 fingerprint.
A Go or Python HTTP client claiming to be Chrome 140 is over the moment the handshake completes: the UA says Chrome, the handshake says crypto/tls. The post calls this a contradiction rather than a heuristic.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 30, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
The stroke width that never rendered: SVG attributes lose every cascade fight1 distinct publisher
product
AI writes the Dockerfile, and the pipeline is still checking the app code1 distinct publisher
build
JetBrains asked 15,000 developers how much code agents write. The answers add up to 112 percent1 distinct publisher
product
MinIO went dark on 13 February. Docker will keep patching it until 2031, for a fee.1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Checkable mechanics, one uninspected number
Split the piece in two and it scores very differently. The protocol material — JA3/JA4 hashing of handshake order, HTTP/2 SETTINGS and pseudo-header shape, the fetch-metadata header pattern, the impossible rtt/effectiveType pair — is the kind of thing a reader can confirm with a packet capture and a browser in an afternoon, and it is stated precisely enough to be falsified. The load carried by the 75% figure is a different matter: it exists in this reporting as a citation string, arXiv number and conference included, with no second account and no dataset in hand.
No usage figures of any kind
Nothing in this reporting counts anything: no installs, no request volumes, no block rates across a fleet, no customers. We get one agent failing against one unnamed vendor portal two months before publication, plus a description of how the author's own browser derives connection metrics. Treating an anecdote and a product note as traction would be dressing up the wrong thing, so we leave this unscored.
Slightly ahead of its proof
Mildly overstated, and mostly in one place. 'The layer that kills you is almost never the one you're looking at' is delivered as settled fact when the only number behind the ordering is borrowed, and the dispositive framing — contradiction, not heuristic — leaves no room for detectors that score rather than reject. Working the other way, the piece declines most of the available hype: no silver bullet, the author's hardest failure is the one he volunteers, and the closing advice is unglamorous engineering hygiene. Hence a small positive rather than a large one.
Disclosed, and shaping every recommendation
He says in the fourth paragraph that he builds a browser for this, and the argument is built to that shape. Fix the network layer first, derive timezone and locale from the exit IP, stop injecting overrides from userland — read as a list, that is a specification for a purpose-built browser and a demonstration that an HTTP client plus extra headers cannot get there. The connection-object passage switches to 'when we derive that object' and describes the product directly. Honest disclosure does not neutralise the pull; it just lets you see it.
One voice, no counterparty
We are working from a single post on a single platform, written by someone with something to sell, and our copy of it breaks off mid-sentence in the recommendations. The two parties who could test the ordering claim — a detection vendor and a targeted site operator — are absent, and the academic work that would settle the header-only question never appears as more than a reference. Enough to act on the mechanics; not enough to call the 75% figure or the vendor's implementation established.