# Selenium

Source: https://docs.evomi.com/proxy-instructions/integration-guides/selenium/

This guide explains how to use Evomi proxies with Selenium for browser automation in Python. Since Selenium does not natively support authenticated proxies, we use a lightweight Chrome extension to handle proxy credentials automatically.

## Prerequisites

- Python 3.8+ installed
- Google Chrome installed
- Your Evomi proxy credentials (username and password)

## Installation

Install Selenium using pip:

```bash
pip install selenium
```

You do **not** need to download ChromeDriver manually. Since Selenium 4.6+, Selenium Manager automatically downloads and manages the correct driver version for your installed Chrome browser.

## Configuration

Standard Selenium can set a proxy via `--proxy-server`, but it does not support username/password authentication. To work around this, we dynamically create a small Chrome extension that injects the credentials.

```python
import zipfile
import os
import tempfile
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

proxy_host = "rp.evomi.com"
proxy_port = 1000
proxy_user = "your_username"
proxy_pass = "your_password_session-anychars_mode-speed"

manifest_json = """{
    "version": "1.0.0",
    "manifest_version": 3,
    "name": "Evomi Proxy Auth",
    "permissions": ["proxy", "webRequest", "webRequestAuthProvider"],
    "host_permissions": ["<all_urls>"],
    "background": {"service_worker": "background.js"}
}"""

background_js = """
chrome.proxy.settings.set({
    value: {
        mode: "fixed_servers",
        rules: {
            singleProxy: {
                scheme: "http",
                host: "%s",
                port: %d
            },
            bypassList: ["localhost", "127.0.0.1"]
        }
    },
    scope: "regular"
});

chrome.webRequest.onAuthRequired.addListener(
    function(details) {
        return {
            authCredentials: {
                username: "%s",
                password: "%s"
            }
        };
    },
    { urls: ["<all_urls>"] },
    ["blocking"]
);
""" % (proxy_host, proxy_port, proxy_user, proxy_pass)

plugin_dir = tempfile.mkdtemp()
plugin_file = os.path.join(plugin_dir, "evomi_proxy.zip")

with zipfile.ZipFile(plugin_file, "w") as zp:
    zp.writestr("manifest.json", manifest_json)
    zp.writestr("background.js", background_js)

chrome_options = Options()
chrome_options.add_extension(plugin_file)

driver = webdriver.Chrome(options=chrome_options)
driver.get("https://ip.evomi.com/s")
print(driver.find_element("tag name", "body").text)

driver.quit()
os.remove(plugin_file)
os.rmdir(plugin_dir)
```

Replace `your_username` with your Evomi username and `your_password` with your actual password (keeping the `_session-anychars_mode-speed` parameters).

## Explanation

1. **Manifest V3 extension**: We create a minimal Chrome extension using Manifest V3 (the current Chrome extension standard). It requests `proxy`, `webRequest`, and `webRequestAuthProvider` permissions.
2. **Proxy configuration**: The `background.js` service worker calls `chrome.proxy.settings.set()` to route all traffic through the Evomi proxy.
3. **Authentication**: The `onAuthRequired` listener intercepts proxy authentication challenges and automatically supplies your credentials.
4. **Extension loading**: The extension is packaged as a ZIP file and loaded into Chrome via `chrome_options.add_extension()`.
5. **Verification**: We navigate to `https://ip.evomi.com/s` which returns the IP address seen by the server -- this should be the proxy IP.
6. **Cleanup**: The temporary extension file is removed after the driver quits.

## Using SOCKS5

For SOCKS5 proxies, modify the `singleProxy` configuration in `background_js`:

```python
background_js = """
chrome.proxy.settings.set({
    value: {
        mode: "fixed_servers",
        rules: {
            singleProxy: {
                scheme: "socks5",
                host: "%s",
                port: %d
            },
            bypassList: ["localhost", "127.0.0.1"]
        }
    },
    scope: "regular"
});
// ... rest of the onAuthRequired listener stays the same
"""
```

## Headless Mode

The extension-based approach does **not** work with `--headless=new` because Chrome's headless mode does not support extensions. If you need headless operation with an authenticated proxy, consider using Playwright instead (which has built-in proxy authentication support).

## Evomi Proxy Endpoints

| Proxy Type | HTTP | HTTPS | SOCKS5 |
|---|---|---|---|
| **Residential** | `rp.evomi.com:1000` | `rp.evomi-proxy.com:1001` | `rp.evomi.com:1002` |
| **Mobile** | `mp.evomi.com:3000` | `mp.evomi-proxy.com:3001` | `mp.evomi.com:3002` |
| **Datacenter** | `dcp.evomi.com:2000` | `dcp.evomi-proxy.com:2001` | `dcp.evomi.com:2002` |

HTTPS endpoints use the `evomi-proxy.com` domain — that is the hostname our TLS certificate covers, and it reaches the same servers. A client that verifies certificates will reject the `evomi.com` form on the HTTPS port.

## Running the Script

Save the script (e.g., `selenium_proxy_test.py`) and run:

```bash
python selenium_proxy_test.py
```

A Chrome window will open, navigate through the proxy, and print the proxy IP to your console.

## Tips and Troubleshooting

- **Credentials**: Double-check your proxy host, port, username, and password. The password format is `your_password_session-anychars_mode-speed`.
- **Chrome version**: Ensure you have a recent version of Chrome installed. The Manifest V3 extension approach requires Chrome 105+.
- **Extension disabled flag**: If Chrome blocks the extension, you may need to add `chrome_options.add_argument("--disable-features=DisableLoadExtensionCommandLineSwitch")`.
- **Firewall/antivirus**: Some security software may interfere with the proxy extension. Add Chrome as an exception in your security software or temporarily disable it to test.
- **Alternative -- SeleniumBase**: The [SeleniumBase](https://github.com/seleniumbase/SeleniumBase) framework has built-in proxy authentication support and can be a simpler option if you are starting a new project.
