Skip to content

Commit 39e63bc

Browse files
myleshortonclaude
andcommitted
Add blog post: Why CEF Beats CDP for Anti-Detection
Technical deep dive on why embedding Chrome's engine (CEF) is fundamentally better than controlling it via CDP (Playwright/Puppeteer) for anti-detection. Covers detection vectors, the censorship circumvention parallel, and when CDP is still the right choice. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6bfce79 commit 39e63bc

3 files changed

Lines changed: 170 additions & 0 deletions

File tree

site/blog/cef-vs-cdp.html

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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">&larr; 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 &mdash; Playwright, Puppeteer, Selenium, Browserbase, Browserless &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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 &mdash; 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> &mdash; TLS fingerprinting explained</li>
148+
<li><a href="wick-on-apify.html">Wick is Now on Apify</a> &mdash; 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> &mdash; 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>

site/blog/index.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@
4747
<h1>Wick Blog</h1>
4848
<p class="subtitle">Updates, guides, and deep dives from the team behind Wick.</p>
4949

50+
<a href="cef-vs-cdp.html" class="post">
51+
<div class="post-date">April 2, 2026</div>
52+
<div class="post-title">Why CEF Beats CDP for Anti-Detection</div>
53+
<div class="post-summary">Playwright, Puppeteer, and Browserbase all control Chrome via CDP — a debug protocol that sites can detect. Wick Pro uses CEF to embed Chrome's engine directly, with no automation artifacts to fingerprint.</div>
54+
<span class="post-tag">deep dive</span>
55+
</a>
56+
5057
<a href="wick-on-apify.html" class="post">
5158
<div class="post-date">April 1, 2026</div>
5259
<div class="post-title">Wick is Now on Apify</div>

site/sitemap.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
<lastmod>2026-03-26</lastmod>
4141
<priority>0.9</priority>
4242
</url>
43+
<url>
44+
<loc>https://getwick.dev/blog/cef-vs-cdp.html</loc>
45+
<lastmod>2026-04-02</lastmod>
46+
<priority>0.9</priority>
47+
</url>
4348
<url>
4449
<loc>https://getwick.dev/blog/wick-on-apify.html</loc>
4550
<lastmod>2026-04-01</lastmod>

0 commit comments

Comments
 (0)