Proxy Testing
This skill provides a JS library to run autoconsent via regional proxies in Playwright.
Rule changes are verified with a two-level regional policy.
The core region set (default for detection, iteration, and verification) covers us (CCPA), gb (UK GDPR), de (EEA GDPR), plus the reported region from the task when specified (if the reported region is not a supported proxy region, use the closest supported one, e.g. es for pt). Iterate in the single most relevant region; run the full core set once when the fix is stable.
Escalate to the expanded set (us, gb, de, fr, nl, pl, au, ca, jp) if any of these is true:
- core results diverge
- the rule contains region-dependent logic
- the fix relies on language-specific or brittle structural selectors
- the change touches a widely-used generic rule (as final pre-PR validation)
- a non-core region named in the report behaves differently.
The remaining GDPR/EEA regions (ch, no, it, es, se, dk) are optional even in an expanded pass: test them only when named in the report or clearly relevant (e.g. the site's ccTLD).
Important! Autoconsent results can have false positives. When testing, always inspect the screenshots and confirm that opt-out was successful.
Prerequisites
npm run prepublish # builds dist/autoconsent.playwright.js and rules/rules.json
Environment variables:
REGIONAL_PROXY_<TWO_LETTER_REGION_CODE> (for example, REGIONAL_PROXY_US, REGIONAL_PROXY_GB, REGIONAL_PROXY_AU, etc.) - the domain endpoint
REGIONAL_PROXY_USERNAME
REGIONAL_PROXY_PASSWORD
Endpoints must be bare hostnames: no scheme, credentials, or port.
The library adds https:// and port 443.
Credentials are shared across regions.
Usage
Test one URL:
import { formatResult, testUrl } from './.agents/skills/proxy-testing/scripts/regional-proxy.mjs';
const result = await testUrl('https://www.wohnen.de/', 'de');
console.log(formatResult(result));
Test multiple regions:
import { formatResult, testRegions } from './.agents/skills/proxy-testing/scripts/regional-proxy.mjs';
const results = await testRegions('https://www.wohnen.de/', ['us', 'de', 'fr']);
for (const result of results) {
console.log(formatResult(result));
}
Use an existing page:
import { launchRegionalProxyBrowser, testPage } from './.agents/skills/proxy-testing/scripts/regional-proxy.mjs';
const browser = await launchRegionalProxyBrowser('de');
const page = await browser.newPage();
const result = await testPage(page, 'https://www.wohnen.de/', 'de');
await browser.close();
Get proxy config for Playwright Test:
import { defineConfig } from '@playwright/test';
import { buildProxyConfig } from './.agents/skills/proxy-testing/scripts/regional-proxy.mjs';
export default defineConfig({
use: {
proxy: buildProxyConfig('us'),
},
});
API
testUrl(url, regionKey, options?) — test one URL in a single region; launches a proxied browser, runs autoconsent, returns a TestResult.
testRegions(url, regions?, options?) — test one URL across several regions (defaults to CORE_REGIONS), a fresh browser per region; returns TestResult[]. Remember to include the reported region when not already covered.
CORE_REGIONS — the core region set (default); add the reported region when not already covered.
EXPANDED_REGIONS — the expanded region set used on escalation.
ALL_REGIONS — all supported regions.
testPage(page, url, regionKey, options?) — run a full test on a page you created yourself (you own the browser/context); returns a TestResult.
injectAutoconsent(page, options?) — set up isolated-world injection; call before page.goto(). Returns a context (received, hasMessage, waitForCompletion, waitForMessage, collectResult).
buildProxyConfig(regionKey) — build the Playwright { server, username, password } proxy object for a region from its env vars.
launchRegionalProxyBrowser(regionKey, options?) — launch a Chromium browser routed through the region's proxy.
formatResult(result) — format a TestResult as a human-readable summary line.
Options (all optional):
action — 'optOut' (default), 'optIn', or null to only detect (no opt-out/opt-in performed).
screenshotsDir — directory for the final screenshots (default: test-results/regional-proxy).
navigationTimeout — page.goto timeout in ms (default 45000).
completionTimeout — max wait for autoconsent to finish opt-out/opt-in in ms (default 45000).
detectionTimeout — max wait for cmpDetected before giving up (default: completionTimeout).
headless — run Chromium headless (default true).
launchOptions — extra options merged into chromium.launch() (e.g. args); the regional proxy is always applied on top.
Smoke Test
import { launchRegionalProxyBrowser } from './.agents/skills/proxy-testing/scripts/regional-proxy.mjs';
const browser = await launchRegionalProxyBrowser('us');
const page = await browser.newPage();
await page.goto('https://api.ipify.org?format=json', { waitUntil: 'domcontentloaded', timeout: 30000 });
console.log(await page.textContent('body'));
await browser.close();
Rule Checks
- Run
npm run build-rules after changing rule JSON.
- Smoke-test each regional proxy.
- Verify on the core region set (
us, gb, de + reported region); escalate to the expanded set per the policy above.
- Inspect screenshots, not just API results.
- Reload after dismissal and confirm the rule does not keep matching, unless cosmetic-only.
Gotchas
- Use Playwright's proxy auth object:
{ server, username, password }.
- Never embed proxy credentials in URLs, command lines, logs, traces, or source.
- Call
injectAutoconsent(page) before page.goto() so the init script is installed before page scripts run.
- The content script runs in an isolated world (via CDP) and
eval snippets run in the page's main world, matching the extension. Chromium only.
- Use a fresh browser per region to avoid leaking proxy state, cookies, cache, or DNS.
- Some sites localize by more than IP; only add locale/geolocation settings intentionally.
- Some sites block proxy traffic outright (captcha, 403, endless challenge page). If every region's proxy is blocked for a site, retest it over a direct connection and state explicitly in the report that the result is unproxied. If direct access is blocked too, ask the triager for the popup's HTML pasted from their own browser as a last resort, and note that the rule was written from pasted markup rather than a live run.
1---2name: proxy-testing3description: Test autoconsent via regional proxies in Playwright. Use when verifying rule changes across regions (US, EU, UK, etc.), or investigating region-dependent CMP behavior.4---56# Proxy Testing7This skill provides a JS library to run autoconsent via regional proxies in Playwright.89Rule changes are verified with a two-level regional policy.10The **core region set** (default for detection, iteration, and verification) covers `us` (CCPA), `gb` (UK GDPR), `de` (EEA GDPR), plus the reported region from the task when specified (if the reported region is not a supported proxy region, use the closest supported one, e.g. `es` for `pt`). Iterate in the single most relevant region; run the full core set once when the fix is stable.1112Escalate to the **expanded set** (`us`, `gb`, `de`, `fr`, `nl`, `pl`, `au`, `ca`, `jp`) if any of these is true:13- core results diverge14- the rule contains region-dependent logic15- the fix relies on language-specific or brittle structural selectors16- the change touches a widely-used generic rule (as final pre-PR validation)17- a non-core region named in the report behaves differently.1819The remaining GDPR/EEA regions (`ch`, `no`, `it`, `es`, `se`, `dk`) are optional even in an expanded pass: test them only when named in the report or clearly relevant (e.g. the site's ccTLD).2021Important! Autoconsent results can have false positives. When testing, always inspect the screenshots and confirm that opt-out was successful.2223## Prerequisites2425```bash26npm run prepublish # builds dist/autoconsent.playwright.js and rules/rules.json27```2829Environment variables:3031- `REGIONAL_PROXY_<TWO_LETTER_REGION_CODE>` (for example, `REGIONAL_PROXY_US`, `REGIONAL_PROXY_GB`, `REGIONAL_PROXY_AU`, etc.) - the domain endpoint32- `REGIONAL_PROXY_USERNAME`33- `REGIONAL_PROXY_PASSWORD`3435- Endpoints must be bare hostnames: no scheme, credentials, or port.36- The library adds `https://` and port `443`.37- Credentials are shared across regions.3839## Usage4041Test one URL:4243```javascript44import { formatResult, testUrl } from './.agents/skills/proxy-testing/scripts/regional-proxy.mjs';4546const result = await testUrl('https://www.wohnen.de/', 'de');47console.log(formatResult(result));48```4950Test multiple regions:5152```javascript53import { formatResult, testRegions } from './.agents/skills/proxy-testing/scripts/regional-proxy.mjs';5455const results = await testRegions('https://www.wohnen.de/', ['us', 'de', 'fr']);56for (const result of results) {57 console.log(formatResult(result));58}59```6061Use an existing page:6263```javascript64import { launchRegionalProxyBrowser, testPage } from './.agents/skills/proxy-testing/scripts/regional-proxy.mjs';6566const browser = await launchRegionalProxyBrowser('de');67const page = await browser.newPage();68const result = await testPage(page, 'https://www.wohnen.de/', 'de');69await browser.close();70```7172Get proxy config for Playwright Test:7374```javascript75import { defineConfig } from '@playwright/test';76import { buildProxyConfig } from './.agents/skills/proxy-testing/scripts/regional-proxy.mjs';7778export default defineConfig({79 use: {80 proxy: buildProxyConfig('us'),81 },82});83```8485## API8687- `testUrl(url, regionKey, options?)` — test one URL in a single region; launches a proxied browser, runs autoconsent, returns a `TestResult`.88- `testRegions(url, regions?, options?)` — test one URL across several regions (defaults to `CORE_REGIONS`), a fresh browser per region; returns `TestResult[]`. Remember to include the reported region when not already covered.89- `CORE_REGIONS` — the core region set (default); add the reported region when not already covered.90- `EXPANDED_REGIONS` — the expanded region set used on escalation.91- `ALL_REGIONS` — all supported regions.92- `testPage(page, url, regionKey, options?)` — run a full test on a page you created yourself (you own the browser/context); returns a `TestResult`.93- `injectAutoconsent(page, options?)` — set up isolated-world injection; call before `page.goto()`. Returns a context (`received`, `hasMessage`, `waitForCompletion`, `waitForMessage`, `collectResult`).94- `buildProxyConfig(regionKey)` — build the Playwright `{ server, username, password }` proxy object for a region from its env vars.95- `launchRegionalProxyBrowser(regionKey, options?)` — launch a Chromium browser routed through the region's proxy.96- `formatResult(result)` — format a `TestResult` as a human-readable summary line.9798Options (all optional):99100- `action` — `'optOut'` (default), `'optIn'`, or `null` to only detect (no opt-out/opt-in performed).101- `screenshotsDir` — directory for the final screenshots (default: `test-results/regional-proxy`).102- `navigationTimeout` — `page.goto` timeout in ms (default `45000`).103- `completionTimeout` — max wait for autoconsent to finish opt-out/opt-in in ms (default `45000`).104- `detectionTimeout` — max wait for `cmpDetected` before giving up (default: `completionTimeout`).105- `headless` — run Chromium headless (default `true`).106- `launchOptions` — extra options merged into `chromium.launch()` (e.g. `args`); the regional `proxy` is always applied on top.107108## Smoke Test109110```javascript111import { launchRegionalProxyBrowser } from './.agents/skills/proxy-testing/scripts/regional-proxy.mjs';112113const browser = await launchRegionalProxyBrowser('us');114115const page = await browser.newPage();116await page.goto('https://api.ipify.org?format=json', { waitUntil: 'domcontentloaded', timeout: 30000 });117console.log(await page.textContent('body'));118await browser.close();119```120121## Rule Checks1221231. Run `npm run build-rules` after changing rule JSON.1242. Smoke-test each regional proxy.1253. Verify on the core region set (`us`, `gb`, `de` + reported region); escalate to the expanded set per the policy above.1264. Inspect screenshots, not just API results.1275. Reload after dismissal and confirm the rule does not keep matching, unless cosmetic-only.128129## Gotchas130131- Use Playwright's proxy auth object: `{ server, username, password }`.132- Never embed proxy credentials in URLs, command lines, logs, traces, or source.133- Call `injectAutoconsent(page)` before `page.goto()` so the init script is installed before page scripts run.134- The content script runs in an isolated world (via CDP) and `eval` snippets run in the page's main world, matching the extension. Chromium only.135- Use a fresh browser per region to avoid leaking proxy state, cookies, cache, or DNS.136- Some sites localize by more than IP; only add locale/geolocation settings intentionally.137- Some sites block proxy traffic outright (captcha, 403, endless challenge page). If every region's proxy is blocked for a site, retest it over a direct connection and state explicitly in the report that the result is unproxied. If direct access is blocked too, ask the triager for the popup's HTML pasted from their own browser as a last resort, and note that the rule was written from pasted markup rather than a live run.