Playwright geolocation vs network IP: test country-specific behavior
Playwright geolocation can change the coordinates the browser reports, but it does not configure the network route used by the request. Playwright documents geolocation, locale, and timezone as emulation options, while proxy routing is a separate network option.
If you set a Berlin geolocation without changing the network route, Playwright can make the browser report Berlin while the server still receives the request from your normal internet connection. That matters when the application uses request origin to decide what to return, including country redirects, localized content, regional availability, pricing, or other IP-based behavior.
For those tests, configure both layers explicitly: the browser context you want to emulate and the country-specific network route the request should actually use.
Official references:
For a request-level version of the same controlled comparison, see the request replay recipe. If the behavior is a Cloudflare Worker redirect, use the Cloudflare country-redirect debugging recipe.
Configure Playwright's network route explicitly
In Shellroute's recorded Playwright compatibility check, browser traffic did not use the proxy environment variables injected into the child process automatically. For this workflow, configure Playwright's use.proxy setting explicitly and read the proxy server from HTTP_PROXY.
Keep the config fail-closed. If the routed proxy is missing, stop before the suite runs rather than letting a country-specific test silently use the normal connection.
import { defineConfig } from '@playwright/test';
const proxyServer = process.env.HTTP_PROXY;
if (!proxyServer) {
throw new Error(
'HTTP_PROXY is not set. Run this suite inside shellroute, e.g. shellroute run DE -- npx playwright test',
);
}
export default defineConfig({
use: { proxy: { server: proxyServer } },
}); Then run the test through the country route:
shellroute run DE -- npx playwright test
Playwright documents proxy as the proxy setting used for all pages in the test. Its browser API also documents proxy.server as the proxy used for requests.
The config throws if HTTP_PROXY is not set, so this routed configuration cannot silently fall back to a direct connection. The check runs when Playwright loads the config, including commands such as --list and --ui.
Two failure modes to distinguish
Shellroute wrapper without Playwright proxy config: the child process has proxy environment variables, but Playwright browser traffic can still use the normal connection. The browser proxy setting is required for this workflow.
Routed Playwright config without the Shellroute wrapper: HTTP_PROXY is missing, so the config throws before tests run. This is intentional. A country-route test should fail closed rather than look successful on the normal connection.
Compare direct and routed behavior without weakening the fail-closed config
Use a separate baseline config for the direct control. Keep the test files and browser settings the same; change only the network configuration.
import { defineConfig } from '@playwright/test';
export default defineConfig({}); Run the direct baseline:
npx playwright test -c playwright.direct.config.ts Run the routed version:
shellroute run DE -- npx playwright test Compare the server-observed behavior between the two runs. This keeps the routed config fail-closed while still giving you a direct control.
Minimal CI shape
Keep your existing Playwright tests. Use the fail-closed proxy config for the routed job, then invoke the suite through the country you need to verify:
shellroute run DE -- npx playwright test If you also want a direct control in CI, run the same test files with the separate direct config shown above. Do not remove the fail-closed check from the routed job just to make the control pass.
Need another country route for the same test?
Configure the route with the Shellroute Quickstart