All articles Bot detection

Fingerprinting undetected-chromedriver Sessions

undetected-chromedriver exists because vanilla Selenium is trivially detectable: it injects cdc_ variables into the document, flips navigator.webdriver, and advertises automation switches. UC patches the ChromeDriver binary and launch to bury those tells, which makes it popular for Python scraping, and still leaves a signature a modern detector can read.

What UC fixes

The core wins are real:

  • The cdc_$wdc_ and related properties Selenium injects into every document are renamed or removed by patching the driver binary.
  • Automation-controlled switches that set navigator.webdriver are dropped from the launch.
  • A few high-visibility navigator properties are normalized so shallow scripts pass.

If your bot defense greps for cdc_ or checks navigator.webdriver, UC walks straight through it. Those checks have been dead for years.

Where UC still shows itself

UC patches the famous tells and leaves the structural ones:

  1. CDP session presence. UC still drives Chrome over the DevTools Protocol. Execution-context creation timing, the DevTools target, and Runtime exception quirks persist below the JavaScript layer where the patches live.
  2. Client hints and UA drift. UC sessions frequently run slightly behind on Chrome version, or present User-Agent Client Hints that disagree with the rendered engine build, because the environment is pinned while the spoofed strings are not.
  3. Font and rendering environment. Headless-derived Linux server profiles ship a thin, telltale font set and specific font-smoothing behavior that a claimed consumer-Windows profile contradicts.
  4. Scripted input. UC does nothing about behavior. ActionChains produce linear, evenly timed pointer motion with pixel-perfect targeting no human generates.

The provenance problem

The deepest issue for UC is that page-level patches cannot change how the browser was launched or where it runs. A patched binary still starts under an automation harness on infrastructure that looks like a datacenter, and those facts surface in signals the script cannot reach. This is why we lean on server-side signals and reputation rather than trusting any property the client hands us: the client is exactly what UC controls.

Correlation is the killer

UC-based scraping is almost always a farm. Operators run many workers off one patched image, one launch recipe, and a small pool of hardware and font profiles behind rotating proxies. Prynt assigns a stable visitorId that survives IP rotation, incognito, and storage clearing, so ten thousand “distinct” scrape sessions that resolve to a few dozen persistent identities are exposed by the collapse. Add the cross-site reputation network and a UC signature seen abusing one property arrives flagged on the next.

Version drift is a gift

One trait makes UC especially catchable in practice: it lags Chrome. Because UC patches a specific ChromeDriver build, operators tend to pin a version and leave it, while genuine users auto-update within days of a Chrome release. That creates a detectable population of sessions clustered on an outdated build, presenting client hints and feature profiles that no longer match the current stable channel. When a session claims to be a mainstream consumer on the latest Chrome but its rendering capabilities, codec support, and API surface belong to a build three or four versions old, the contradiction is hard to explain away. Combine that version drift with the datacenter-hosted network path most UC farms run on and you have two independent signals pointing the same direction before you even look at behavior. Real users rarely present both an outdated pinned build and a server-grade IP at once.

A practical detection stack

To fingerprint UC sessions with confidence:

  • Score CDP and process-level artifacts server-side rather than checking for cdc_.
  • Cross-check client hints, UA, and the actual rendering engine for version drift.
  • Profile the font and rendering environment against the claimed platform.
  • Measure input entropy and event cadence for scripted flatness.
  • Correlate the visitorId across sessions and against reputation data.
  • Return an explainable suspect score with reason codes.

Any one of these can false-positive in isolation, which is why the score is a weighted combination, not a single rule. A privacy-conscious user on an older browser might trip the version-drift check; the same user is exceedingly unlikely to also present scripted input, CDP artifacts, a server-grade IP, and a collapsed cross-session identity. The weighting is what separates a cautious human from an automation farm without punishing the former.

The takeaway

undetected-chromedriver is very good at defeating the detection techniques of five years ago and largely helpless against correlated, server-side scoring plus cross-session identity. The specific properties it patches will keep expanding; the structural tells, CDP provenance, environment contradictions, and behavioral flatness, will not go away.

Want to see how a UC session scores against live signals? Run one through the playground. Free to start.

Try it free

Prynt is device intelligence with a free tier — visitor IDs, bot & fraud Smart Signals, and behavioral biometrics, powered by a cross-site network. Start free.

Keep reading