Referral Program
Development

Puppeteer Proxy Setup

Add rotating proxies to Puppeteer headless Chrome scraping.

Puppeteer controls headless Chrome for scraping JavaScript-heavy pages. Set the proxy at browser launch - all pages this browser instance opens will route through SotaProxy.

Setup guide

1

Install Puppeteer

bash
npm install puppeteer

Puppeteer installs a bundled version of Chromium automatically.

2

Launch with proxy

javascript
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    args: ['--proxy-server=http://proxy.sotaproxy.com:10000'],
  });

  const page = await browser.newPage();

  // Authenticate the proxy
  await page.authenticate({
    username: 'YOUR_USERNAME',
    password: 'YOUR_PASSWORD',
  });

  await page.goto('https://httpbin.org/ip');
  const content = await page.content();
  console.log(content);
  await browser.close();
})();

Set --proxy-server in launch args and call page.authenticate() with your credentials. Puppeteer requires credentials to be set per-page, not per-browser.

3

Geo-targeting

javascript
const browser = await puppeteer.launch({
  args: ['--proxy-server=http://proxy.sotaproxy.com:10000'],
});

const page = await browser.newPage();
await page.authenticate({
  username: 'YOUR_USERNAME_c_FR',  // French IP
  password: 'YOUR_PASSWORD',
});

Append _c_XX to the username in page.authenticate() to target a specific country.

Automate it with the SotaProxy API

Everything above works without opening the dashboard. With an API key, Puppeteer can pull fresh proxy credentials, buy new proxies, and renew expiring ones - straight from code.

javascript
const API = 'https://api.sotaproxy.com/api/v1'
const H = { Authorization: 'Bearer sk_live_your_key' }

// Every active proxy on your account - no copy-pasting credentials
const { proxies } = await (await fetch(`${API}/proxies`, { headers: H })).json()
const p = proxies[0]
const proxyUrl = `http://${p.login}:${p.password}@${p.ip}:${p.portHttp}`

// Buy more when you scale (price-check first with POST /quote)
await fetch(`${API}/orders`, {
  method: 'POST',
  headers: { ...H, 'Content-Type': 'application/json', 'Idempotency-Key': 'my-unique-order-id' },
  body: JSON.stringify({ product: 'ipv4', countryId: 565, periodId: '1m', quantity: 5 }),
})
Read the API docs

Why Puppeteer needs two steps

Chromium takes the proxy from a launch flag, and that flag has no place for credentials. Authentication happens afterwards, per page:

Rotating residential
login:password@proxy.sotaproxy.com:10000
Pinned to a country
login_c_US:password@proxy.sotaproxy.com:10000
Sticky for 15 minutes
login_c_US_s_42_ttl_15m:password@proxy.sotaproxy.com:10000
Static address (ISP, datacenter)
login:password@your-ip:50100, SOCKS5 on 50101

The proxy is set for the whole browser process, so one browser equals one address. Run several browsers when you need several identities in parallel.

One browser per address

Launch with the endpoint, then call page.authenticate before the first navigation:

Node: browser per identity

const puppeteer = require('puppeteer');

async function browserFor(sessionId) {
  const browser = await puppeteer.launch({
    args: ['--proxy-server=http://proxy.sotaproxy.com:10000'],
  });
  const page = await browser.newPage();
  await page.authenticate({
    username: `login_c_US_s_${sessionId}_ttl_1h`,
    password: 'password',
  });
  return { browser, page };
}

const { page } = await browserFor(7);
await page.goto('https://example.com', { timeout: 30000 });
  • Call authenticate on every new page, not once per browser. A page opened later starts unauthenticated and the first request comes back 407.
  • Use a separate user data directory per browser. Otherwise profiles share cookies and the address separation buys you nothing.
  • Close browsers you are done with. Each one holds an open connection to our endpoint, and a leak here looks like a rate limit later.
  • For many parallel identities, Playwright contexts are cheaper than Puppeteer browsers. Consider it when the count passes about ten.

Puppeteer specifics

Credentials in the launch flag do nothing

--proxy-server accepts a host and port only. Anything before the @ is dropped silently and you get 407.

One proxy per browser process

There is no per-context proxy. Rotating means launching another browser, which is why heavy rotation belongs in Playwright.

authenticate applies per page

New tabs and popups need their own call, and OAuth flows that open a popup break without it.

Headless detection is a separate problem

The proxy fixes the address, not the fingerprint. Pair it with stealth measures or an antidetect browser for account work.

Notes & tips

  • Puppeteer requires page.authenticate() for each new page. Playwright handles authentication at the browser level (simpler for multi-page sessions).
  • Consider puppeteer-extra and puppeteer-extra-plugin-stealth to reduce fingerprinting detection.
  • For high-volume scraping, consider Playwright instead - it handles multi-context proxy configuration more cleanly.

FAQ

What is the difference between Puppeteer and Playwright for proxy use?

Playwright supports proxy configuration at the browser context level (cleaner for multi-session setups). Puppeteer requires per-page authentication. Both work with SotaProxy.

Can Puppeteer handle CAPTCHA challenges?

Puppeteer cannot solve CAPTCHAs natively. Residential proxies reduce CAPTCHA frequency. For remaining challenges, integrate a CAPTCHA solving service (2Captcha, Anti-Captcha).

Get your proxy credentials

Sign up, top up your balance, and copy your endpoint into Puppeteer. Takes under 5 minutes.

Get started