# Debugging a PAC file in Chrome, Edge and Firefox

Source: https://findproxyforurl.net/articles/debug-pac-chrome-edge-firefox/ · updated 2026-10-06

When a PAC file misbehaves in production, the question is always the same. Which proxy did this browser choose for this URL, and why? Chromium-based browsers and Firefox can both tell you, if you know where to look.

Before you open a browser, paste the file into the [online PAC file tester](https://findproxyforurl.net/check/). It shows per
URL and engine which line decided the result, and it catches most logic errors in seconds. Use the
browser when you need to know what one real client did.

Items marked *(expert)* are practitioner knowledge that has not been verified in our lab yet.
Everything else is either documented by the vendor or used in our lab runs.

## Chrome and Edge (Chromium)

**Isolated test profile.** Start a separate browser instance that uses your PAC and nothing else:

```sh
chrome --user-data-dir=/tmp/pac-test --proxy-pac-url=https://pac.corp.example/proxy.pac \
       --log-net-log=/tmp/pac-test/netlog.json --net-log-capture-mode=Everything
```

These are the flags our lab uses to drive Chrome and Edge (source: lab, 2026-10-04). Use the Edge
executable for Edge.

**Record a NetLog in a running browser.** Open `chrome://net-export/`, click **Start Logging To
Disk**, reproduce the problem in another tab, then click **Stop Logging**. Keep the net-export tab
open while recording. Open the file in the
[NetLog viewer](https://chromium.googlesource.com/catapult/+/HEAD/netlog_viewer/) (source: doc,
[chromium.org](https://www.chromium.org/for-testers/providing-network-details/), checked
2026-10-06). In Edge the page is `edge://net-export/` *(expert)*.

**What to look for:**

- the proxy list the PAC returned for the request, and which entry was used;
- `alert()` messages from your PAC. Chromium sends them to the NetLog, not to a dialog (source:
  code, verified 2026-10-04);
- whether the PAC fetch itself failed. Without a usable PAC, Chromium connects directly unless a
  mandatory-PAC policy is set ([PAC-D010](https://findproxyforurl.net/rules/http-error-status/)).

`chrome://net-internals/#proxy` shows the effective proxy settings and lets you re-apply them after
you change the PAC *(expert)*.

**Chrome-specific traps:**

- For `https://` URLs Chrome passes only `https://host:port/` to the script; path and query are
  removed (source: code, verified 2026-10-04). A rule on the path of an https URL never matches.
- Name resolution is asynchronous, and the script may run again once a DNS answer arrives
  *(expert)*. `alert()` output can therefore appear twice.

## Firefox

**Test profile.** In a fresh profile, set these prefs in `about:config` or in `user.js`:

```js
user_pref("network.proxy.type", 2);   // 2 = automatic proxy configuration URL
user_pref("network.proxy.autoconfig_url", "https://pac.corp.example/proxy.pac");
```

**Proxy logging.** Start Firefox with the `MOZ_LOG` environment variable to log proxy resolution:

```sh
MOZ_LOG=proxy:5,timestamp MOZ_LOG_FILE=/tmp/pac-test/moz.log firefox -profile /tmp/pac-test
```

The prefs and the log module are what our lab uses for Firefox (source: lab, 2026-10-04). The same
modules can be switched on at runtime in `about:logging` *(expert)*.

**alert() output** goes to the browser console (source: doc,
[MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_PAC_file),
checked 2026-10-06).

**Firefox-specific traps:**

- With the default settings Firefox removes the path and query for **every** scheme, plain
  `http://` included (source: code, verified 2026-10-04).
- `dnsResolve` blocks the PAC thread while it waits (source: code, verified 2026-10-04). A slow
  resolver slows every request; see [DNS in PAC files](https://findproxyforurl.net/articles/dns-in-pac-files/).
- The Microsoft `*Ex` functions do not exist in Firefox. Calling them throws, and the request goes
  direct ([PAC-K003](https://findproxyforurl.net/rules/ex-functions-not-portable/)).

## Traps in every browser

- **Caching.** The browser keeps the PAC for an engine-specific time when the server sends no
  `Cache-Control` ([PAC-D003](https://findproxyforurl.net/rules/missing-cache-control/)). While debugging, restart the test
  profile after each change. In production, send `max-age` of an hour or less during a change.
- **Errors look like success.** An exception or a missing `return` makes Chromium and Firefox
  connect **directly** (source: code, verified 2026-10-04). If "everything works" but the proxy logs
  are empty, check for that first.
- **Remove debugging alerts.** `alert()` calls in a production PAC write to logs on every request.

## Before you debug in a browser

Most "the browser ignores my PAC" reports turn out to be one of the [top 20 PAC
mistakes](https://findproxyforurl.net/top-20/). Run the file through the [tester](https://findproxyforurl.net/check/) first, with the failing URL as a
test URL. If all engine profiles agree and the browser still differs, the NetLog or `MOZ_LOG`
shows why.


## Frequently asked questions

### Where does alert() output from a PAC file go?

In Chromium (Chrome, Edge) alert() in a PAC file writes to the NetLog, not to a dialog. In Firefox it goes to the browser console. pacparser prints it to the console.

### How do I test a PAC file in Chrome without changing the system proxy?

Start Chrome with a separate profile and the --proxy-pac-url flag, for example chrome --user-data-dir=/tmp/pac-test --proxy-pac-url=https://pac.corp.example/proxy.pac. Only that browser instance uses the PAC.

### Why does my PAC change not take effect?

Browsers keep the downloaded PAC for a while. Without a Cache-Control header the engine decides how long. Serve the file with an explicit max-age and reload the proxy settings or restart the browser while testing.

