Ever deployed a feature that worked perfectly locally, only to discover users in specific countries couldn’t access it?
Or received complaints about geo-restricted content appearing where it shouldn’t?
I’ve been there. Tests passed on my machine, but production users in Europe and Asia hit blocked checkout flows. The problem? I never tested from different geographic locations.
The solution?
A proxy server acts as an intermediary between the browser and the internet, masking the original IP address and routing requests through a different network path.
Overview
A proxy is defined inside the launch options and can include authentication if required.
const { chromium } = require(‘playwright’);
(async () => {
const browser = await chromium.launch({
proxy: {
server: ‘http://proxy-ip:port’, // Example: ‘http://pr.oxylabs.io:7777’
username: ‘proxy_user’, // Optional for authenticated proxies
password: ‘proxy_pass’ // Optional for authenticated proxies
}
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto(‘https://example.com’); // Routed through proxy
await browser.close();
})();
server: The proxy server address in http://ip:port or https://ip:port formatusername and password: Optional. Only used when the proxy requires authentication
What Is a Proxy and Why Use One in Playwright?
A proxy server sits between your Playwright scripts and target websites. Instead of connecting directly, your requests route through the proxy first, which then forwards them to the destination.
Why Do Testers Use Proxies?
- Geo-Location Testing: Test how your app behaves for users in different countries. Verify geo-restricted content, localized pricing, and regional compliance without traveling.
- Avoid Rate Limits: Distribute requests across multiple IP addresses to prevent blocking or throttling during large-scale automation.
- Privacy and Security: Mask your actual IP address when testing sensitive applications or conducting competitive analysis.
- Corporate Requirements: Many enterprises require all traffic to route through corporate proxies for security auditing and compliance.
- Internal Testing: Access and test applications behind firewalls or simulate specific network environments.
While understanding proxy use cases is crucial, setting up and managing proxy infrastructure for comprehensive testing can be time-consuming. BrowserStack simplifies proxy testing with cloud-based infrastructure, letting you validate configurations across different environments without the setup overhead.
Run Proxy Tests With Playwright
How to Configure a Proxy in Playwright (Global Scope)
The simplest way to configure a proxy is at browser launch. This applies to all pages and contexts from that browser instance.
1. Basic HTTP Proxy
const { chromium } = require(‘playwright’);
(async () => {
const browser = await chromium.launch({
proxy: {
server: ‘http://proxy.example.com:8080’
}
});
const page = await browser.newPage();
await page.goto(‘https://example.com’);
await browser.close();
})();
Read More:What does Configure Proxy Mean?
2. HTTPS and SOCKS Proxies
Playwright supports HTTP, HTTPS, and SOCKS5:
// HTTPS proxyconst browser = await chromium.launch({
proxy: {
server: ‘https://secure-proxy.example.com:8443’
}
});
// SOCKS5 proxy
const browser = await chromium.launch({
proxy: {
server: ‘socks5://socks-proxy.example.com:1080’
}
});
How to Configure a Proxy at Context or Page Level
Context-level proxy configuration offers more flexibility, letting different browser contexts use different proxies within the same browser instance. Perfect for simulating multiple users or locations simultaneously.
1. Context-Level Configuration
const { chromium } = require(‘playwright’);
(async () => {
const browser = await chromium.launch();
// Context 1: US proxy
const context1 = await browser.newContext({
proxy: { server: ‘http://us-proxy.example.com:8080’ }
});
const page1 = await context1.newPage();
await page1.goto(‘https://example.com’);
// Context 2: UK proxy
const context2 = await browser.newContext({
proxy: { server: ‘http://uk-proxy.example.com:8080’ }
});
const page2 = await context2.newPage();
await page2.goto(‘https://example.com’);
await browser.close();
})();
2. Combining Geolocation with Proxies
For realistic geo-testing, combine proxy configuration with geolocation and locale:
const context = await browser.newContext({ proxy: { server: ‘http://japan-proxy.example.com:8080’ },
geolocation: { longitude: 139.6917, latitude: 35.6895 },
locale: ‘ja-JP’,
timezoneId: ‘Asia/Tokyo’
});Authenticating, Bypassing and Advanced Proxy Options
Many proxy servers require authentication, and certain traffic needs to bypass proxies entirely. Here’s how to handle these scenarios.
1. Proxy Authentication
const browser = await chromium.launch({ proxy: {
server: ‘http://proxy.example.com:8080’,
username: ‘proxy_user’,
password: ‘secure_password’
}
});2. Environment Variable Credentials
For better security, store credentials in environment variables:
const browser = await chromium.launch({ proxy: {
server: process.env.PROXY_SERVER,
username: process.env.PROXY_USERNAME,
password: process.env.PROXY_PASSWORD
}
});3. Bypassing Specific Domains
Use the bypass option to exclude domains from proxy routing:
const browser = await chromium.launch({ proxy: {
server: ‘http://proxy.example.com:8080’,
bypass: ‘localhost,127.0.0.1,*.internal.company.com,192.168.*’
}
});Read More: How to redirect URL using Chrome Extension?
4. Handling Connection Failures
Implement error handling for proxy connectivity issues:
try { const browser = await chromium.launch({
proxy: { server: ‘http://proxy.example.com:8080’ }
});
const page = await browser.newPage();
await page.goto(‘https://example.com’, { timeout: 30000 });
} catch (error) {
if (error.message.includes(‘net::ERR_PROXY_CONNECTION_FAILED’)) {
console.error(‘Proxy connection failed, using fallback’);
// Fallback logic
}
}Proxy Rotation and Dynamic Routing Strategies with Playwright
For large-scale automation, rotating proxies prevents detection and distributes load across multiple IP addresses.
1. Simple Round-Robin Rotation
const proxies = [ ‘http://proxy1.example.com:8080’,
‘http://proxy2.example.com:8080’,
‘http://proxy3.example.com:8080’
];let currentProxyIndex = 0;
async function createContextWithRotatedProxy(browser) {
const proxy = proxies[currentProxyIndex];
currentProxyIndex = (currentProxyIndex + 1) % proxies.length;return await browser.newContext({
proxy: { server: proxy }
});
}const browser = await chromium.launch();
const context1 = await createContextWithRotatedProxy(browser);
const context2 = await createContextWithRotatedProxy(browser);
2. Random Proxy Selection
function getRandomProxy() {
const proxies = [
{ server: ‘http://proxy1.example.com:8080’, weight: 3 },
{ server: ‘http://proxy2.example.com:8080’, weight: 2 },
{ server: ‘http://proxy3.example.com:8080’, weight: 1 }
];
const totalWeight = proxies.reduce((sum, p) => sum + p.weight, 0);
let random = Math.random() * totalWeight;
for (const proxy of proxies) {
if (random < proxy.weight) return proxy.server;
random -= proxy.weight;
}
}
const context = await browser.newContext({
proxy: { server: getRandomProxy() }
});
3. Geographic Routing Strategy
const proxyPool = {
‘US’: [‘http://us-east.proxy.com:8080’, ‘http://us-west.proxy.com:8080’],
‘EU’: [‘http://eu-west.proxy.com:8080’, ‘http://eu-central.proxy.com:8080’],
‘ASIA’: [‘http://asia-pacific.proxy.com:8080’, ‘http://asia-east.proxy.com:8080’]
};
function getProxyForRegion(region) {
const proxies = proxyPool[region];
return proxies[Math.floor(Math.random() * proxies.length)];
}
const usContext = await browser.newContext({
proxy: { server: getProxyForRegion(‘US’) }
});
const euContext = await browser.newContext({
proxy: { server: getProxyForRegion(‘EU’) }
});
4. Time-Based Rotation
class ProxyRotator {
constructor(proxies, rotationIntervalMs = 300000) {
this.proxies = proxies;
this.currentIndex = 0;
this.rotationInterval = rotationIntervalMs;
this.lastRotation = Date.now();
}
getProxy() {
const now = Date.now();
if (now – this.lastRotation > this.rotationInterval) {
this.currentIndex = (this.currentIndex + 1) % this.proxies.length;
this.lastRotation = now;
}
return this.proxies[this.currentIndex];
}
}
const rotator = new ProxyRotator([
‘http://proxy1.example.com:8080’,
‘http://proxy2.example.com:8080’
], 300000);
const context = await browser.newContext({
proxy: { server: rotator.getProxy() }
});
Handling Corporate / Internal Network Proxies and Firewalls
Enterprise environments require special proxy handling for security auditing, content filtering, and compliance. Corporate proxies often need domain authentication (like NTLM), use self-signed SSL certificates for traffic inspection, and require specific domains to bypass the proxy entirely.
1. Corporate Proxy with Authentication
const { chromium } = require(‘playwright’);
const browser = await chromium.launch({
proxy: {
server: ‘http://corporate-proxy.company.com:8080’,
username: process.env.CORP_PROXY_USER,
password: process.env.CORP_PROXY_PASS,
bypass: ‘localhost,127.0.0.1,*.company.com,10.*’
},
ignoreHTTPSErrors: true
});This authenticates with your corporate proxy while bypassing it for internal company domains and local addresses. The ignoreHTTPSErrors flag handles self-signed certificates used by corporate SSL inspection.
2. System Proxy Detection
const browser = await chromium.launch({ proxy: {
server: process.env.HTTPS_PROXY || process.env.HTTP_PROXY
}
});This automatically detects and uses your system’s configured proxy without hardcoding server addresses-perfect for CI/CD environments where proxy settings vary.
3. NTLM Authentication for Windows
const context = await browser.newContext({ proxy: {
server: ‘http://corporate-proxy.company.com:8080’,
username: ‘DOMAIN\username’,
password: process.env.NTLM_PASSWORD
}
});Windows Active Directory environments use NTLM authentication. The DOMAIN\username format is required for domain-authenticated proxies.
4. Bypassing Proxy for Internal Resources
const context = await browser.newContext({ proxy: {
server: ‘http://internal-proxy.company.com:8080’,
bypass: ‘*.internal.company.com,192.168.*’
},
baseURL: ‘https://app.internal.company.com’
});Internal company sites and local development servers should connect directly without proxy routing. This prevents unnecessary latency and authentication loops for resources already inside your network.
Managing enterprise proxy configurations across different environments and authentication methods can become complex quickly. BrowserStack’s local testing capabilities let you test corporate proxy setups seamlessly, connecting your cloud tests to internal networks while handling authentication transparently.
How to Test Proxy-Dependent Websites Across Browsers and Devices at Scale
Testing proxy configurations across multiple browsers, devices, and real network conditions quickly becomes complex. Managing local infrastructure for this is resource-intensive and time-consuming.
Testing proxy configurations across multiple browsers, devices, and real network conditions quickly becomes complex. Managing local infrastructure for this is resource-intensive and time-consuming.
That’s where BrowserStack comes in. BrowserStack provides instant access to 3,500+ real browsers and devices with built-in proxy support, eliminating infrastructure management.
Here are core features of BrowserStack that can help you test proxy-dependent websites:
- Parallel Testing: Test US, EU, and ASIA proxy configurations in parallel across different device types without managing complex infrastructure.
- Local Environment Testing: Test your proxy setups with locally hosted applications before deployment.
- Test Reporting & Analytics: Track proxy test results with detailed logs, screenshots, and video recordings of every session.
- Web Performance Testing: Measure how proxy routing impacts your application’s load times and performance metrics.
Conclusion
Configuring proxies in Playwright is essential for catching geo-blocking bugs and location-specific failures before production. Master the appropriate configuration level, implement proper authentication, and design rotation strategies that match your testing patterns to ensure your application works globally.
BrowserStack eliminates the complexity of managing proxy infrastructure across browsers and devices. With instant access to real devices, parallel testing, and comprehensive analytics, you can focus on building robust tests instead of maintaining infrastructure.
Useful Resources for Playwright
- Playwright Automation Framework
- Playwright Java Tutorial
- Playwright Python tutorial
- Playwright Debugging
- End to End Testing using Playwright
- Visual Regression Testing Using Playwright
- Mastering End-to-End Testing with Playwright and Docker
- Page Object Model in Playwright
- Scroll to Element in Playwright
- Understanding Playwright Assertions
- Cross Browser Testing using Playwright
- Playwright Selectors
- Playwright and Cucumber Automation
Tool Comparisons:

