Cloudflare umgehen mit Puppeteer
Ausgangspunkt
Ich wollte eine Seite scrapen, die von Cloudflare geschützt wird. Ohne Proxy, ohne Browser – kein Durchkommen: 403 Forbidden, leere Antwort oder direkt cf-chl-bypass. Also: Headless-Browser muss her.
Ziel: Seite automatisch aufrufen, DOM lesen, JSON extrahieren. Kein massives Crawling, nur regelmäßiger Pull.
⚙️ Werkzeugwahl
Ich habe mich für Puppeteer entschieden, weil:
- Setup schnell gemacht ist
- Page-Steuerung einfach per JS
- Kein Overhead wie bei Selenium + Webdriver
Alternativen wie Playwright oder undetected-chromedriver habe ich später getestet, aber erstmal: Puppeteer pur.
Probleme
- Cloudflare blockt headless Chrome
→ trotz Wartezeit kommt nur Error-Seite navigator.webdriver = true
→ klarer Fingerabdruck für Bot-Erkennung- Fehlender User-Agent & Headers
→ Chrome ohne Styles, leerer Inhalt
Lösungsschritte
1. Headless deaktivieren
const browser = await puppeteer.launch({
headless: false,
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
2. navigator.webdriver entfernen
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'webdriver', {
get: () => false,
});
});
3. User-Agent + Header setzen
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64)...');
await page.setExtraHTTPHeaders({
'accept-language': 'de-DE,de;q=0.9',
});
4. Wartezeit einbauen + Screenshot prüfen
await page.goto(url, { waitUntil: 'networkidle2' });
await page.waitForTimeout(3000);
await page.screenshot({ path: 'proof.png' });
5. Proxy einbinden (wenn IP gebannt)
const browser = await puppeteer.launch({
headless: false,
args: [
'--proxy-server=http://user:[email protected]:8000',
],
});
Was ich gelernt habe
- Headless = sofort blockiert, egal wie nett die Headers sind
navigator.webdrivermuss raus, sonst hat man keine ChancewaitForTimeoutist oft nötig, um dynamisches JS abzuwarten
Bonus: Minimal-Skript
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.setUserAgent('Mozilla/5.0...');
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'webdriver', { get: () => false });
});
await page.goto('https://zielseite.com', { waitUntil: 'networkidle2' });
const html = await page.content();
console.log(html);
await browser.close();
})();
Fazit
Cloudflare ist nervig, aber nicht unknackbar – mit Browser-Automation kommt man fast immer durch. Headless = raus, Header + Delay = rein.
Test von 04/2025 – kann sich ändern, wenn Cloudflare ihre Detection-Logik anpasst.