Skip to content

feat: detect headless browsers via missing headers (Playwright/Puppeteer)#8

Merged
Gdewilde merged 1 commit intomainfrom
feat/headless-detection
Apr 21, 2026
Merged

feat: detect headless browsers via missing headers (Playwright/Puppeteer)#8
Gdewilde merged 1 commit intomainfrom
feat/headless-detection

Conversation

@Gdewilde
Copy link
Copy Markdown
Contributor

Detects Playwright-based agents (Aider, OpenCode) that spoof real browser UAs by checking for missing standard headers.

How it works

detectHeadless(req) scores browser-like requests on 6 signals:

Signal Why
Missing Accept-Language Every real browser sends this
Missing Sec-Fetch-Mode All modern browsers (Chrome 76+, Firefox 90+, Safari 16.4+)
Missing Sec-CH-UA Chromium Client Hints (v89+)
Sec-CH-UA contains HeadlessChrome Explicitly headless
Missing or bare Accept Browsers send detailed accept lists
Connection: close Browsers use keep-alive

Score >= 2 with a browser UA = headless-likely.

Integration

  • classifyRequest(req) promotes browser to headless-likely when detected
  • trackVisit emits headless_score and headless_likely properties
  • skipBrowsers: true now captures headless-likely requests alongside declared bots and HTTP clients

New exports

  • detectHeadless(req) — standalone headless detection
  • classifyRequest(req) — full request classification (UA + headers)
  • HeadlessDetection type

Bumps to v0.7.0. 103 tests pass.

…ders

Adds detectHeadless(req) that scores browser-like requests on 6 signals:
- Missing Accept-Language (every real browser sends this)
- Missing Sec-Fetch-Mode (all modern browsers)
- Missing Sec-CH-UA (Chromium 89+)
- Sec-CH-UA contains HeadlessChrome
- Missing or bare Accept header
- Connection: close (browsers use keep-alive)

Score >= 2 with a browser UA = headless-likely.

Integration:
- classifyRequest(req) promotes browser to headless-likely when detected
- trackVisit emits headless_score and headless_likely properties
- skipBrowsers: true now captures headless-likely requests (Aider, OpenCode)

New exports: detectHeadless, classifyRequest, HeadlessDetection

Bumps to v0.7.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Gdewilde Gdewilde merged commit fbf9298 into main Apr 21, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant