Chrome Proxy Flags: --proxy-server and Beyond

To send Chrome's traffic through a proxy, launch it with the --proxy-server command-line switch, for example chrome --proxy-server="http://host:port". Add --proxy-bypass-list for hosts that should connect directly. For SOCKS5, add a host-resolver rule so DNS lookups don't leak. This guide covers each flag, the mistakes that make them silently fail, and how to run them in headless mode for scraping and automation.
TL;DR
--proxy-server="[scheme://]host:port"is the core flag. The scheme defaults to http if you omit it, and socks5 is supported.--proxy-bypass-listtakes a semicolon-separated list of host patterns that skip the proxy.- For SOCKS5, pair the proxy flag with
--host-resolver-rulesso Chrome doesn't resolve names locally. - Command-line switches are what you want for automation. The chrome://flags page is for experimental UI features. Check
chrome://versionto confirm what is actually applied.
Table of Contents
- Flags versus command-line switches
- --proxy-server: the core flag
- --proxy-bypass-list: keep some traffic direct
- SOCKS5 and the DNS leak
- Headless Chrome with a proxy
- Verify what Chrome is actually using
- Why the proxy behind the flag matters
- Our perspective: flags solve the plumbing, not the blocks
- Using Masklabs with Chrome flags
- A reference launch command
- FAQ
- Sources
Flags versus command-line switches
People search for "Chrome proxy flags" and usually mean one of two different things.
chrome://flags is a page of experimental features you toggle through the interface. Chrome's own documentation warns that changing them can cost you data or weaken security and privacy. There is no proxy toggle there that fits automated work.
Command-line switches are arguments you pass when you start the browser. --proxy-server is one of these. For scrapers, test runners and anything that must behave the same on every run, switches are the right tool, because they don't depend on whoever last clicked through a settings screen.
Why do switches exist for proxies at all? Chromium's design notes explain that Chrome normally follows system network settings. Proxy settings are the one area where users asked for an alternative, so command-line options were added. That is why you can give one Chrome instance its own proxy without changing the whole machine.

--proxy-server: the core flag
The syntax is:
--proxy-server="[scheme://]host:port"
The supported schemes are http, socks (equivalent to socks5), socks4 and socks5. Leave the scheme off and Chrome assumes http.
Here are examples for each platform.
# Linux
google-chrome --proxy-server="http://proxy.example.com:8080"
# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --proxy-server="http://proxy.example.com:8080"
# Windows (cmd)
"C:\Program Files\Google\Chrome\Application\chrome.exe" --proxy-server="http://proxy.example.com:8080"
On macOS and Windows, close every running Chrome window first. If a Chrome process is already running, a new launch can hand its arguments to the existing process instead of starting a fresh one with your flags.
Choosing the scheme
| Scheme | Use it when |
|---|---|
http:// | Your provider gives you an HTTP/HTTPS proxy endpoint. This is the most common case. |
socks5:// | You need a SOCKS5 endpoint, or the provider recommends it for non-HTTP traffic. |
socks4:// | Only for legacy endpoints. It has no remote DNS or authentication. |
The scheme describes how Chrome talks to the proxy. It has nothing to do with whether the target site is HTTP or HTTPS. HTTPS pages still work through an http:// proxy.
Authentication is not a flag
A common stumbling block: --proxy-server takes an address and port, not a username and password. A proxy that requires credentials will trigger an authentication prompt in a normal window. In headless runs, that prompt has nowhere to appear, so requests fail with a 407 error.
The usual fixes are on the automation side. Puppeteer exposes a page.authenticate() call, Playwright accepts credentials in its proxy launch option, and Selenium setups often use a small local forwarding proxy or an extension. Whichever you choose, keep credentials in environment variables rather than in scripts or shell history. If you work in Python, our Python scraping guide shows the pattern in code, and the Java version covers how to fix 407s.
--proxy-bypass-list: keep some traffic direct
Sometimes a few hosts shouldn't go through the proxy: localhost, an internal API, a metrics endpoint. Use --proxy-bypass-list alongside --proxy-server. It accepts a semicolon-separated list of host patterns that are accessed directly.
google-chrome \
--proxy-server="http://proxy.example.com:8080" \
--proxy-bypass-list="*.internal.example.com;localhost;127.0.0.1"
Two practical notes. First, quote the whole value, because an unquoted semicolon ends the command in most shells. Second, be deliberate about what you bypass in a scraping job. Every bypassed host exposes your real IP, so a stray pattern like *.google.com can quietly send some requests from your own network while the rest use the proxy.
The opposite switch is --no-proxy-server. It makes Chrome always connect directly and overrides any other proxy flags. It is useful as a quick control run: if a page loads with this flag and fails without it, the proxy is the cause.
SOCKS5 and the DNS leak
Setting --proxy-server="socks5://host:port" does not by itself guarantee that every name lookup goes through the proxy. Chrome's SOCKS documentation says to launch with two flags together: the proxy flag and a host-resolver rule. The rule blocks local DNS resolution for everything except the proxy's own hostname:
google-chrome \
--proxy-server="socks5://proxy.example.com:1080" \
--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE proxy.example.com"
Without the rule, background components such as the DNS prefetcher may still attempt resolutions on your own network. That matters in two ways. Your resolver sees which domains you visit, and the site can see a mismatch between your IP location and where the DNS query came from. For geo-targeted work, that mismatch is exactly what you are trying to avoid.

