PAC File Tester guide

PAC basics, helper function reference, common mistakes, diff mode, safety and FAQ

日本語

▶ Download PAC File Tester

PAC basics

A PAC (Proxy Auto-Configuration) file is a JavaScript file that browsers and operating systems use to decide which proxy to use for a URL. It defines one function, FindProxyForURL(url, host).

Example and return values

It is often named proxy.pac or wpad.dat. The browser calls the function for every URL it opens and connects as the returned string says.

function FindProxyForURL(url, host) {
  if (isPlainHostName(host)) return "DIRECT";
  if (dnsDomainIs(host, ".example.com")) return "DIRECT";
  return "PROXY proxy.example.net:8080; DIRECT";
}
  • url is the full URL (for example http://www.example.com/a/b); host is just the host name (www.example.com, lower case, without the port)
  • The return value is "DIRECT" (no proxy) or "PROXY host:port". Separate several with ; and the next one is used when the previous one is unavailable
  • Some browsers also accept SOCKS host:port, HTTPS host:port and others

How to use

  1. Download pac-tester.html from the download page and double-click it
  2. Paste your PAC into the PAC ファイル (PAC file) box on the left
  3. In テストする URL (URLs to test) on the right, write one URL per line
  4. It evaluates as you type. The 結果 (Results) table shows the return value for each URL
More on the screen and the evaluation settings

The tool's screen is in Japanese. The label table on the download page gives the English meaning of each label.

  • Choose a .pac file with 開く (Open) or drag and drop it onto the page
  • Without http:// a URL line is treated as http. Lines starting with # are comments. The list loads from and saves to a .txt file
  • Ctrl+Enter or 評価する evaluates at once
  • The coloured buttons above the results are the counts for each return value; click one to show only those rows. Filter by text, show only errors and warnings, or save as CSV
  • Problems found in the script are listed under 構文・ロジックのチェック (Syntax and logic checks). Click one to jump to the line

Evaluation settings

  • Host-to-IP table: replaces DNS for dnsResolve, isInNet and isResolvable. One entry per line, as "host IP" or in hosts-file order "IP host". *.example.com 10.0.0.1 applies to every host under that domain
  • IP address returned by myIpAddress(): test a PAC that picks a proxy per site by entering that site's client address
  • Date and time: the date, time and UTC offset used by weekdayRange, dateRange and timeRange. Untick "use the current date and time" to test any moment you like
  • Strip the path and query from https URLs: matches Chrome and Edge (on by default)

Diff mode

Use diff mode when you change a PAC, to confirm that only the URLs you meant to change get a different result.

How diff mode works
  1. Press 差分モード (Diff mode). The PAC box splits into 旧 PAC(いまの版) (old, current) and 新 PAC(変更後) (new, changed). The new box starts with a copy of the old one
  2. Put the PAC in use now in the old box and the changed PAC in the new box (Open and drag and drop work for each)
  3. Both are evaluated against the same URLs. Only rows whose result changed are coloured and marked 変更 (Changed). The number of changes appears above the results, and 変わった行だけ shows only the changed rows

Differences in whitespace around ; in the return value don't count as changes. Errors and timeouts do. The CSV includes both old and new results.

Helper functions and their pitfalls

The tester provides the 14 standard functions available inside a PAC file.

All 14 functions and their pitfalls

Their behaviour follows the Firefox and Chromium implementations (both descend from Netscape's original code).

FunctionWhat it doesPitfalls
isPlainHostName(host)True if the host name has no dot (e.g. intranet)False for IPv6 addresses (containing :)
dnsDomainIs(host, domain)True if host ends with domainCase-sensitive. Without the leading dot, "example.com" also matches badexample.com
localHostOrDomainIs(host, hostdom)True if they are identical, or if a host with no domain matches the start of hostdomlocalHostOrDomainIs("www", "www.example.com") is true
isResolvable(host)True if the host resolves to an IP addressFalse for hosts not in the host-to-IP table
isInNet(host, pattern, mask)True if the IP address is in that networkA host name is resolved through the table first. The mask must be dotted ("255.255.0.0"); /16 does not work
dnsResolve(host)Returns the IP addressnull if it can't be resolved
convert_addr(ip)Converts an IP address to a 32-bit integerSigned, as in browsers (192.168.0.1 is negative)
myIpAddress()The client's own IP addressReturns the value from the settings
dnsDomainLevels(host)The number of dotswww.example.com gives 2
shExpMatch(str, pattern)Wildcard match* is zero or more characters, ? exactly one. True only if the whole string matches. Case-sensitive. Other characters are literal here, but some browsers treat [ ] or + as regular expression syntax, so avoid them
weekdayRange(wd1, wd2, "GMT")Day-of-week rangeThree upper-case English letters such as "MON". Can wrap around the week ("FRI", "MON"). A final "GMT" uses the UTC day
dateRange(…)Range of days, months and yearsIf the range ends with a month only, it runs to the last day of that month (browser implementations can be a few days off in months with fewer than 31 days)
timeRange(…)Time-of-day rangetimeRange(9, 17) means 9:00 to 17:59. Hours-only ranges do not wrap past midnight (timeRange(22, 6) is always false); timeRange(22, 0, 6, 0) does
alert(message)Outputs a messageShown on that URL's row in the results

You can't use eval or new Function inside the PAC (blocked for safety). Calling new Date() directly gives your computer's clock, not the date and time in the settings.

Common mistakes (what the checks find)

Full-width spaces, unbalanced brackets, a missing final return, broken shExpMatch patterns, shadowed rules and malformed return values. The checks are approximate; read them together with the results table.

Each mistake, with examples
  • Full-width spaces and punctuation: after typing comments in Japanese, Chinese or Korean, a full-width space or bracket can slip into the code. JavaScript accepts a full-width space as whitespace, so browsers won't complain. Inside comments these are fine, inside strings they are a warning, in code they are an error
  • Unbalanced brackets and quotes: mismatched { }, ( ), [ ] and unclosed quotes, with line numbers. Parser errors are also reported
  • Missing final return: a URL that matches none of the if statements reaches the end of the function. The result is undefined, which browsers handle differently. End with return "DIRECT"; or similar
  • Broken shExpMatch patterns: shExpMatch(host, ".example.com") (missing *, matches nothing), shExpMatch(host, "http://…") (host has no scheme), shExpMatch(url, "http://www.example.com") (missing the trailing / of the URL), patterns with capital letters and so on. All patterns are also listed
  • Shadowed rules: if shExpMatch(host, "*.example.com") returns first, a later shExpMatch(host, "www.example.com") can never be reached. For simple sequences of if (shExpMatch(…)) return …; (including ||, dnsDomainIs and host == "…"), the checks report when an earlier pattern covers all of a later one. Same return value: info; different: warning
  • Malformed return values: "PROXY proxy.example.net:8080, DIRECT" (the separator is ;), a bare "PROXY", a port out of range
  • Helper misuse: the isInNet mask format, weekdayRange("mon") (lower case), timeRange(22, 6) and so on

FAQ

Can the results differ from a real browser?
Yes. The tester does no DNS lookups: only hosts in the host-to-IP table resolve. Browsers and operating systems also differ slightly in how they run PAC files. Do the final check in the browser and OS you use.
How do isInNet and dnsResolve find IP addresses?
A web page cannot query DNS, so they use the host-to-IP table in the evaluation settings. Hosts not in the table cannot be resolved: dnsResolve returns null, and isResolvable and isInNet return false.
Are isInNetEx and the other Microsoft extensions, or IPv6, supported?
No. Calling isResolvableEx, dnsResolveEx, myIpAddressEx, isInNetEx, sortIpAddressList or the other extension functions raises an error. The host table and myIpAddress handle IPv4 addresses only.

Notes and data handling

Safety, licenses and the sample
  • No network access: everything, including the parser library (acorn), is in one file, and it never connects to a server. The page's Content-Security-Policy (connect-src 'none' and more) also blocks loading from and sending to other sites
  • Sandboxed execution: a PAC is a program, and one you received from someone else could contain harmful code. So the PAC doesn't run in the page. It runs in a Worker started inside an iframe with the sandbox attribute (a different origin from the page). It can't reach the page, its storage (localStorage and so on) or other tools on this site. The same network restrictions apply to the iframe and the Worker, so the PAC can't send data out
  • Stoppable: if one URL takes longer than 0.2 seconds, the Worker is terminated and recreated. An infinite loop won't freeze the page
  • Not saved by default: the PAC and test URLs are saved in the browser only if you tick the option to save them
  • No ads or analytics in pac-tester.html (ads appear only on this guide and the download page)

The tool's code is under the MIT License (GitHub). pac-tester.html embeds this library unchanged:

LibraryVersionLicenseUsed for
acorn8.18.0MITParsing the PAC for the checks (it builds a syntax tree only; it doesn't run the PAC)

The full license text is in THIRD_PARTY_LICENSES.txt and behind the ライセンス button in pac-tester.html.

Sample: the sample PAC is a generic example that uses only example domains (example.com, example.net, example.org, .example) and private or documentation IP addresses.

Feedback and bug reports (Google Forms): the form is in Japanese, but you can write in English.

The site-wide about page and disclaimer and privacy policy apply to all tools. The change log is in the Japanese guide.

Query Active Directory without RSAT from PowerShell, by the same author → ADSearch