Browser Automation with Playwright and Proxies

Browser automation creates a much louder fingerprint than plain HTTP requests because the target sees full page loads, scripts, cookies, and multi-step navigation. Proxy choice matters most when the browser must log in, keep state, or repeat actions without looking like one obvious datacenter bot.

Guardrail: keep the browser proxy server set to the exact endpoint shown in your portal. Add stickiness or provider selection in the username field instead of inventing alternate hosts or ports.

What browser automation needs from a proxy

  • Sticky identity across login, navigation, form submission, and follow-up page loads.
  • Residential traffic when the target is sensitive to automation and datacenter routing.
  • Predictable proxy auth that works in the browser launch configuration.
  • Deliberate session turnover so one long automation run does not poison future runs.

Which NinjaProxy product fits and why

Proxy setupBest forWhy
Sticky residential sessionPlaywright login flows, carts, and multi-step account actionsOne stable residential route reduces breakage when the site expects the same client through the whole flow.
Rotating residentialShort-lived browser runs that should look unrelatedFresh residential routes are a better fit when each run is independent and should not share identity.
ISP/staticLong-lived browser jobs that need one stable IP over timeStatic identity is useful when a partner system or allowlist expects a consistent origin.

Working code example

This Playwright example keeps the gateway endpoint fixed and places stickiness in the proxy username. That matches the currently documented authentication flow for rotating gateways.

import { chromium } from "playwright"

const browser = await chromium.launch({
  proxy: {
    server: "http://<ROTATING_HTTP_ENDPOINT>",
    username: "<USERNAME>--session-browser-run-01--duration-300--provider-res",
    password: "<API_KEY>",
  },
})

const page = await browser.newPage()
await page.goto("https://example.com/login", { waitUntil: "networkidle" })
await page.fill('input[name="email"]', "[email protected]")
await page.fill('input[name="password"]', "super-secret")
await page.click('button[type="submit"]')
await page.waitForLoadState("networkidle")
console.log(await page.title())
await browser.close()

Common failure modes

FailureLikely causeFix
Login breaks between stepsThe browser changed routes mid-flow.Use a sticky session token and a duration long enough to cover the full run.
Automation gets challenged immediatelyDatacenter traffic is too easy for the target to flag.Move the workflow to residential traffic and reduce run parallelism.
Proxy auth fails in PlaywrightThe endpoint, username, or password fields are malformed.Use the exact portal endpoint in server and keep controls only in username.
Every run reuses the same IP unexpectedlyThe same session token is being reused across jobs.Generate a fresh session token per job when you want route rotation between runs.

Related docs