Giorgio
Giorgio

Reputation: 13539

How to specify browser language in Puppeteer

I would like to launch a Google Chrome browser with language Spanish es using Puppeteer.

I've tried puppeteer.launch(args:['--lang=es',...],...) but it didn't work.

I've tried passing the environment variable LANGUAGE=es mocha puppeteer-test.js but it didn't work.

I've tried using the userDataDir option and passing a folder with a Preferences file a { "intl": { "accept_languages": "es" } } but the browser Settings - Languages still don't show Spanish and neither does window.navigator.languages neither window.navigator.language

I'm using
Puppeteer 0.11.0
Node 8.4.0
NPM 5.2.0
macOS El Capitan 10.11.6
MacBook Pro Retina, 15-inch, Mid 2015

Upvotes: 29

Views: 34450

Answers (7)

kaikuchn
kaikuchn

Reputation: 795

Another reason why your browser may not pick up the language despite passing a --lang flag is, that support for that language could be missing. I had to install chromium-l10n on Debian Bookworm to get Chromium 133 to switch to German.

Upvotes: 0

Samuel
Samuel

Reputation: 6490

I've been using --lang=.. that worked nearly everywhere: locally on my windows and in a docker instance on WSL ubuntu. On a hyper-v teamcity agent, where I started executing unit tests, I noticed that for whatever reason, setting the language failed.

I fixed in once, setting the ENV var LANG=xx to something but reckoned this was annoying and also did sometimes not work.

The fix was based on the list of command switches for chromium

Solution

Also add --accept-lang=XX to puppeteer startup args. This now seems to work. For german the startup code looks like:

 await puppeteer.launch(
            { 
                args: [
                    '--accept-lang=de',
                    '--lang=de'
                ]
            });

Upvotes: 2

zirkelc
zirkelc

Reputation: 1723

One more option using Chrome DevTools Protocol and Network.setUserAgentOverride:

const cdpSession = await page.createCDPSession();
cdpSession.send('Network.setUserAgentOverride', {
  userAgent: await browser.userAgent(),
  acceptLanguage: locale,
});

Upvotes: 0

jones1008
jones1008

Reputation: 167

Additional info to the accepted answer:

If you want to dynamically change the locale via the navigator.language property in puppeteer you need to pass your variable as an argument array as a second parameter of the evaluateOnNewDocument() function like this:

const locale = req.body.localization;

// add locale
await page.evaluateOnNewDocument((args) => {
    Object.defineProperty(navigator, "language", {
        get: function () {
            return args[0];
        }
    });
}, [locale]);

If you want to directly use the locale variable inside the evaluateOnNewDocument() function, it will be undefined and puppeteer will possibly render an empty page. Therefore you will need this workaround with the argument

Upvotes: 1

devside
devside

Reputation: 2217

On Chrome Linux, you can do

puppeteer.launch({ ...yourParams, env: { LANGUAGE: "fr_FR" } })

I don't know for the others OS/browsers ...

Upvotes: 2

Md. Abu Taher
Md. Abu Taher

Reputation: 18866

There are several ways to change locale, you can try all of them to find what works for you,

Use Args when launching

const browser = await puppeteer.launch({
    headless: false,
    args: ['--lang=bn-BD,bn']
});

Send the language as Header

await page.setExtraHTTPHeaders({
    'Accept-Language': 'bn'
});

Forcefully set the language

// Set the language forcefully on javascript
await page.evaluateOnNewDocument(() => {
    Object.defineProperty(navigator, "language", {
        get: function() {
            return "bn-BD";
        }
    });
    Object.defineProperty(navigator, "languages", {
        get: function() {
            return ["bn-BD", "bn"];
        }
    });
});

For the sake of testing, I'll test this in multiple languages, including es, and here is the result.

Google search:

es bn

BrowserLeaks:

enter image description here

Upvotes: 74

kaitlinsm
kaitlinsm

Reputation: 145

There's an error in Md-Abu-Taher's answer.

The response to navigator.language should return a string, not an array. Try it in your own browser console.

The code snippet should be:

await page.evaluateOnNewDocument(() => {
    Object.defineProperty(navigator, "language", {
        get: function() {
            return "en-GB";
        }
    });
    Object.defineProperty(navigator, "languages", {
        get: function() {
            return ["en-GB", "en"];
        }
    });
});

Upvotes: 8

Related Questions