Proxy Management for Browser Automation
Use this skill when setting up or troubleshooting proxy infrastructure for browser automation, web scraping, or multi-account systems.
Support files (shared with browser-automation skill):
references/proxy-and-detection.md— Proxy provider comparison, platform-specific anti-detection, email verification patternsreferences/proxyempire-rotation.md— ProxyEmpire residential proxy SID rotation pattern for IP cyclingreferences/provider-inventory.md— Active proxy/SMS provider accounts, balances, how to check each, what works/fails
Proxy Architecture
For multi-account systems, use sticky residential IPs — one dedicated IP per profile that persists across sessions. Rotating per-request triggers security flags.
Format: ip:port:username:password
Providers: Bright Data ($8/IP/mo), IPRoyal ($5/IP/mo), Oxylabs ($8/IP/mo), Proxy-Cheap ($3/IP/mo)
Proxy assignment pattern:
- Each profile gets a dedicated IP assigned on first use
- Proxy stays assigned until explicitly released
- Health tracking: 3 consecutive failures → mark unhealthy, rotate
- Fallback: if no healthy unassigned proxies, use least-failed proxy
Proxy config for Playwright:
# With auth
context_options["proxy"] = {
"server": f"http://{ip}:{port}",
"username": username,
"password": password,
}
# Without auth — add to launch args instead
args = [f"--proxy-server=http://{ip}:{port}"]
ProxyEmpire SID Rotation
ProxyEmpire residential proxies use a session-ID-in-username pattern:
session_id = f"sid-{uuid.uuid4().hex[:12]}"
username = f"r_{api_key}-country-ca-region-british+columbia-city-vancouver-{session_id}"
proxy = f"http://{username}:{password}@v2.proxyempire.io:5000"
When to rotate: Every scraping request (new SID = new IP). For account creation, use one SID per account to maintain IP consistency through the multi-step flow.
Credentials on file: ProxyEmpire key r_ffc0d9d520, password 70266b2665, endpoint v2.proxyempire.io:5000. Tested Jul 18 returned 407 — may be expired.
Provider Health Tracking
class ProxyPool:
def __init__(self):
self.proxies: dict[str, ProxyState] = {}
def assign(self, profile_id: str) -> str:
"""Assign least-used healthy proxy to profile"""
def mark_failure(self, proxy_id: str):
"""Track failures; 3 consecutive = unhealthy"""
def rotate(self, profile_id: str) -> str:
"""Release current, assign new"""
Pitfalls
- Cloudflare blocking: If a proxy triggers a Cloudflare challenge or CAPTCHA, the IP is burned for that platform. Mark it unhealthy, rotate to a new one, and slow down.
- Consistent fingerprints matter more than perfect ones: A profile that changes user agents or screen sizes between sessions triggers more flags than a mildly suspicious but consistent fingerprint.
- Geo consistency: Match proxy geo to account details. Canadian phone numbers with Canadian residential proxies — mismatched geo is a red flag.
- Sticky over rotating: Per-request IP rotation looks like a bot. One IP per session/profile is safer.