We use cookies to enhance user experience, personalize content, and analyze traffic. Cookie Policy

← Back to all articles

Selenium User Agent: How to Set, Change, and Verify

Set and verify a Selenium user agent in Python, change it safely between sessions, and avoid mismatches with browser and proxy fingerprints.

by Unknown Proxies

10 min read

July 31, 2026

Selenium User Agent: How to Set, Change, and Verify

A Selenium user agent is the browser identity string sent in the HTTP User-Agent request header and exposed to page JavaScript as navigator.userAgent. In Python with Chrome, set it before creating the driver by adding --user-agent=<value> to ChromeOptions, then verify the value inside the running browser.

Use an override for controlled compatibility testing, localization QA, or a site you are authorized to automate. Keep it stable for the life of the browser session. Changing one string does not reproduce another browser or device, grant access, or fix aggressive traffic; the viewport, client hints, cookies, browser engine, and network route still matter.

This guide shows the launch-time setup, verification steps, per-session rotation, mobile emulation, and practical debugging for a Selenium user agent in Python.

Selenium User Agent Quick Setup

Read the value from configuration rather than burying a browser version in source code:

import os

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


user_agent = os.environ["SELENIUM_USER_AGENT"]

options = Options()
options.add_argument(f"--user-agent={user_agent}")

driver = webdriver.Chrome(options=options)

try:
    driver.get("https://example.com")
    active_user_agent = driver.execute_script(
        "return navigator.userAgent"
    )
    print(active_user_agent)
finally:
    driver.quit()

Set SELENIUM_USER_AGENT to a maintained value that matches the browser and operating system in your approved test profile. Selenium's Options.add_argument() API passes command-line arguments to Chrome when WebDriver starts it.

The timing is important: add the argument before webdriver.Chrome(). The first navigation, redirects, page resources, and JavaScript then see the same launch-time override. If the browser is already running, changing the Python variable does nothing to that session.

Selenium user-agent setup and verification flow from configuration through ChromeOptions to the browser request

What the User Agent Changes—and What It Does Not

The User-Agent header identifies the client software and usually includes browser, rendering engine, operating system, and version tokens. MDN's User-Agent reference documents the common format and explains modern user-agent reduction.

In Selenium, a Chrome launch override normally changes two values you will notice first:

It does not change Chrome into Firefox, turn a desktop machine into a phone, or automatically align every browser-visible signal. A website can also observe viewport dimensions, touch support, language, time zone, cookies, WebGL behavior, and User-Agent Client Hints such as Sec-CH-UA-Platform and Sec-CH-UA-Mobile.

This distinction matters for testing. Chrome's DevTools documentation notes that overriding the user-agent string changes the content a server may return, not how Chrome functions internally. Use the override to test code paths keyed to a user agent, not as proof that you reproduced the advertised device.

For a broader view of request metadata, see the web scraping headers guide. It explains why browser-generated headers should remain consistent with the client that sends them.

Find Selenium's Default User Agent

Before overriding anything, record the browser default. That gives you a known-good baseline and prevents a stale copied string from becoming permanent configuration:

from selenium import webdriver


driver = webdriver.Chrome()

try:
    driver.get("https://example.com")
    print(driver.execute_script("return navigator.userAgent"))
finally:
    driver.quit()

The repository's user-agent checker provides a convenient browser-side readout of navigator.userAgent, client hints, language, viewport, and other visible values. It runs locally in the page, so it is useful for profile checks but does not capture the exact raw navigation header on the wire.

For network verification, send one request to an endpoint you control and inspect the incoming User-Agent header in its server logs. A controlled echo endpoint is better than guessing from the rendered page because it proves what the server actually received.

Compare the Expected and Active Values

Fail the test when Selenium launches with the wrong identity:

import os

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


expected_user_agent = os.environ["SELENIUM_USER_AGENT"]

options = Options()
options.add_argument(f"--user-agent={expected_user_agent}")

driver = webdriver.Chrome(options=options)

try:
    driver.get("https://example.com")
    actual_user_agent = driver.execute_script(
        "return navigator.userAgent"
    )
    assert actual_user_agent == expected_user_agent, (
        f"Expected {expected_user_agent!r}, "
        f"received {actual_user_agent!r}"
    )
finally:
    driver.quit()

An exact assertion is appropriate when the value comes from your own versioned test profile. If you are testing the browser default, assert capabilities or required tokens instead of pinning a complete string that changes with browser updates.