If you want to inspect DNS behavior outside the browser first, our curl proxy command guide walks through five commands for debugging it.
Headless Chrome with a proxy
The same switches apply in headless mode. You pass them either on the command line or through your automation library's launch arguments.
google-chrome --headless=new \
--proxy-server="http://proxy.example.com:8080" \
--user-data-dir=/tmp/chrome-proxy-test \
https://example.com
In Puppeteer, the equivalent is:
const browser = await puppeteer.launch({
headless: true,
args: ['--proxy-server=http://proxy.example.com:8080'],
});
const page = await browser.newPage();
await page.authenticate({
username: process.env.PROXY_USER,
password: process.env.PROXY_PASS,
});
In Selenium with Python, add the argument to ChromeOptions with options.add_argument('--proxy-server=http://proxy.example.com:8080'). Playwright prefers its own proxy option over raw flags, and it handles credentials for you.
Use a clean profile
Notice --user-data-dir in the first example. Chrome's documentation guidance is that testing proxy configurations should start from an isolated profile, so history, cookies and extensions from your daily browsing don't affect the result. An extension that manages proxies is a classic reason a flag appears to be ignored.
For tools built around this workflow, see our roundup of headless browser tools for proxy-ready workflows and the Selenium proxy walkthrough.
Verify what Chrome is actually using
When a flag doesn't seem to work, don't guess. Open chrome://version and read the Command Line field. It lists the effective flags the running browser was started with. If your --proxy-server isn't there, Chrome joined an existing process or your launcher dropped the argument.
Then confirm the exit IP. Load an IP-echo page through the browser and compare it with your own address. For a mobile proxy, also check the location and network type you expect.
A short troubleshooting list:
- Flag missing in chrome://version. Quit all Chrome processes, then relaunch with a fresh
--user-data-dir. - 407 Proxy Authentication Required. Supply credentials through your automation library, not the flag.
- ERR_PROXY_CONNECTION_FAILED. Check the host, port and scheme. A socks5 endpoint addressed with http:// fails this way.
- Right IP but wrong location in page results. Check DNS handling and your browser's language and timezone settings, which can contradict the proxy's location.
- Intermittent blocks. This is usually session design rather than flags. Our scraper success rate checklist covers silent failures.
Why the proxy behind the flag matters
The flag only tells Chrome where to send traffic. Whoever runs that endpoint can see the destination of your requests and, for unencrypted traffic, the content. The FTC has documented cases of providers misusing browsing and location data from people who trusted them with their network path.
Free public proxy lists are the riskiest source. Operators of open nodes can attempt man-in-the-middle attacks, and the FTC's public network guidance is a reminder to check for encryption rather than assume it. Lists like these are also a common place to meet phishing risks. For business-critical research, use an authenticated endpoint from a provider with clear data handling terms.
Our perspective: flags solve the plumbing, not the blocks
We see the same pattern with developers who come to us. They get --proxy-server working in an afternoon, then spend weeks wondering why a target still blocks or throttles them. The flag was never the problem.
The IP itself is what the site evaluates. Datacenter ranges are widely recognized, so requests from them can look automated before the first byte is parsed. That is why we built Masklabs on real US carrier IPs rather than datacenter addresses: the requests look like ordinary mobile traffic, which means fewer blocks and less throttling. Our published figures are about 99.9% uptime and a success rate above 99%.
The second lesson is session design. Rotating IPs suit broad collection where each request is independent. Sticky sessions suit anything with state, such as a login, a cart or a paginated flow, where changing IP mid-sequence breaks the job. We let you pick either per use case, and target 46 US cities so a price check or local search test comes from where the customer actually is.
The third is operational. Credentials should be self-serve, manageable per team, and visible in a usage dashboard, so no one is pasting a shared password into a launch script. You should be able to start without a sales call or a long contract.
My advice is to treat the Chrome flag as one line of config and spend your effort on IP quality, session type and verification.
— Jon
Using Masklabs with Chrome flags
Our endpoints support HTTP, HTTPS and SOCKS5, so everything above applies directly: pass the host and port from your dashboard to --proxy-server, add the host-resolver rule for SOCKS5, and handle credentials in your automation library. Our proxy API for browser automation article shows the integration in more detail.
Plans are billed monthly by data pool size, with a free trial of limited data to test your flags first. Pricing is Starter at $30.00 per month, Basic at $100.00, Advanced at $500.00 and Scale at $1,000.00. Billing is per byte, and you can add prepaid data by the GB. See the US mobile proxies on real carrier IPs page to get started.
A reference launch command
Putting the pieces together, this is a reasonable baseline for a SOCKS5 headless run:
google-chrome --headless=new \
--user-data-dir=/tmp/proxy-profile \
--proxy-server="socks5://proxy.example.com:1080" \
--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE proxy.example.com" \
--proxy-bypass-list="localhost;127.0.0.1" \
https://example.com
Before you scale it up, run it once headed, visit chrome://version, check the exit IP and test one target page. Then move it into your automation code. For a broader view of the workflow, see automated browsing and scraping and the rest of our mobile proxy guides.
FAQ
How do I open Chrome flags?
Type chrome://flags into the address bar. Those are experimental features, and Chrome warns that changing them can affect your data, security or privacy. For proxy setup, use command-line switches such as --proxy-server instead.
Can I put a username and password in --proxy-server?
The flag is designed for an address and port, so authentication belongs in your automation tool or a local forwarding proxy. Puppeteer, Playwright and Selenium each have their own approach. Avoid hardcoding credentials in scripts.
Does --proxy-server work in headless Chrome?
Yes. Pass it as a launch argument exactly as you would for a normal window. Add a separate --user-data-dir so your test starts clean, and check chrome://version in a headed run to confirm the flags.
How do I stop Chrome from using a proxy?
Launch it with --no-proxy-server. It forces direct connections and overrides other proxy flags. It is also a quick way to test whether a failure comes from the proxy.
Sources
- Chrome man page (reference build)
- Chromium network settings
- Configuring a SOCKS proxy server in Chrome
- What are Chrome flags? (Chrome for Developers)
- FTC: Avast privacy settlement
- FTC: Are public Wi-Fi networks safe?
- ChromeFlags list (juxtapix)