Browser automation seems deceptively simple on paper: open a page, locate a button selector, and invoke .click(). But when interacting with modern single-page applications protected by bot-mitigation engines (like Cloudflare Turnstile, DataDome, or Akamai), standard Puppeteer scripts immediately get blocked.
When developing TikTok-Streak—a utility designed to automate daily message streaks without manual mobile interaction—I had to address several subtle pitfalls.
1. Defeating Automation Fingerprinting
Standard Chromium instances launched via puppeteer.launch() leave dozens of obvious fingerprints:
navigator.webdriveris set totrue.- Default user-agent includes
HeadlessChrome. - Missing audio context codecs and hardware acceleration flags.
- Suspiciously consistent mouse trajectories and zero-latency keyboard inputs.
Using puppeteer-extra and puppeteer-extra-plugin-stealth helps patch standard JavaScript leaks, but behavioral timing is equally important:
// Adding human-like typing jitter
async function humanType(page, selector, text) {
await page.focus(selector);
for (const char of text) {
await page.keyboard.type(char);
// Random delay between 40ms and 140ms per keystroke
await new Promise((r) => setTimeout(r, Math.floor(Math.random() * 100) + 40));
}
} 2. Stateless Authentication via Cookie Injection
Entering email/password credentials or solving 2FA captchas programmatically on every execution is a surefire way to trigger account locks.
Instead, the cleanest approach is extracting active session cookies (sessionid, sid_guard) and persisting them into an encrypted JSON file. On boot, the bot loads the cookies into the browser context before navigating:
import fs from 'fs/promises';
async function restoreSession(page, cookiePath) {
const raw = await fs.readFile(cookiePath, 'utf-8');
const cookies = JSON.parse(raw);
await page.setCookie(...cookies);
} This bypasses login forms entirely, landing directly on authenticated messaging endpoints.
3. Managing Headless Chrome Memory Leaks
Chromium instances consume massive amounts of RAM over time. If a background process runs for weeks without terminating browser instances, it will quickly exhaust available system memory.
Best practices for long-running automation bots:
- Ephemeral Contexts: Launch the browser, complete the task, close the browser immediately (
await browser.close()). - Resource Blocking: Block unnecessary assets such as images, web fonts, and tracking pixels using request interception to save bandwidth and memory:
await page.setRequestInterception(true);
page.on('request', (req) => {
if (['image', 'stylesheet', 'font', 'media'].includes(req.resourceType())) {
req.abort();
} else {
req.continue();
}
}); By keeping tasks scoped, authenticating via session cookies, and blocking heavy assets, headless automation remains rock-solid and undetected.