|
| 1 | +<!DOCTYPE html> |
| 2 | +<html lang="en"> |
| 3 | +<head> |
| 4 | +<meta charset="UTF-8"> |
| 5 | +<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 6 | +<title>Why CEF Beats CDP for Anti-Detection — Wick</title> |
| 7 | +<link rel="icon" type="image/svg+xml" href="../favicon.svg"> |
| 8 | +<meta name="description" content="Playwright, Puppeteer, and Browserbase all use CDP to control Chrome remotely. That's detectable. Wick Pro uses CEF — Chrome's rendering engine embedded directly, with no debug protocol to fingerprint."> |
| 9 | +<meta name="keywords" content="CEF vs CDP, chrome devtools protocol detection, chromium embedded framework, anti-detection, browser fingerprinting, playwright detection, puppeteer detection, headless browser detection"> |
| 10 | +<meta property="og:title" content="Why CEF Beats CDP for Anti-Detection"> |
| 11 | +<meta property="og:description" content="Every tool built on Playwright or Puppeteer uses CDP — and sites can detect it. Here's why embedding Chrome's engine directly is a fundamentally better approach."> |
| 12 | +<meta property="og:url" content="https://getwick.dev/blog/cef-vs-cdp.html"> |
| 13 | +<meta property="og:type" content="article"> |
| 14 | +<meta property="og:image" content="https://getwick.dev/og-image.png"> |
| 15 | +<meta property="article:published_time" content="2026-04-02T00:00:00Z"> |
| 16 | +<meta name="twitter:card" content="summary_large_image"> |
| 17 | +<meta name="twitter:title" content="Why CEF Beats CDP for Anti-Detection"> |
| 18 | +<meta name="twitter:description" content="Every tool built on Playwright or Puppeteer uses CDP — and sites can detect it. Here's why embedding Chrome's engine directly is a fundamentally better approach."> |
| 19 | +<meta name="twitter:image" content="https://getwick.dev/og-image.png"> |
| 20 | +<link rel="canonical" href="https://getwick.dev/blog/cef-vs-cdp.html"> |
| 21 | +<script type="application/ld+json"> |
| 22 | +{ |
| 23 | + "@context": "https://schema.org", |
| 24 | + "@type": "BlogPosting", |
| 25 | + "headline": "Why CEF Beats CDP for Anti-Detection", |
| 26 | + "description": "Playwright, Puppeteer, and Browserbase all use CDP. That's detectable. Here's why CEF is a fundamentally better approach.", |
| 27 | + "author": {"@type": "Person", "name": "Adam Fisk", "url": "https://getwick.dev"}, |
| 28 | + "publisher": {"@type": "Organization", "name": "Wick", "url": "https://getwick.dev"}, |
| 29 | + "datePublished": "2026-04-02", |
| 30 | + "dateModified": "2026-04-02", |
| 31 | + "mainEntityOfPage": {"@type": "WebPage", "@id": "https://getwick.dev/blog/cef-vs-cdp.html"}, |
| 32 | + "url": "https://getwick.dev/blog/cef-vs-cdp.html" |
| 33 | +} |
| 34 | +</script> |
| 35 | +<link rel="preconnect" href="https://fonts.googleapis.com"> |
| 36 | +<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| 37 | +<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> |
| 38 | +<style> |
| 39 | +:root{--flame:#E8913A;--ash:#1A1714;--smoke:#2A2520;--smoke-light:#3D3630;--warm-white:#F0E6D8;--warm-gray:#9E958A;--cool-gray:#6B635A;--black:#0D0B09;--font-display:'Outfit',sans-serif;--font-mono:'JetBrains Mono',monospace} |
| 40 | +*,*::before,*::after{margin:0;padding:0;box-sizing:border-box} |
| 41 | +body{background:var(--black);color:var(--warm-gray);font-family:var(--font-display);font-weight:300;line-height:1.8;-webkit-font-smoothing:antialiased} |
| 42 | +::selection{background:var(--flame);color:var(--black)} |
| 43 | +article{max-width:680px;margin:0 auto;padding:3rem 2rem 6rem} |
| 44 | +.back{display:inline-block;font-size:0.8rem;color:var(--flame);text-decoration:none;margin-bottom:2rem} |
| 45 | +.back:hover{text-decoration:underline} |
| 46 | +h1{font-size:1.8rem;font-weight:700;color:var(--warm-white);line-height:1.3;margin-bottom:0.5rem} |
| 47 | +.date{font-size:0.75rem;color:var(--cool-gray);margin-bottom:2rem} |
| 48 | +h2{font-size:1.15rem;font-weight:600;color:var(--warm-white);margin-top:2.5rem;margin-bottom:0.75rem} |
| 49 | +p{margin-bottom:1rem;font-size:0.92rem} |
| 50 | +strong{color:var(--warm-white);font-weight:500} |
| 51 | +a{color:var(--flame)} |
| 52 | +ul,ol{padding-left:1.5rem;margin-bottom:1rem;font-size:0.92rem} |
| 53 | +li{margin-bottom:0.4rem} |
| 54 | +code{font-family:var(--font-mono);font-size:0.82rem;background:var(--smoke);padding:0.15rem 0.4rem;border-radius:3px;color:#F5B74C} |
| 55 | +pre{background:var(--ash);border:1px solid var(--smoke-light);border-radius:6px;padding:1.25rem 1.5rem;overflow-x:auto;margin-bottom:1.5rem;line-height:1.7} |
| 56 | +pre code{background:none;padding:0;font-size:0.8rem;color:var(--warm-white)} |
| 57 | +hr{border:none;border-top:1px solid var(--smoke-light);margin:3rem 0 1.5rem} |
| 58 | +table{width:100%;border-collapse:collapse;margin-bottom:1.5rem;font-size:0.85rem} |
| 59 | +th{text-align:left;color:var(--warm-white);font-weight:500;padding:0.5rem 0.75rem;border-bottom:1px solid var(--smoke-light)} |
| 60 | +td{padding:0.5rem 0.75rem;border-bottom:1px solid var(--smoke);color:var(--warm-gray)} |
| 61 | +</style> |
| 62 | +</head> |
| 63 | +<body> |
| 64 | +<article> |
| 65 | +<a href="/" class="back">← Back to Wick</a> |
| 66 | + |
| 67 | +<h1>Why CEF Beats CDP for Anti-Detection</h1> |
| 68 | +<p class="date">April 2, 2026</p> |
| 69 | + |
| 70 | +<p>Every major browser automation tool — Playwright, Puppeteer, Selenium, Browserbase, Browserless — controls Chrome through the <strong>Chrome DevTools Protocol</strong> (CDP). It's the same protocol that powers Chrome's developer tools. You open a WebSocket connection to the browser, send commands, read responses.</p> |
| 71 | + |
| 72 | +<p>The problem: <strong>CDP is detectable.</strong> And anti-bot systems are very good at detecting it.</p> |
| 73 | + |
| 74 | +<h2>How sites detect CDP</h2> |
| 75 | + |
| 76 | +<p>When a browser is being controlled via CDP, it leaves fingerprints that JavaScript running on the page can observe:</p> |
| 77 | + |
| 78 | +<ul> |
| 79 | +<li><code>navigator.webdriver</code> is set to <code>true</code>. Playwright and Puppeteer try to override this, but the override itself is detectable — the property descriptor changes.</li> |
| 80 | +<li><strong>Runtime artifacts.</strong> CDP injects a JavaScript runtime context for its own use. Tools like <a href="https://abrahamjuliot.github.io/creepjs/">CreepJS</a> specifically check for these extra contexts.</li> |
| 81 | +<li><strong>Console API differences.</strong> When CDP is connected, <code>console.debug</code> behaves differently than in a normal browser. This is a known detection vector.</li> |
| 82 | +<li><strong>Notification permissions.</strong> Headless Chrome controlled via CDP reports different default permission states than a real browser.</li> |
| 83 | +<li><strong>WebSocket connection pattern.</strong> The CDP debug WebSocket is visible at the OS level. Sophisticated detection can look for this.</li> |
| 84 | +<li><strong>Missing browser features.</strong> Headless Chrome historically lacked certain APIs (like WebGL extensions or Bluetooth) that real Chrome exposes. The gap has narrowed but hasn't fully closed.</li> |
| 85 | +</ul> |
| 86 | + |
| 87 | +<p>The stealth arms race around CDP is well-documented. Projects like <code>puppeteer-extra-plugin-stealth</code> patch over 10+ detection vectors. Browserbase and Browserless do similar patching. But they're playing whack-a-mole — for every artifact they hide, detection services find new ones.</p> |
| 88 | + |
| 89 | +<p>This is fundamentally a losing architecture. You're using a debug protocol and then trying to hide the fact that you're using a debug protocol.</p> |
| 90 | + |
| 91 | +<h2>CEF: a different architecture</h2> |
| 92 | + |
| 93 | +<p><strong>CEF</strong> (Chromium Embedded Framework) takes the opposite approach. Instead of controlling Chrome from the outside via a debug protocol, CEF embeds Chrome's rendering engine directly into your application's process.</p> |
| 94 | + |
| 95 | +<p>There's no CDP. No WebSocket connection. No remote debugger. No <code>navigator.webdriver</code>. The page renders in a real Chromium instance that happens to be hosted inside Wick's process rather than in a standalone browser window.</p> |
| 96 | + |
| 97 | +<p>From the perspective of JavaScript running on the page, it's a normal browser. Because it <em>is</em> a normal browser — just embedded.</p> |
| 98 | + |
| 99 | +<table> |
| 100 | +<tr><th></th><th>CDP (Playwright, etc.)</th><th>CEF (Wick Pro)</th></tr> |
| 101 | +<tr><td>Architecture</td><td>Remote control via WebSocket</td><td>Engine embedded in process</td></tr> |
| 102 | +<tr><td>navigator.webdriver</td><td>Must be patched/hidden</td><td>Not set (not automated)</td></tr> |
| 103 | +<tr><td>Runtime injection</td><td>Yes (CDP contexts)</td><td>None</td></tr> |
| 104 | +<tr><td>Debug protocol</td><td>Always active</td><td>Not present</td></tr> |
| 105 | +<tr><td>Detection surface</td><td>Large, well-documented</td><td>Minimal</td></tr> |
| 106 | +<tr><td>Stealth approach</td><td>Patch over artifacts</td><td>No artifacts to patch</td></tr> |
| 107 | +</table> |
| 108 | + |
| 109 | +<h2>The censorship circumvention parallel</h2> |
| 110 | + |
| 111 | +<p>This is the same lesson we learned building <a href="https://lantern.io">Lantern</a>. National censors in China, Iran, and Russia use deep packet inspection to detect circumvention tools. Early tools tried to disguise their traffic — making VPN packets look like HTTPS, adding fake headers, randomizing packet timing.</p> |
| 112 | + |
| 113 | +<p>It didn't work well. The censors kept finding new detection vectors in the disguise. The approach that worked was <strong>not disguising traffic at all</strong>, but instead using actual standard protocols. If your TLS handshake is real Chrome because you're using Chrome's actual code, there's nothing to detect.</p> |
| 114 | + |
| 115 | +<p>Same principle with CEF vs CDP. Don't try to make automation look like a real browser. Use a real browser engine and remove the automation layer entirely.</p> |
| 116 | + |
| 117 | +<h2>What Wick does with CEF</h2> |
| 118 | + |
| 119 | +<p>Wick Pro embeds CEF for pages that need JavaScript rendering. The request flow:</p> |
| 120 | + |
| 121 | +<ol> |
| 122 | +<li>Wick receives a fetch request</li> |
| 123 | +<li>Cronet makes the initial HTTP request (Chrome TLS fingerprint)</li> |
| 124 | +<li>If JS rendering is needed, CEF loads the page in an embedded Chromium instance</li> |
| 125 | +<li>The rendered DOM is extracted and converted to clean markdown</li> |
| 126 | +<li>The result is returned to the agent</li> |
| 127 | +</ol> |
| 128 | + |
| 129 | +<p>No CDP at any point. The page sees a normal Chromium browser with a normal TLS fingerprint, normal JavaScript environment, and no automation artifacts.</p> |
| 130 | + |
| 131 | +<h2>When you still need CDP</h2> |
| 132 | + |
| 133 | +<p>CEF is better for content extraction — fetching and rendering pages. But CDP has legitimate advantages for <strong>interactive automation</strong>: clicking buttons, filling forms, navigating multi-step workflows. If you need to drive a browser through a complex UI flow, Playwright + CDP is the right tool.</p> |
| 134 | + |
| 135 | +<p>The distinction: <strong>reading the web</strong> vs <strong>acting on the web.</strong> For reading, you don't need a debug protocol. For acting, you do.</p> |
| 136 | + |
| 137 | +<p>Most AI agent use cases today are reading — fetching pages, extracting content, researching. That's where CEF shines and CDP is overkill.</p> |
| 138 | + |
| 139 | +<h2>Try it</h2> |
| 140 | + |
| 141 | +<p>The free version of Wick uses Cronet (Chrome's network stack without rendering) and handles most sites. For JS-heavy sites that need rendering, <a href="https://getwick.dev">Wick Pro</a> adds CEF at $20/month.</p> |
| 142 | + |
| 143 | +<pre><code>brew tap wickproject/wick && brew install wick && wick setup</code></pre> |
| 144 | + |
| 145 | +<h2>Further reading</h2> |
| 146 | +<ul> |
| 147 | +<li><a href="why-your-ai-agent-cant-read-the-web.html">Why Your AI Agent Can't Read the Web</a> — TLS fingerprinting explained</li> |
| 148 | +<li><a href="wick-on-apify.html">Wick is Now on Apify</a> — run it in the cloud without installing</li> |
| 149 | +<li><a href="wick-0-7-http-api.html">Wick 0.7: Local HTTP API</a> — use Wick from any language</li> |
| 150 | +</ul> |
| 151 | + |
| 152 | +<hr> |
| 153 | + |
| 154 | +<p><a href="https://github.com/wickproject/wick">GitHub</a> | <a href="https://getwick.dev/docs.html">Docs</a> | <a href="mailto:hello@getwick.dev">Contact</a></p> |
| 155 | + |
| 156 | +</article> |
| 157 | +</body> |
| 158 | +</html> |
0 commit comments