Change the Selenium User Agent Between Sessions

For most automation, “rotation” should mean selecting one approved profile for a new browser session—not replacing the identity on every navigation. A fresh driver also gives that profile a fresh cookie jar, storage partition, cache, and connection state.

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


approved_profiles = [
    "YOUR_MAINTAINED_DESKTOP_CHROME_UA",
    "YOUR_SECOND_MAINTAINED_DESKTOP_CHROME_UA",
]

for user_agent in approved_profiles:
    options = Options()
    options.add_argument(f"--user-agent={user_agent}")

    driver = webdriver.Chrome(options=options)
    try:
        driver.get("https://example.com/compatibility-test")
        print(driver.execute_script("return navigator.userAgent"))
    finally:
        driver.quit()

In production code, put the strings in a versioned configuration file or test matrix and validate them when browser packages are updated. Do not scrape random user-agent lists at runtime. A random string may advertise a browser version, device class, or operating system that the actual session cannot support.

Also avoid using a random choice when reproducibility matters. Map each test case to a named profile so a failure can be rerun with the same browser build, user agent, locale, viewport, and network conditions.

Can You Change It Without Restarting Chrome?

Chromium exposes Network.setUserAgentOverride through the Chrome DevTools Protocol (CDP), and Selenium exposes a Chromium-only execute_cdp_cmd() method. The CDP Network domain accepts a user-agent string plus optional language, platform, and user-agent metadata.

That route is useful for a narrow test that must change the header during one driver process. It is a poor default for unrelated stateful identities: existing cookies, storage, cache, tabs, service workers, and network connections remain in the session. Omitting userAgentMetadata can also leave Client Hints inconsistent with the new string.

Prefer a new driver for each complete profile. If your test requires CDP, apply the override before navigation, specify the related metadata required by the test, verify both JavaScript-visible values and captured request headers, and treat the implementation as Chromium-specific.

Use Mobile Emulation for a Mobile User Agent

Do not combine a mobile user agent with an ordinary desktop viewport and assume you now have a mobile test. ChromeDriver's mobile-emulation support can configure device metrics, touch behavior, client hints, and the user agent as one profile.

For a built-in device profile:

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


options = Options()
options.add_experimental_option(
    "mobileEmulation",
    {"deviceName": "Pixel 7"},
)

driver = webdriver.Chrome(options=options)

try:
    driver.get("https://example.com")
    print(driver.execute_script("return navigator.userAgent"))
    print(driver.get_window_size())
finally:
    driver.quit()

Device names depend on the installed Chrome and ChromeDriver versions. If a named profile is unavailable, configure explicit device metrics and client hints based on the ChromeDriver mobile-emulation documentation. That documentation also cautions that desktop emulation is not equivalent to a real device: hardware, GPU performance, mobile UI, and some APIs still differ.

Use physical devices or an appropriate device lab when those differences affect the result. Use mobile emulation when the test is about responsive layout, touch-oriented browser behavior, or content selection under a controlled emulated profile.

Comparison of a consistent Selenium browser profile with a mismatched mobile user agent and desktop browser signals

Keep the Browser Profile Consistent

A Selenium user agent is one component of a browser profile. Keep these values aligned within each stateful session:

Signal Keep it consistent with
User agent Actual browser family and a maintained version profile
User-Agent Client Hints Browser brand, version, platform, and mobile/desktop mode
Viewport and touch Intended desktop, tablet, or phone test
Language and time zone The locale scenario being tested
Cookies and storage One logical account or anonymous session
Proxy route The location and network identity for that session

Consistency improves test validity and troubleshooting. It does not guarantee access to a site, and it should not be used to misrepresent an unauthorized client. Review the site's terms, robots directives where applicable, and approved access methods before automating collection.

If the workflow is stateful, keep its cookie jar, user-agent profile, and network route fixed until the workflow ends. Start a separate session for a separate profile. This also makes failures attributable: you can tell whether a change came from the browser build, profile configuration, application state, or route.

Do You Need a Proxy With a Selenium User Agent?

No. A user-agent override changes browser identity metadata; a proxy changes the network route and source IP. You can test a Selenium user agent without a proxy, and changing the user agent will not repair proxy authentication, routing, or IP reputation.

Add a proxy only when an allowed workflow has a real network requirement, such as localization testing from a specific region, distributing independent monitoring jobs, or keeping a stable route for a browser session. The Python Selenium proxy guide covers launch-time routing, authentication, rotation, and 407 debugging separately.

