# pactester vs Chrome, Edge, Firefox and Windows: why a PAC file passes in pactester and fails in the browser

Source: https://findproxyforurl.net/articles/pactester-vs-chrome-firefox/ · updated 2026-10-11

Changed 2026-10-11: The page now has a short note on how Windows runs PAC files and links the new article and the Windows engine page.

pactester is the usual way to test a proxy.pac on the command line and in CI. For most files it gives the same answer as the browsers. For some calls it does not, and then a test passes while users go to the wrong proxy. Windows adds its own engine on top.

## Why the engines differ

Every PAC engine contains a small library of helper functions such as `isInNet`, `weekdayRange` and
`shExpMatch`. In pactester, Chrome and Firefox they go back to the same code that Netscape and later
Mozilla wrote in the late 1990s. pacparser, the library behind `pactester` and the Python module
`pacparser`, keeps that code close to its original form. Chrome and Firefox have changed their copies
over the years. Windows evaluates PAC files with its own implementation in WinHTTP, and WinINet in
older applications.

None of these is a bug in the usual sense. The trouble starts when a file is tested in one engine and
used in another, and the usual case is a test with pactester and users on Chrome, Edge or Firefox.

## Where pactester and the browsers can disagree

- **[isInNet()](https://findproxyforurl.net/functions/isinnet/)** with a network in CIDR form such as `"10.0.0.0/8"`, a shortened
  mask, a prefix length as the mask, leading zeros or a missing argument. Some of these are true in
  pactester and false in every browser.
- **[weekdayRange()](https://findproxyforurl.net/functions/weekdayrange/), [dateRange()](https://findproxyforurl.net/functions/daterange/) and
  [timeRange()](https://findproxyforurl.net/functions/timerange/)** with a range that wraps around the weekend, the new year or
  midnight. The browsers match it, pactester never does, and `timeRange(22, 6)` matches nowhere.
- **[myIpAddress()](https://findproxyforurl.net/functions/myipaddress/)**, which pactester takes from the machine the test runs
  on, while the browsers take it from the network connection.
- **[dnsResolve()](https://findproxyforurl.net/functions/dnsresolve/)** and every function that resolves names: the engines
  differ in IPv6 answers, in upper-case names and in how many lookups one run of the script may make.
- **[isPlainHostName()](https://findproxyforurl.net/functions/isplainhostname/)** on IPv6 addresses.
- **IP addresses written with leading zeros, in hex or as one number**, such as `010.1.2.3`. The
  browsers convert the host to the plain form before the file sees it, pactester does not, and
  Windows reads leading zeros as octal. Write plain addresses even where the odd form works
  ([PAC-C031](https://findproxyforurl.net/rules/ip-address-unusual-form/)).
- **The URL itself.** pactester passes the full URL to FindProxyForURL, while the browsers remove the
  path and query, at least for `https://`. A rule on the path matches in the test and not in the
  browser ([engine differences](https://findproxyforurl.net/engines/differences/)).

## Windows is a third kind of engine

Applications that use the Windows proxy settings, and Windows services, get their answer from
WinHTTP's own PAC engine, not from pactester's code and not from a browser's. It answers some of the
calls above in a third way. Chrome and Edge do not use it; they run the file in their own engine, also
on Windows. A file that has to work for browsers and Windows applications alike should stay with the
plain forms of each call.

The differences on Windows go further than the calls above. `dateRange()` and `timeRange()` are
always false there, and newer JavaScript such as `?.` makes the whole file fail. The article
[Windows runs PAC files differently from Chrome and Firefox](https://findproxyforurl.net/articles/pac-on-windows/) lists them,
and the engine page [Windows (WinHTTP)](https://findproxyforurl.net/engines/winhttp/) has the details.

## Test the file where it will run

The way to be sure is to run your file in the engine your users have. Paste it into the
**[PAC file tester](https://findproxyforurl.net/check/)**, enter a URL and an optional client IP, and switch the engine profile
between Chromium, Firefox, pacparser and the two Windows profiles. The live trace shows which tests were true or false and which
line decided, and the rating flags the calls whose answer depends on the engine, such as an `isInNet`
with a CIDR network or a time range that wraps around.

Keep pactester in your [CI test](https://findproxyforurl.net/articles/test-pac-files-in-ci-with-pactester/) as the safety net,
and set the client address there with `pactester -c`. For problems in production, start with
[PAC file troubleshooting](https://findproxyforurl.net/articles/pac-file-troubleshooting/).


## Frequently asked questions

### Does pactester give the same results as Chrome?

For most PAC files, yes. It can differ for isInNet with a CIDR network or a short mask, for IP addresses written with leading zeros or in hex, for weekdayRange, dateRange and timeRange ranges that wrap around, for myIpAddress, for DNS lookups, for IPv6 addresses, and for the URL passed to FindProxyForURL. Test the file in a browser engine profile too, for example in the tester at findproxyforurl.net/check/.

### Is pacparser wrong?

No. pacparser keeps the PAC helper functions in the form Netscape and early Mozilla wrote them. Chrome and Firefox changed their copies later. Both are consistent; they are different versions of the same functions, and a PAC file should avoid the calls where they differ.

### Does Windows evaluate PAC files like Chrome or like pactester?

Like neither. Windows evaluates proxy.pac and wpad.dat with its own code in WinHTTP (and WinINet in older applications), which answers some calls differently from both. Chrome and Edge use their own engine, also on Windows.

### How do I check my PAC file in several engines?

Paste it into the tester at findproxyforurl.net/check/, enter a URL, and switch the engine profile between Chromium, Firefox and pacparser. The trace shows which test and which line decided in each, and the rating flags calls whose answer depends on the engine.

