Before you start
You'll need a Geonode account, Node.js and Puppeteer installed, and an endpoint from the Geonode dashboard. In the dashboard's proxy configuration, choose the product (residential, ISP or datacenter), the session type (rotating or sticky), your target location, and the host:port:username:password format. Store the values in environment variables:
export GEONODE_HOST="<host>"
export GEONODE_PORT="<port>"
export GEONODE_USER="<username>"
export GEONODE_PASS="<password>"This guide focuses on the Geonode specifics. For Puppeteer proxy concepts in depth, see our pillar guide to Puppeteer proxies.
The simplest setup
import puppeteer from 'puppeteer';
const { GEONODE_HOST, GEONODE_PORT, GEONODE_USER, GEONODE_PASS } = process.env;
const browser = await puppeteer.launch({
args: [`--proxy-server=http://${GEONODE_HOST}:${GEONODE_PORT}`],
});
const page = await browser.newPage();
await page.authenticate({ username: GEONODE_USER, password: GEONODE_PASS });
await page.goto('https://api.ipify.org');
console.log('Exit IP:', await page.evaluate(() => document.body.innerText));
await browser.close();Chrome ignores credentials in --proxy-server, so page.authenticate() supplies them. Call it on every new page before navigating.
One proxy session per browser context
For anything beyond a single page, give each job its own browser context with its own Geonode session. That keeps identities separate and guarantees a fresh connection (and so a fresh exit IP) per context.
async function geonodeContext(browser, { country } = {}) {
const ctx = await browser.createBrowserContext({
proxyServer: `http://${GEONODE_HOST}:${GEONODE_PORT}`,
});
const page = await ctx.newPage();
const username = country ? `${GEONODE_USER}-country-${country}` : GEONODE_USER;
await page.authenticate({ username, password: GEONODE_PASS });
return { ctx, page };
}Geonode's documentation shows location targeting as username suffixes such as -country-jp. If the endpoint generator gives you a different format, follow the dashboard.
Rotating vs sticky
- Rotating endpoints give a new IP per connection. Combined with a new context per job, each job gets a fresh exit.
- Sticky endpoints keep the same IP for a configured lifetime (Geonode lists up to 24 hours). Use them for logins, carts and multi-page flows: one sticky session per context, and close the context when the flow ends.
Matching the browser to the exit
Set timezone and language to fit the exit country:
const { ctx, page } = await geonodeContext(browser, { country: 'de' });
await page.emulateTimezone('Europe/Berlin');
await page.setExtraHTTPHeaders({ 'Accept-Language': 'de-DE,de;q=0.9' });Launch with --force-webrtc-ip-handling-policy=disable_non_proxied_udp to prevent WebRTC leaks.
Proxy tip: Before scaling, run a short pilot on your real targets with Geonode and record success rate, latency and GB per result. Our our complete Geonode guide explains which Geonode product to start with.
Saving bandwidth
Residential traffic is billed per GB, so block what you don't need:
await page.setRequestInterception(true);
page.on('request', (r) =>
['image', 'media', 'font'].includes(r.resourceType()) ? r.abort() : r.continue()
);Test that blocking doesn't hurt success on your target, since some bot protection checks that assets loaded.
Retries and block detection
Treat a page as successful only if it contains the content you expect. On failure, close the context and retry with a new one (and therefore a new session), with a short backoff and a cap on attempts. See the production pattern in Puppeteer proxies.
Using Geonode ISP proxies
ISP proxies are static IPs. Use each one as a proxyServer for a context that represents one identity, with the credentials Geonode provides. Keep the mapping between identities and IPs stable. See Geonode ISP proxies.
Troubleshooting
| Problem | Likely cause | Fix |
|---|---|---|
| 407 Proxy Authentication Required | page.authenticate() missing or called after navigation; wrong username format | Authenticate first; copy the username from the dashboard |
ERR_TUNNEL_CONNECTION_FAILED | Wrong host or port, or the target refused through the proxy | Check endpoint; test with cURL |
| Same IP across contexts with rotating endpoint | Connection reuse | Use a new context per job |
| Exit in wrong country | Targeting not in username | Use the dashboard's targeted endpoint |
| High bandwidth | Images, media and scripts loading | Block resources; prefer HTTP clients where possible |
To isolate problems, run the same endpoint through cURL first. See Geonode with cURL.
A checklist before scaling a Puppeteer job on Geonode
Before you go from a working script to thousands of pages a day, run through this list:
- Product per domain: confirm each target actually needs residential. Datacenter traffic is far cheaper where it works.
- Context per job: every job gets its own browser context and Geonode session, closed when finished.
- Authentication on every page, including pop-ups and new tabs you intend to use.
- Location consistency: timezone and
Accept-Languagematch the exit; WebRTC restricted. - Bandwidth controls: images, media and fonts blocked where safe; third-party trackers blocked.
- Block detection: success means the expected content is present, not just a 200 status.
- Retry policy: new context, short backoff, capped attempts.
- Concurrency limits per domain, increased gradually while success holds.
- Monitoring: success rate, median and p95 page time, bytes per successful page, retries per success.
- Credentials: stored in environment variables, masked in logs, separate per environment.
Each item prevents a specific, common failure: surprise bandwidth bills, sudden blocks, leaked credentials or silent data gaps. Our pillar guide to Puppeteer proxies covers each one in depth, including a production-ready pattern and a test harness.
Quick self-test
Keep a short script in your repository that launches Puppeteer, opens two contexts on a rotating Geonode endpoint and prints the exit IP for each, then opens one context on a sticky endpoint and prints its IP twice. Different IPs for the first two and a repeated IP for the third confirm that authentication, rotation and sessions all work. Run it after every Puppeteer or Chrome upgrade and whenever you change proxy settings.
FAQ
Do I need page.authenticate() with Geonode?
Yes, unless you've whitelisted your server's IP in Geonode, in which case the proxy accepts connections without credentials.
How do I get a new IP for each page?
Use a rotating endpoint and a new browser context per page or job.
Can I use SOCKS5 with Puppeteer and Geonode?
Chrome doesn't support SOCKS5 authentication, so use IP whitelisting or a local forwarder. HTTP is simpler.
Which Geonode product is best for Puppeteer?
Rotating residential for scraping protected sites, sticky residential or ISP for logged-in flows, datacenter for lenient targets.
Editorial note: Proxy providers change their pools, features and prices often, so treat any figures here as typical ranges at the time of writing and confirm current terms with the provider before you buy.