ScreenshotNeo

BlogHow-to

How to Test Websites Behind a VPN or Firewall with Percy

Route Percy’s requests through a proxy, and use BrowserStack Local when remote browsers need private-site access. Learn which layer to configure and how to troubleshoot it.

By the ScreenshotNeo team4 October 20268 min read

Direct answer: Configure the network path that is failing. Set HTTP_PROXY and, when needed, HTTPS_PROXY for Percy CLI or SDK traffic. If Percy’s resource-discovery browser also needs the proxy, configure its browser launch argument with --proxy-server. If a remote BrowserStack browser must open a site available only inside your VPN or firewall, start BrowserStack Local as a separate tunnel. These settings solve different connectivity problems.

First identify which component cannot reach which destination: the test runner connecting to Percy, Percy’s discovery browser loading the page or its assets, or a remote browser reaching your private site. Then use the matching setup below.

1. Identify the failing network path

What is failing? Likely fix
The runner cannot connect to Percy’s service Configure Percy’s proxy environment variables in the runner’s environment.
Percy connects, but resource discovery cannot load the app or its assets Configure the proxy for the discovery browser with --proxy-server.
A remote BrowserStack browser cannot open a private, staging, or localhost site Use BrowserStack Local to connect the remote browser to a Local agent inside the network.

Percy documents proxy configuration for SDK requests and resource discovery as separate settings. BrowserStack Local addresses remote-browser access to private networks. Turning on Local does not automatically configure Percy’s API proxy, and a Percy API proxy does not make a private site reachable from a remote browser. See BrowserStack’s Percy proxy guide, Percy environment-variable reference, and Local Testing overview.

2. Configure the proxy for Percy CLI or SDK traffic

Set the variables in the environment that launches Percy. The documentation says HTTP_PROXY alone is sufficient in most cases. Set both variables when your organization uses different proxy endpoints for HTTP and HTTPS traffic.

export HTTP_PROXY="http://proxy.example.com:8080"
export HTTPS_PROXY="http://proxy.example.com:8080"
# Optional: bypass the proxy for hosts your network policy allows directly.
export NO_PROXY="localhost,127.0.0.1,.internal.example.com"

# Run the Percy command used by your project in this same environment.
# For a local run, avoid updating the shared master baseline:
export PERCY_BRANCH="local"
# Example: npx percy exec -- <your-test-command>

Replace the example proxy address and bypass list with values approved for your network. Percy accepts proxy URLs with optional username and password fields, for example http://username:password@proxy.example.com:8080/. Avoid putting credentials directly in source files or shell history; inject them through your CI or secret-management mechanism.

For PAC-based proxy selection, set PERCY_PAC_FILE_URL to the local-file or HTTP-hosted PAC URL. Percy documents this variable as taking precedence over its other proxy variables. Follow your organization’s rules for accessing and authenticating to that PAC file.

CI configuration

Define the proxy variables as job environment variables or secrets so the Percy process inherits them. Keep the Percy project token in secret storage: Percy describes it as a write-only token used to create builds and upload snapshots and resources, and warns that access to it can consume account quota. Use the CI workflow for CI runs; set PERCY_BRANCH=local for local runs when you want to avoid updating the master baseline. See Percy’s environment-variable reference.

3. Route Percy resource discovery through the proxy

Percy asset discovery runs in a browser. If the CLI can connect to Percy but discovery cannot reach your application or its assets, add the proxy-server browser launch argument to Percy’s discovery configuration:

--proxy-server=http://proxy.example.com:8080

Use the configuration mechanism supported by your Percy integration to pass that argument to the discovery browser. The exact configuration location depends on the SDK or project setup; do not assume setting HTTP_PROXY alone configures the browser launch. See Configuring Proxy Requests.

Percy documents PERCY_DEBUG=true for debugging asset discovery without uploading snapshots. Its environment-variable reference lists page-load and network-idle discovery timeout controls, with a documented default of 30,000 ms for each. Increase a timeout only when discovery is slow but succeeds with more time; it cannot fix a blocked route or missing authentication.

4. Use BrowserStack Local for remote access to private sites

Use BrowserStack Local when the browser or device is remote on BrowserStack and the application is reachable only from your private network. BrowserStack describes Local as supporting localhost, staging, and private-network sites, including sites behind proxies, firewalls, or VPNs. The Local agent initiates an outbound connection and authenticates with BrowserStack; remote browser requests go through a repeater and are resolved through the agent inside your network. This lets the remote browser reach the site without exposing the internal server to the public internet. See How Local Testing works.

Start and configure Local for the BrowserStack product and test framework you use. For example, the Cypress Automate guide shows enabling Local with connection_settings.local in browserstack.json:

