Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Set Chrome’s language preference before creating the driver. Selenium passes Chromium’s intl.accept_languages preference through ChromeOptions, while --headless=new starts current headless Chrome:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("--headless=new")
options.add_experimental_option(
    "prefs",
    {"intl.accept_languages": "fr-FR,fr"},
)

driver = webdriver.Chrome(options=options)
try:
    driver.get("https://example.com/")
finally:
    driver.quit()

Replace fr-FR,fr with an ordered, comma-separated list such as en-US,en or de-DE,de. The preference affects browser-generated requests, but it does not force an application to display a particular translation.

What intl.accept_languages controls

intl.accept_languages is Chromium’s preference for the language list used in the Accept-Language HTTP request header. The first value is preferred, followed by fallbacks. Selenium’s Python Options object sends that preference to Chrome when the session starts.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For example, fr-FR,fr asks for French as used in France, then generic French. A server may respond in French, but it can also use cookies, a locale in the URL, an account setting, geolocation, or its own negotiation rules instead.

Complete headless Selenium example

Install the dependencies

Install Selenium in the Python environment used by your test runner:

python -m pip install -U selenium

You also need a compatible Chrome or Chromium installation. Modern Selenium can manage the driver in many environments; in pinned CI images, record the Chrome, Chromium and Selenium versions together so a later browser update does not silently change locale behavior.

Choose the language list and start a fresh session

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

LANGUAGES = "de-DE,de"

options = Options()
options.add_argument("--headless=new")
options.add_experimental_option(
    "prefs",
    {"intl.accept_languages": LANGUAGES},
)

# A new driver is important: preferences are read when Chrome starts.
driver = webdriver.Chrome(options=options)
try:
    driver.get("https://example.com/")
    print(driver.title)
finally:
    driver.quit()

Use a new WebDriver instance after changing the preference. Reusing an existing session will not reliably recreate the renderer processes with the new setting.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common language-list patterns

Value Typical intent
en-US,en US English, then generic English
de-DE,de German as used in Germany, then generic German
fr-FR,fr French as used in France, then generic French
ja-JP,ja Japanese as used in Japan, then generic Japanese
es-ES,es Spanish as used in Spain, then generic Spanish

Keep the order meaningful: Chrome treats the list as preference ordered. Do not add spaces unless your test intentionally models a header containing them; a compact comma-separated value is easiest to audit.

How to verify the actual language negotiation

Checking JavaScript alone is insufficient. A page can expose one language while the request header has been normalized, reduced, ignored, or overridden by application state.

Inspect browser-visible values as a diagnostic

language = driver.execute_script("return navigator.language")
languages = driver.execute_script("return navigator.languages")
print("navigator.language:", language)
print("navigator.languages:", languages)

These values help identify the browser’s effective language settings, but they are not proof of the exact wire header. Chrome’s Accept-Language reduction can affect both the HTTP header and the navigator.languages getter, and the behavior depends on Chrome version and rollout.

Verify at the server or network layer

Use a request-inspection endpoint you control, or a controlled test server that records incoming headers. Assert the observed Accept-Language value there. This catches cases where an application redirects, applies a cookie, or ignores negotiation.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For deterministic tests, clear or isolate cookies, avoid a URL that embeds a locale unless that is what you are testing, and start a new driver for each language scenario. A response body, redirect location, or server-side locale marker is usually a stronger assertion than a browser property.

Preference versus a DevTools request override

There are two different testing goals. Configure the preference when you want to model a user’s Chrome language list. Use a Chrome DevTools Protocol (CDP) network override only when you need narrowly scoped request instrumentation.

Approach Scope JavaScript visibility Persistence Best use
intl.accept_languages Broadly applies to browser-generated requests Normally reflected in navigator.language and navigator.languages, subject to reduction Chrome profile preference for the session Localized navigation and server content negotiation
CDP network override Request-level instrumentation Does not necessarily model the browser’s full language preference Override-specific and version-sensitive A targeted header experiment

