# Selenium static proxy setup for Chrome

> Selenium static proxy setup for Chrome: why a login in --proxy-server fails, and 2 tested fixes, IP allowlist or a local forwarder. No KYC, pay in crypto.

- URL: https://steadyproxy.com/guides/selenium-static-proxy/
- Last updated: 2026-10-19
- Publisher: SteadyProxy (https://steadyproxy.com)

Chrome takes a proxy host and port, not a login. Authorise your machine by IP, or let a small local forwarder add the login.

**Quick answer — How do I use a static proxy with Selenium and Chrome?**

For a Selenium static proxy in Chrome, do not put the username and password in --proxy-server: Chrome takes only a scheme, a host and a port there. Use one of two working methods. Authorise your machine in the proxy's IP allowlist, or run a small local forwarder that adds the login for Chrome. **SteadyProxy** login options: Username and password, or an IP allowlist (up to 10 IPs). Updated 19 October 2026.

## What are the key facts?

| Attribute | Value |
| --- | --- |
| Chrome switch | --proxy-server=http://host:port, with no field for a login |
| Method 1 | IP allowlist: up to 10 of your own IPs connect without a password |
| Method 2 | Local forwarder on 127.0.0.1:8899 adds the Proxy-Authorization header |
| Avoid | user:password inside --proxy-server; browser plug-ins of unknown origin |
| Check | Open api.ipify.org in the driven browser |
| Tested | Forwarder passed HTTPS and HTTP requests through a password-protected test proxy, 19 October 2026 |

## Why does Chrome reject credentials in the proxy URL?

Chrome's --proxy-server switch accepts a scheme, a host and a port. The Chromium network settings documentation shows no username or password in that format. When a proxy asks for a login, a person would see a sign-in box, but a script driven by Selenium cannot fill it reliably. So the login must happen outside Chrome: either the proxy trusts your machine's IP, or a helper on your machine sends the login for Chrome.

## How do I use the IP allowlist with Selenium?

This is the simplest method. Find your machine's public IP by opening api.ipify.org without the proxy. Add that IP to the allowlist of your SteadyProxy account; you can register up to 10 source IPs. Then pass only the host and port to Chrome. The example uses the HTTP port; SOCKS5 works the same way with socks5:// and the SOCKS5 port. Our [allowlisting guide](https://steadyproxy.com/guides/ip-allowlisting/) explains both directions of allowlisting.

*selenium_allowlist.py: Chrome with host and port only*

```python
"""Selenium + Chrome through a static proxy authorised by IP allowlist.

Install: python -m pip install selenium
Before running: add this machine's public IP to the allowlist of your account.
"""
import os

from selenium import webdriver
from selenium.webdriver.common.by import By

HOST = os.environ.get("PROXY_HOST", "gw.steadyproxy.com")
PORT = os.environ.get("PROXY_PORT", "7777")

options = webdriver.ChromeOptions()
# Host and port only: Chrome's --proxy-server switch has no field for a username or password
options.add_argument("--proxy-server=http://" + HOST + ":" + PORT)

driver = webdriver.Chrome(options=options)
try:
    driver.get("https://api.ipify.org?format=json")
    print("Exit IP:", driver.find_element(By.TAG_NAME, "body").text)
finally:
    driver.quit()

```

## How does a local forwarder add the login?

A local forwarder listens on 127.0.0.1, receives Chrome's proxy requests without a login, adds the Proxy-Authorization header and passes them to your static proxy. It uses the Python standard library only. It handles HTTPS through CONNECT tunnels, and plain http:// with one request per connection. Keep it bound to 127.0.0.1, so no other machine can use your proxy through it. We tested it on 19 October 2026 with curl over HTTPS and HTTP, through a test proxy that rejects requests without the right login.

*local_forwarder.py: 127.0.0.1:8899 to your static proxy*

```python
"""Local forwarder: Chrome -> 127.0.0.1:8899 (no login) -> static proxy (with login).

It adds the Proxy-Authorization header for you. Keep it bound to 127.0.0.1.
Run: python local_forwarder.py   (standard library only)
"""
import asyncio
import base64
import os

LISTEN_PORT = int(os.environ.get("LOCAL_PORT", "8899"))
UPSTREAM_HOST = os.environ.get("PROXY_HOST", "gw.steadyproxy.com")
UPSTREAM_PORT = int(os.environ.get("PROXY_PORT", "7777"))
CREDENTIALS = os.environ.get("PROXY_USER", "USERNAME") + ":" + os.environ.get("PROXY_PASS", "PASSWORD")
AUTH = "Proxy-Authorization: Basic " + base64.b64encode(CREDENTIALS.encode()).decode()
DROP = ("proxy-authorization:", "proxy-connection:", "connection:")


async def pipe(reader, writer):
    try:
        while data := await reader.read(65536):
            writer.write(data)
            await writer.drain()
    except ConnectionError:
        pass
    finally:
        writer.close()


async def handle(client_reader, client_writer):
    try:
        head = await client_reader.readuntil(b"\r\n\r\n")
    except (asyncio.IncompleteReadError, asyncio.LimitOverrunError):
        client_writer.close()
        return
    lines = head.decode("latin-1").split("\r\n")
    headers = [h for h in lines[1:] if h and not h.lower().startswith(DROP)]
    headers.append(AUTH)
    if not lines[0].upper().startswith("CONNECT "):
        headers.append("Connection: close")  # plain http:// - one request per connection
    try:
        up_reader, up_writer = await asyncio.open_connection(UPSTREAM_HOST, UPSTREAM_PORT)
    except OSError:
        client_writer.write(b"HTTP/1.1 502 Bad Gateway\r\nContent-Length: 0\r\n\r\n")
        client_writer.close()
        return
    up_writer.write(("\r\n".join([lines[0]] + headers) + "\r\n\r\n").encode("latin-1"))
    await up_writer.drain()
    await asyncio.gather(pipe(client_reader, up_writer), pipe(up_reader, client_writer))


async def main():
    server = await asyncio.start_server(handle, "127.0.0.1", LISTEN_PORT)
    print("Forwarding 127.0.0.1:%d -> %s:%d" % (LISTEN_PORT, UPSTREAM_HOST, UPSTREAM_PORT))
    async with server:
        await server.serve_forever()


if __name__ == "__main__":
    asyncio.run(main())

```

Start the forwarder in one terminal, then run Selenium with the local address. Chrome never sees the password, and the login stays in environment variables on your machine.

*selenium_forwarder.py: Chrome through the local forwarder*

```python
"""Selenium + Chrome through the local forwarder (username/password kept out of Chrome).

Start local_forwarder.py first, then run this file.
"""
from selenium import webdriver
from selenium.webdriver.common.by import By

options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=http://127.0.0.1:8899")

driver = webdriver.Chrome(options=options)
try:
    driver.get("https://api.ipify.org?format=json")
    print("Exit IP:", driver.find_element(By.TAG_NAME, "body").text)
finally:
    driver.quit()

```

## How do I run several static IPs with Selenium?

Run one forwarder per IP on its own local port, such as 8899, 8900 and 8901, each with that IP's credentials. Start one Chrome driver per port. With the IP allowlist, you skip the forwarders and pass each IP's host and port to its own driver. Give each driver its own --user-data-dir if it must keep cookies between runs. Check every driver with api.ipify.org before real work.

## Does the same problem exist with Firefox and Selenium?

Yes, in a similar form. Firefox reads proxy host and port from its preferences, and an HTTP proxy login appears as a dialog that automation cannot fill reliably. The same two methods work: the IP allowlist, or the local forwarder with Firefox's HTTP proxy set to 127.0.0.1 and port 8899. For a browser-automation tool with a built-in proxy login, see the [Playwright guide](https://steadyproxy.com/guides/playwright-static-proxy/).

## What else do people ask about Selenium and static proxies?

### Can I write http://user:password@host:port in --proxy-server?

It does not work reliably. Chrome's documented format for --proxy-server has no place for a login, so the credentials are not used. Requests then fail with a proxy authentication error or show a sign-in box. Use the IP allowlist or the local forwarder described on this page.

### Is a Chrome extension a good way to send the proxy login?

It can work, but it adds code with wide permissions to the browser you automate, and extension rules change between Chrome versions. The two methods here have no moving parts inside Chrome. If you use an extension, write it yourself or audit it, and keep it out of profiles used for other work.

### Is the local forwarder safe?

It listens only on 127.0.0.1, so only programs on your machine can use it. Anyone with access to your machine could use it too, as they could read your environment variables. Stop it when the job ends. It logs nothing by default; add logging only without the Proxy-Authorization header.

### How do I find the public IP to allowlist?

On the machine that runs Selenium, open https://api.ipify.org without the proxy. That is the address the proxy sees. If your office or server has a fixed IP, allowlist it once. A home connection whose IP changes is a poor fit; use the forwarder with a username and password instead.

### Does Selenium Wire or a similar library solve this?

Some libraries add proxy login to Selenium by running their own intercepting proxy, much like the forwarder here. Check that a library is still maintained before you depend on it. The forwarder on this page is about 60 lines of standard-library Python that you can read in full.

### How many IPs can I allowlist for Selenium machines?

Up to 10 source IPs on your SteadyProxy account, which covers most offices and server fleets. Our login options are: Username and password, or an IP allowlist (up to 10 IPs). If you run Selenium on more machines, route them through one server with a fixed IP, or use the forwarder with a username and password on each machine.

## Which sources does this guide use?

1. [Network settings (--proxy-server format)](https://www.chromium.org/developers/design-documents/network-settings/) — The Chromium Projects (2026-10-19)
2. [asyncio streams](https://docs.python.org/3/library/asyncio-stream.html) — Python Software Foundation (2026-10-19)
3. [Selenium WebDriver: Chrome options](https://www.selenium.dev/documentation/webdriver/browsers/chrome/) — Selenium (2026-10-19)

---

SteadyProxy: SteadyProxy is a static proxy provider: ISP (static residential) and dedicated datacenter IPs rented per IP for 30 days, paid in crypto with no ID upload.