{
  "connection_settings": {
    "local": true
  }
}

That setting is an example for the documented Cypress integration, not a universal configuration for every BrowserStack product. Follow the setup guide for your integration. The Local agent can be stopped with Ctrl+C; BrowserStack says this tears down the agent and repeater state.

Proxy types and routing flags in the Cypress guide

BrowserStack’s Cypress Local Testing proxy guide describes support for unauthenticated or HTTP Basic authenticated standard proxies, unauthenticated or HTTP Basic authenticated MITM proxies, and PAC files without authentication. It documents these options for that integration:

Proxy setup Documented options
Standard proxy --proxy-host, --proxy-port; for Basic authentication, --proxy-user and --proxy-pass
MITM proxy --local-proxy-host and --local-proxy-port
PAC file --pac-file; the guide documents PAC without authentication

The same guide says to bypass bs-local.com in the proxy if required. It documents --force-proxy and --force-local for routing remote browser or device requests through the configured proxy and Local connection. Without these flags, the Local binary attempts direct connections where possible for performance. Apply these options only when they match your routing policy, and verify support in the guide for your exact BrowserStack product and integration. See Run your Cypress tests from behind a proxy and Run tests on localhost and staging websites.

5. Troubleshoot in network-path order

  1. The Percy command cannot reach Percy. Check that the process inherits the intended HTTP_PROXY and HTTPS_PROXY, that the proxy address and credentials are correct, and that network policy permits the connection. If HTTP and HTTPS need different proxies, set both variables.
  2. Percy connects, but discovery reports missing pages or assets. Configure the discovery browser’s --proxy-server argument separately. Enable PERCY_DEBUG=true to inspect discovery without uploading snapshots.
  3. A remote browser cannot open an internal hostname. Confirm BrowserStack Local is running and enabled for the test integration, and that the hostname resolves from the network containing the Local agent. Percy’s API proxy alone does not provide this tunnel.
  4. Local works for some requests but not others. Check whether your organization’s proxy type and authentication match the options supported by the specific Local integration. For the Cypress guide, check the documented standard, MITM, and PAC limitations, and whether bs-local.com needs a proxy bypass.
  5. Traffic takes a direct route when policy requires the tunnel. Check the integration’s guidance for --force-local and --force-proxy. These flags change routing; use them when policy requires it, since BrowserStack says direct connections may otherwise be attempted where possible for performance.
  6. Discovery times out on a slow page. Check whether the page eventually loads and whether network-idle conditions are realistic for it. Percy’s documented discovery page-load and network-idle timeout defaults are 30 seconds; raising a timeout can help slow but reachable pages, but not blocked traffic.
  7. A local run changes a shared baseline. Set PERCY_BRANCH=local for local runs when appropriate, and reserve CI runs for the project’s CI workflow.

Do not commit proxy passwords or Percy project tokens. Treat both as credentials and keep them out of logs where possible. Percy specifically warns that token access can consume account quota.

6. Performance, reliability, and cost considerations

Proxy routing and Local tunnels add network hops, so response time depends on your proxy, tunnel, DNS resolution, and application. Use forced routing only when required by the network or security policy; BrowserStack notes that Local attempts direct connections where possible for performance when force flags are not used. For slow pages, first distinguish a real timeout from a route or authentication failure before raising discovery timeouts.

For reliability, make the runner, discovery browser, and remote browser routes explicit and configure each at its own layer. Keep credentials in managed secrets, use a stable internal hostname reachable from the Local agent, and close the Local agent when the run finishes. The cited documentation does not provide a performance benchmark or a cost figure for this setup, so none is claimed here.

Or skip the browser setup

If your goal is to capture a page rather than run Percy visual regression, ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. One GET request returns a PNG, JPEG, WebP, or PDF. It can capture public pages; it does not replace a private-network tunnel for a site that only your VPN can reach.

For an accessible page, a single call looks like this:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for the request options. Before capture, it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Create a free ScreenshotNeo account for 1,000 screenshots a month, with no card required.

FAQ

Does BrowserStack Local configure Percy’s API proxy?

No. Local provides a tunnel for remote BrowserStack browsers to reach private sites. Percy CLI or SDK traffic uses its own proxy environment settings.

Does setting HTTP_PROXY also configure Percy asset discovery?

Not necessarily. If discovery’s browser needs the proxy, Percy documents configuring its launch argument with --proxy-server.

Can I use Local Testing for a public site?

It is intended for cases where the remote browser needs a route through the Local agent, such as localhost, staging, or private network sites. Use it when that network path is necessary for your test.

Can I apply the Cypress proxy flags to another BrowserStack integration?

Do not assume so. The cited proxy options are documented for Cypress Automate; verify the setup for the specific BrowserStack product and integration you use.