Why Puppeteer needs a proxy
Proxies for Puppeteer let the tool connect through a different IP address instead of always using the IP of the machine running it. This is useful for location-based tasks, testing, monitoring, and other jobs where the connection source matters.
Puppeteer still handles the main task. The proxy handles where the connection comes from.
What happens without one: IP bans, rate limits, geo walls
Without a proxy, websites keep seeing the same IP. As activity increases, that IP may hit a rate limit or get blocked.
Location can matter too. A page opened from Germany may not return the same content as one opened from the US.
A proxy for Puppeteer makes it possible to connect from different IPs and locations when needed.
Which proxy type to use with Puppeteer
The right proxy type depends on the job.
| Proxy type | Scraping | Account management | Testing | Monitoring |
|---|
| Residential | Good when location and IP source matter | Useful when accounts need residential IPs | Good for location-based testing | Useful for checking content from different locations |
| ISP | Good when a stable IP is needed | Useful for longer sessions on one IP | Good for testing with a consistent IP | Useful for ongoing checks from the same IP |
| Datacenter | Good for speed and larger request volumes | Better when residential IPs are not required | Good for general testing | Good for frequent automated checks |
Residential proxies are useful when the IP source and location matter. ISP proxies work well when the same IP needs to stay active for longer. Datacenter proxies make sense when the main focus is speed and scale.
The best option also depends on whether the task needs geo-targeting, a stable connection, or access to a larger pool of IPs.
How to connect a proxy in Puppeteer
The Puppeteer proxy setup needs the Geonode host, port, username, and password. Keep the credentials in environment variables, then load them when setting up the proxy in code.
Using Geonode? Get the username and password from Access Credentials and the host, port, and protocol from Proxy Server Information.
Settings path or code
For Puppeteer, pass the proxy host and port through --proxy-server when launching the browser:
import puppeteer from "puppeteer";
import "dotenv/config";
const browser = await puppeteer.launch({
headless: true,
args: [
`--proxy-server=http://${process.env.GEONODE_PROXY_HOST}:${process.env.GEONODE_PROXY_PORT}`,
],
});
Then create the page and provide the proxy credentials:
const page = await browser.newPage();
await page.authenticate({
username: process.env.GEONODE_PROXY_USER,
password: process.env.GEONODE_PROXY_PASS,
});
Keep the actual username and password in environment variables instead of putting them directly in the source file. This setup successfully returned HTTP 200 through the proxy in our test.
Authentication format host:port:user:pass
Geonode gives you four values:
proxy.geonode.io:PORT:USERNAME:PASSWORD
For Puppeteer, keep the values separate. Store them in environment variables:
GEONODE_PROXY_HOST=proxy.geonode.io
GEONODE_PROXY_PORT=9000
GEONODE_PROXY_USER=USERNAME
GEONODE_PROXY_PASS=PASSWORD
Load the host and port through --proxy-server, then authenticate the page:
const browser = await puppeteer.launch({
headless: true,
args: [
`--proxy-server=http://${process.env.GEONODE_PROXY_HOST}:${process.env.GEONODE_PROXY_PORT}`,
],
});
const page = await browser.newPage();
await page.authenticate({
username: process.env.GEONODE_PROXY_USER,
password: process.env.GEONODE_PROXY_PASS,
});
We tested this with valid credentials and received HTTP 200. With an incorrect password, the proxy returned HTTP 407 and:
Authentication error. Please check your authentication settings.
Rotation vs sticky session in Puppeteer
If the requests do not need to keep the same IP, use rotation.
For our test, we launched Puppeteer with the HTTP rotating port:
const browser = await puppeteer.launch({
headless: true,
args: ["--proxy-server=http://proxy.geonode.io:9000"],
});
const page = await browser.newPage();
await page.authenticate({
username: process.env.GEONODE_PROXY_USER,
password: process.env.GEONODE_PROXY_PASS,
});
We made five requests using fresh browser sessions:
Request 1: 108.31.182.167
Request 2: 45.186.93.125
Request 3: 109.254.131.42
Request 4: 109.153.11.141
Request 5: 37.113.173.139
Unique IPs: 5
Rotation: Yes
All five requests returned different IPs in this test. That confirms rotation worked during the run, but it does not guarantee a new IP for every future request.
If related requests need to stay on the same IP, use a sticky session instead. Use the sticky port and add the session details to the username:
const browser = await puppeteer.launch({
headless: true,
args: ["--proxy-server=http://proxy.geonode.io:10000"],
});
const page = await browser.newPage();
await page.authenticate({
username:
`${process.env.GEONODE_PROXY_USER}-session-blogpuppeteer01-lifetime-10`,
password: process.env.GEONODE_PROXY_PASS,
});
We made three requests using the same session:
Request 1: 178.64.64.40
Request 2: 178.64.64.40
Request 3: 178.64.64.40
Same IP: Yes
All three requests used the same IP.
See the Geonode guides for rotating proxies and sticky sessions for the available settings.
Common proxy errors in Puppeteer and how to fix them
If the proxy is not working, start with the connection details. Check the username and password, then the host, port, and protocol. The error returned by Puppeteer can usually help narrow down the problem.
407 Proxy Authentication Required
A 407 usually points to an authentication problem.
When we tested Puppeteer with an incorrect password, the proxy returned:
HTTP status: 407
Authentication error. Please check your authentication settings.
Check the username and password first. If they are correct, make sure page.authenticate() is called after creating the page.
ERR_TUNNEL_CONNECTION_FAILED / connection refused
A connection error usually means Puppeteer could not reach the proxy.
Check the host and port first. Then make sure the protocol matches the proxy server being used.
In our failed connection test, Puppeteer did not return ERR_TUNNEL_CONNECTION_FAILED. Using an unreachable proxy port returned:
net::ERR_CONNECTION_RESET at http://ip-api.com/json
The exact Chromium error can therefore differ depending on how the connection fails.
Timeouts and empty responses
A timeout means the page did not receive a response within the configured time.
First, check whether the target URL works and whether the proxy can connect. If both are working, check the timeout passed to page.goto().
For our test, we used a non-routable proxy with a five-second timeout:
await page.goto(url, {
timeout: 5000,
});
Puppeteer returned:
TimeoutError: Navigation timeout of 5000 ms exceeded
Setting an explicit timeout can help a script fail quickly when the proxy connection hangs.
ERR_NO_SUPPORTED_PROXIES
One Puppeteer-specific problem we found was putting the username and password directly inside --proxy-server.
This configuration failed:
--proxy-server=http://USERNAME:PASSWORD@proxy.geonode.io:9000
Puppeteer returned:
net::ERR_NO_SUPPORTED_PROXIES
The fix is to pass only the proxy server through the launch argument:
args: ["--proxy-server=http://proxy.geonode.io:9000"]
Then authenticate separately:
await page.authenticate({
username: process.env.GEONODE_PROXY_USER,
password: process.env.GEONODE_PROXY_PASS,
});
After changing the setup, the request succeeded with HTTP 200.
Puppeteer + Geonode: what you get
Puppeteer handles the requests or connections in the application. Geonode handles the proxy connection.
You can choose residential, ISP, or datacenter proxies based on the job, then use rotation, sticky sessions, and geo-targeting where needed. This keeps the proxy setup separate from the rest of the application code.
Plans vary by proxy type, with some options priced per GB.
FAQ
Does Puppeteer support SOCKS5 proxies?
Authenticated SOCKS5 did not work with the Puppeteer setup we tested.
We tried Geonode's SOCKS5 rotating port with page.authenticate(), but Puppeteer returned:
net::ERR_SOCKS_CONNECTION_FAILED
We also tried embedding the credentials in --proxy-server, which returned:
net::ERR_NO_SUPPORTED_PROXIES
Because none of the tested authenticated SOCKS5 configurations worked, the verified HTTP setup with --proxy-server and page.authenticate() is the safer option for this configuration.
Can I rotate IPs per request in Puppeteer?
Yes, Puppeteer can use a rotating proxy when the browser is launched through the rotating proxy configuration.
In our test, five fresh browser sessions returned five different IPs. That confirms rotation occurred during the test, but a different IP is not guaranteed for every request or browser session.
Is there a free trial?
Yes. Geonode offers a free trial, so the proxy can be tested with Puppeteer before moving to a paid plan. Check the current free trial and plans.
Where should I configure the proxy in Puppeteer?
Set the proxy host and port in puppeteer.launch() using --proxy-server.
Then call page.authenticate() after creating each page to provide the username and password:
const browser = await puppeteer.launch({
args: ["--proxy-server=http://proxy.geonode.io:9000"],
});
const page = await browser.newPage();
await page.authenticate({
username: process.env.GEONODE_PROXY_USER,
password: process.env.GEONODE_PROXY_PASS,
});
This was the configuration that worked in our tests.
Should I put the proxy username and password in --proxy-server?
No. Keep the credentials separate when using this Puppeteer setup.
Embedding USERNAME:PASSWORD@ directly in --proxy-server returned ERR_NO_SUPPORTED_PROXIES in our test. Passing only the host and port there, then using page.authenticate() for the credentials, worked successfully.