Skip to content

Instantly share code, notes, and snippets.

@tegansnyder
Created February 23, 2018 02:41
Show Gist options
  • Save tegansnyder/c3aeae4d57768c58247ae6c4e5acd3d1 to your computer and use it in GitHub Desktop.
Save tegansnyder/c3aeae4d57768c58247ae6c4e5acd3d1 to your computer and use it in GitHub Desktop.
Preventing Puppeteer Detection

I’m looking for any tips or tricks for making chrome headless mode less detectable. Here is what I’ve done so far:

Set my args as follows:

const run = (async () => {

    const args = [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-infobars',
        '--window-position=0,0',
        '--ignore-certifcate-errors',
        '--ignore-certifcate-errors-spki-list',
        '--user-agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3312.0 Safari/537.36"'
    ];

    const options = {
        args,
        headless: true,
        ignoreHTTPSErrors: true,
        userDataDir: './tmp'
    };

    const browser = await puppeteer.launch(options);

I’m loading in a preload file that overrides some window.navigator globals:

    const preloadFile = fs.readFileSync('./preload.js', 'utf8');
    await page.evaluateOnNewDocument(preloadFile);
preload.js
// overwrite the `languages` property to use a custom getter
Object.defineProperty(navigator, "languages", {
  get: function() {
    return ["en-US", "en"];
  };
});

// overwrite the `plugins` property to use a custom getter
Object.defineProperty(navigator, 'plugins', {
  get: function() {
    // this just needs to have `length > 0`, but we could mock the plugins too
    return [1, 2, 3, 4, 5];
  },
});

I see there are some other things suggested here https://intoli.com/blog/making-chrome-headless-undetectable/ but I'm not 100% certain how to implement them in puppeteer. Any ideas tips or tricks?

@betogzo
Copy link

betogzo commented Mar 25, 2022

worked for me, now recaptcha isn't bothering me anymore. thanks!

@uzair004
Copy link

In above gist, passing some arguments won't work because those are deprecated i.e no-infobars won't hide chrome is updated by automated script info bars as chrome teams has removed this as security bug.
instead pass another array to launch method
ignoreDefaultArgs: ["--enable-automation"]

@lifeboatpres
Copy link

lifeboatpres commented Sep 22, 2022

" Object.defineProperty(navigator, 'webdriver', { get: () => false, }); " cant work,it is not enought ,because after that input " 'window' in navigator ",the result is 'True'. it still will be detected.

Better to use:

const newProto = navigator.__proto__;
delete newProto.webdriver;
navigator.__proto__ = newProto;

@Vordlex
Copy link

Vordlex commented Mar 20, 2023

" Object.defineProperty(navigator, 'webdriver', { get: () => false, }); " cant work,it is not enought ,because after that input " 'window' in navigator ",the result is 'True'. it still will be detected.

Better to use:

const newProto = navigator.__proto__;
delete newProto.webdriver;
navigator.__proto__ = newProto;

image
solve WebDriver (NEW) for me

@IggsGrey
Copy link

Works on localhost for me, fails on remote vps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment