# dpr-viewport — VALIDATION RESULTS

## Signal hypothesis

Real users have devicePixelRatio in {1, 1.25, 1.5, 2, 2.25, 2.5, 3}.
Headless default viewport is 1280×720 with DPR=1. Pixel-perfect
`DPR=1 + 1280×720 viewport` is suspicious.

## 3-condition results

| Condition | dpr | innerWidth | screen | visualViewport.scale | verdict |
|---|---|---|---|---|---|
| Vanilla headless | 1 | 1280 | 1280×720 | 1 | 🟡 Default 1280×720 + DPR=1 |
| CDP-attached | 1 | 780 | 800×600 | 1 | ✅ Real Chrome |
| Headful (Xvfb) | 1 | **1920** | (server) | 1 | ✅ Real Chrome |

**Headful differs from vanilla** (1920×1080 vs 1280×720). CDP shows 780×441
(small Chrome window, not fullscreen).

## Verdict: ⚠️ MARGINAL — DPR alone doesn't discriminate

DPR=1 in all 3 conditions. The "1280×720 default" check only fires on
vanilla headless (where Playwright uses default viewport). But:
- Many real users have 1280×720 displays (small laptops)
- DPR=1 is normal for low-DPI screens
- A returning visitor with a 1280×720 laptop is indistinguishable from
  vanilla headless with default viewport

## Recommendation

DO NOT SHIP as standalone. The signal would catch vanilla Playwright only —
not other headless configs (Puppeteer with custom viewport, real users
with small screens).

**Useful as part of a stealth detection check**: if a stealth framework
claims DPR=2 but innerWidth=1280 and screen=1280, that's suspicious. But
that's a composite check, not a single-signal Phase 1 finding.

## Files

- `demo.html`
