Resource probing and behavioural detection
The most direct method: an extension declares web_accessible_resources in its manifest, making files reachable at chrome-extension://<extension-id>/path. A page can fetch() or load an <img> at a known ID+path; a successful load means the extension is present. Manifest V3 narrowed this with per-origin randomised UUIDs, but timing and error-message differences still leak presence in many cases.
Indirect methods watch for what an extension does: ad blockers remove elements with bait class names, password managers inject icons into form fields, and grammar checkers add overlays. A site plants bait and observes whether it is altered.
Why it matters for bot detection
For anti-bot purposes the signal cuts both ways. A real human profile usually carries a handful of common extensions (uBlock Origin, a password manager). A freshly spun headless profile carries none — which, combined with empty history and a default font set, paints a clear automation picture. Conversely, some automation frameworks inject their own helper extensions whose resources are detectable directly. The realistic profile for scraping mirrors a believable human: a small, plausible extension set rather than a sterile blank slate.
Avoiding extension tells in automation
Two things give automation away here. First, automation-specific extensions and helpers (old Selenium IDE artifacts, injected helper scripts) expose web_accessible_resources that a page can probe for with a simple image or fetch load. Second, the absence of any extension at all — no ad blocker, no password manager, none of the resource-blocking behaviour a real user's browser exhibits — is itself a weak signal that you are a clean automation profile.
The fix is to drive the browser through the DevTools Protocol rather than injected extensions, so there are no chrome-extension:// resources to fingerprint, and to let the profile look ordinarily "lived-in" rather than pristine. Tools like Camoufox and managed scraping backends aim for this middle ground: no automation-specific extensions to detect, but a realistic, coherent profile rather than an obviously empty one.