When a proxy is required, apply both settings before starting the driver:

import os

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


options = Options()
options.add_argument(
    f"--user-agent={os.environ['SELENIUM_USER_AGENT']}"
)
options.add_argument(
    f"--proxy-server={os.environ['SELENIUM_PROXY_SERVER']}"
)

driver = webdriver.Chrome(options=options)

Keep credentials out of source code and logs. If the proxy uses authentication, follow the browser-compatible authentication pattern from the proxy guide rather than embedding secrets in diagnostics.

Troubleshoot a Selenium User Agent That Is Not Working

Change one variable at a time. Start from a direct, default browser session, record its behavior, then add only the user-agent override.

Symptom Likely cause First check
navigator.userAgent still shows the default Argument was added too late or not passed to the driver Print options.arguments before launch and create a fresh driver
JavaScript value changed but server behavior did not Response is based on another signal or cached state Inspect the raw request header, cookies, cache, and response classification
Mobile page has desktop layout Only the user-agent string changed Use mobile emulation with viewport, touch, and client hints
Test changes after a browser update Copied user-agent string is stale or profile support changed Record browser/driver versions and refresh the approved profile
Direct session works but proxied session fails Network route or proxy authentication issue Keep the user agent fixed and test the proxy separately
Server returns 403 or 429 Authorization, policy, reputation, or rate limits Inspect the response and slow down before changing identity fields

Confirm the Argument Reached Chrome

Print the options before launch during development:

print(options.arguments)

You should see one entry beginning with --user-agent=. If you build options in a helper, confirm that the same object is passed to webdriver.Chrome(options=options) and that a framework fixture does not replace it.

Verify Both Browser and Server Views

Check navigator.userAgent first, then capture the incoming request header on a test endpoint you control. The two should agree for the navigation. Also inspect low-entropy client hints in Chromium when the test depends on device or platform classification.

Do not rely only on a screenshot or page layout. A responsive site may render from viewport width while its server logs record the user agent independently.

Separate Access Errors From User-Agent Errors

A 403 Forbidden response does not prove that Selenium chose the wrong user agent. It may reflect missing authorization, cookies, a firewall rule, or an unsupported workflow. A 429 Too Many Requests response is a pacing signal; lower concurrency, honor Retry-After, and use bounded backoff.

Similarly, a 407 Proxy Authentication Required response belongs to the proxy layer. Keep the user agent constant while testing the route. The HTTP 403 guide and HTTP 429 guide provide separate diagnostic paths.

Selenium User Agent Checklist

Before running the test suite or browser job:

Frequently Asked Questions

How do I set a user agent in Selenium Python?

Create ChromeOptions, call options.add_argument(f"--user-agent={value}"), and pass those options to webdriver.Chrome(options=options). Set the value before the driver starts.

How do I get the current Selenium user agent?

After navigating, run driver.execute_script("return navigator.userAgent"). For complete verification, also inspect the raw User-Agent header at an endpoint you control.

Can I change the Selenium user agent without restarting?

Chromium supports a CDP user-agent override, but existing cookies, storage, cache, and other browser state remain. For separate identities, starting a fresh driver is more predictable and keeps the whole session isolated.

Should I rotate the user agent on every request?

No. A browser loads many resources and retains state across navigations. Keep one approved user-agent profile for one logical session, then rotate between independent sessions only when the test plan requires it.

Does a custom user agent hide Selenium?

No. It changes one browser identity string. It does not remove automation behavior or align every fingerprint signal, and it does not authorize access that a site has restricted.

Why does a mobile user agent still show a desktop page?

The site may use viewport size, touch capability, client hints, cookies, or account settings instead of the legacy user-agent string. Use ChromeDriver mobile emulation or a real device for a coherent mobile test.

Conclusion

A reliable Selenium user agent setup is simple: configure the value before Chrome starts, verify it from both the browser and server sides, and keep it stable for the session. Use a fresh driver when changing complete profiles, and use mobile emulation when device behavior—not just a header—is under test.

Treat the Selenium user agent as one test input rather than a universal access fix. Align it with the browser, client hints, viewport, cookies, locale, and proxy route, then diagnose authorization, rate limits, and network failures independently.

About the Author

Unknown Proxies

Proxy Infrastructure Team

Stay Unknown

High-performance dedicated proxies optimized for speed and reliability. Get uncompromising quality, 99.9% uptime, and unmatched support. Stay Unknown.

Explore Plans