// Use some infrequently updated stealth plugins
const { chromium } = require('playwright');
const stealthPlugin = require('playwright-extra-plugin-stealth')();
const playwrightExtra = require('playwright-extra');
playwrightExtra.use(stealthPlugin);
// Manually mess with settings such as randomized user agents
const userAgents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/90.0',
];
const randomElement = (arr) => arr[Math.floor(Math.random() * arr.length)];
// Add yet more settings, such as proxies and headless:false
(async () => {
// Use a residential proxy
const proxyServer = 'http://username:password@residential-proxy-address:port';
const browser = await chromium.launch({
headless: false,
args: [`--proxy-server=${proxyServer}`],
});
// Mimic more settings, such as language, location and headers
const context = await browser.newContext({
viewport: { width: 1920, height: 1080 },
userAgent: randomElement(userAgents),
timezoneId: 'Europe/London',
locale: 'en-GB', // Set locale
permissions: ['geolocation'], // Optional: mimic geolocation permission
geolocation: { longitude: -0.12574, latitude: 51.50853 },
extraHTTPHeaders: {
'Accept-Language': 'en-GB,en;q=0.9',
'Referer': 'https://dash.cloudflare.com/',
},
});
const page = await context.newPage();
// Block unnecessary resources to improve performance
await page.route('**/*', (route) => {
const request = route.request();
if (['image', 'stylesheet', 'font', 'media'].includes(request.resourceType())) {
route.abort();
} else {
route.continue();
}
});
await page.goto('https://dash.cloudflare.com/login?lang=en-gb', { waitUntil: 'networkidle' });
// Add your own waits and humanized mouse movements
const acceptCookiesSelector = '#onetrust-accept-btn-handler';
await page.waitForSelector(acceptCookiesSelector, { state: 'visible' });
const acceptCookiesButton = await page.$(acceptCookiesSelector);
await page.mouse.move(
(await acceptCookiesButton.boundingBox()).x + 5,
(await acceptCookiesButton.boundingBox()).y + 5
);
await acceptCookiesButton.click();
console.log('Accepted cookies');
// Try and make your typing not robotic
const emailFieldSelector = "form [data-testid='login-input-email']";
await page.waitForSelector(emailFieldSelector, { state: 'visible' });
await page.fill(emailFieldSelector, 'test@browserless.io', { delay: 100 });
console.log('Typed email');
const passwordFieldSelector = "form [data-testid='login-input-password']";
await page.waitForSelector(passwordFieldSelector, { state: 'visible' });
await page.fill(passwordFieldSelector, 'StrongPassword', { delay: 100 });
console.log('Typed password');
// Yet more delays and checks
const loginButtonSelector = '[data-testid="login-submit-button"]';
await page.waitForSelector(loginButtonSelector, { state: 'visible' });
await page.click(loginButtonSelector, { delay: 100 });
console.log('Clicked login button');
// Somehow click the Verify Human button that's hidden in the shadow DOM
await browser.close();
})();