Selenium exposes Chromium’s CDP commands, but the exact command and behavior must match the Chrome and Selenium versions in your suite. Treat a CDP header override as a request-level technique, not a replacement for setting the browser preference when testing locale behavior end to end.

Headless Chrome version guidance

Chrome 112 unified headless and headful Chrome: headless now uses the same implementation while creating platform windows that are not displayed. Current Selenium examples therefore use --headless=new. Chrome still documents the --headless flag, but avoid assumptions based on the obsolete “old headless” implementation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

From Chrome 132, the old implementation is distributed separately as the chrome-headless-shell binary. If a CI image depends on that binary, document it explicitly rather than assuming it behaves like current unified headless Chrome.

Why the expected language may not appear

The site chooses another locale

Servers can prioritize a cookie, URL parameter, account profile, geolocation, or an application default over Accept-Language. Remove those influences when testing HTTP negotiation, or include them deliberately when testing the application’s real precedence rules.

Chrome normalizes or reduces the header

Chromium composes the effective preference from selected and forced language lists and may normalize values. Chrome’s Accept-Language reduction can change what appears in the request and in JavaScript. Pin browser versions in CI and assert the server-observed result instead of assuming the configured string is transmitted byte for byte.

The preference was applied too late

Preferences are consumed during startup. Create a new driver after changing Options; do not expect an already-running session to adopt the new list.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The wrong preference key or value was used

The key is exactly intl.accept_languages. It takes a string such as fr-FR,fr, not a Python list and not an HTTP-header dictionary. Keep the preference inside add_experimental_option("prefs", ...).

The browser and driver are incompatible

A startup failure, session creation error, or inconsistent behavior can come from incompatible Chrome and driver versions or a stale CI image. Update or pin the pair, print their versions in CI logs, and rerun the same locale test in a clean session.

Testing several locales safely

Parameterize the language list, but create and destroy a driver for every case. This prevents cookies, local storage, service workers, and renderer state from leaking between locales:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

cases = [
    ("en-US,en", "English"),
    ("fr-FR,fr", "French"),
    ("de-DE,de", "German"),
]

for language_value, label in cases:
    options = Options()
    options.add_argument("--headless=new")
    options.add_experimental_option(
        "prefs",
        {"intl.accept_languages": language_value},
    )
    driver = webdriver.Chrome(options=options)
    try:
        driver.get("https://example.com/")
        observed = driver.execute_script("return navigator.languages")
        print(label, language_value, observed)
    finally:
        driver.quit()

For a real localization assertion, replace the diagnostic print with a server-side assertion or a check for a locale marker that your application intentionally exposes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Performance, reliability and reproducibility

  • Startup cost: a fresh Chrome process per locale is slower than reusing one browser, but it gives isolation and ensures the preference is loaded.
  • Parallel runs: use separate temporary profiles and independent driver instances. Shared profiles can carry cookies and language state across tests.
  • Network variability: redirects, cache state and delayed locale requests can make a page appear inconsistent. Wait for a meaningful application condition, not only document readiness.
  • Evidence: log Chrome version, Selenium version, configured language list, final URL and server-observed header for failures.
  • Scope: browser preferences affect browser-generated requests. They do not rewrite arbitrary requests made by application code or guarantee that every third-party service honors the value.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is a clean screenshot rather than a browser-locale test, ScreenshotNeo returns a page image or PDF with one request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

ScreenshotNeo also provides an MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. Every plan includes its features; the Free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000 shots.

See the ScreenshotNeo documentation for parameters and response details. A direct call looks like this:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Create a free ScreenshotNeo account to use the 1,000 monthly screenshots without a card.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently Asked Questions

Does setting intl.accept_languages translate the page automatically?

No. It communicates a preferred language to the browser and usually to servers through content negotiation. The application still decides whether and how to translate its response.

Can I change the language preference after Chrome has started?

Start a new WebDriver session with a new Options object. Preferences are read during startup, so changing Python data in an existing session is not a reliable way to change renderer behavior.

Is navigator.language enough to test Accept-Language?

No. Chrome can reduce or normalize language values, and a site can ignore them. Verify the header at a server or network layer when the wire value matters.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.