Windows WinHTTP (system services, BITS)

Used by: Windows services, BITS, apps using WinHTTP.

Helper library

Emulated helper library (CC0-1.0).

Version ranges and quirks

Later ranges list only what changes compared with the range before.

Windows 11 WinHTTP (11-25H2)

Measured on Windows 11 25H2 in October 2026. Windows services, BITS and apps that use WinHTTP see these results. Test your file with this profile on /check/.

BehaviourValueSource
alert() outputignored
alert() exists and returns false, so calling it does not stop the script.
lab, verified 2026-10-11
Non-ASCII result rejectedfalse
Non-ASCII characters in the result are accepted.
lab, verified 2026-10-11
shExpMatch is case-sensitivetrue
shExpMatch compares case-sensitively and knows only * and ?. Characters such as [ ] + ( ) $ | are taken literally, so some patterns match differently from Chrome.
lab, verified 2026-10-11
dnsResolve is IPv4 onlytrue
dnsResolve returns only IPv4 addresses, and it returns false, not null, when a name does not resolve.
lab, verified 2026-10-11
JavaScript level accepted2017
About ES2017: let, const, arrow functions, classes, template strings and array spread work. Optional chaining (?.), ?? , object spread {...o}, BigInt and newer regular expression syntax are syntax errors, and then the whole file fails to load.
lab, verified 2026-10-11
Calls FindProxyForURLEx if definedtrue
If the file defines FindProxyForURLEx, Windows calls it instead of FindProxyForURL. A file with only FindProxyForURLEx works too.
lab, verified 2026-10-11
Microsoft *Ex functionstrue
dnsResolveEx, isInNetEx, isResolvableEx, sortIpAddressList and myIpAddressEx are available.
lab, verified 2026-10-11
Global variables persist between callstrue
Global variables keep their values from one call to the next.
lab, verified 2026-10-11
IPv6 host passed in bracketstrue
An IPv6 host reaches the script in brackets, for example [2001:db8::1].
lab, verified 2026-10-11
Host lower-cased by the enginefalse
The host keeps the case it had in the request, for example Example.COM, so a case-sensitive test such as dnsDomainIs can miss it.
lab, verified 2026-10-11
Largest PAC file accepted (bytes)1048576
A PAC file larger than about 1 MiB is rejected.
lab, verified 2026-10-11
Functions built into the engine (native)isPlainHostName, dnsDomainIs, localHostOrDomainIs, isResolvable, isInNet, dnsResolve, myIpAddress, dnsDomainLevels, shExpMatch, weekdayRange, dateRange, timeRange, alert, isResolvableEx, isInNetEx, dnsResolveEx, myIpAddressEx, sortIpAddressList, getClientVersion
All 19 PAC functions, including the Microsoft *Ex functions, are built into the engine. The checker imitates them from the measured results.
lab, verified 2026-10-11
On exceptionerror
If the script throws an error, the program that asked for a proxy gets an error instead of an answer. Browsers go DIRECT in this case.
lab, verified 2026-10-11
On non-string / undefined resultstringify
A result that is not a string is turned into text and read as a proxy list. undefined, null or a number give no usable entry, so the connection goes direct; an array such as ["PROXY a:1"] works.
lab, verified 2026-10-11
How the returned string is readwindows
Windows reads the returned string loosely. An entry that contains DIRECT anywhere becomes DIRECT, so a missing ';' before DIRECT sends traffic direct. Lower-case keywords are skipped, a missing port becomes 80, and SOCKS5 is misread. The checker shows the list Windows actually uses.
lab, verified 2026-10-11
Proxy keywords understoodPROXY, HTTPS, SOCKS, DIRECT
HTTP is not a keyword here. SOCKS5 and SOCKS4 are read as SOCKS followed by a broken host name.
lab, verified 2026-10-11
URL passed to FindProxyForURLhttps_to_origin
For https:// URLs the script sees only scheme, host and port, for example https://www.example.com:8443/. http:// URLs reach the script whole, with path, query and #fragment.
lab, verified 2026-10-11

Function availability

Derived from each engine's vendored helper library plus its native bindings (see engines).
Functionchromium
<=51
chromium
>=52
firefox
all
pacparser
<=1.4.6
pacparser
>=1.5.1
winhttp
11-25H2
wininet
11-25H2
reference
all
isPlainHostNameyesyesyesyesyesyesyesyes
dnsDomainIsyesyesyesyesyesyesyesyes
localHostOrDomainIsyesyesyesyesyesyesyesyes
isResolvableyesyesyesyesyesyesyesyes
isInNetyesyesyesyesyesyesyesyes
dnsResolveyesyesyesyesyesyesyesyes
myIpAddressyesyesyesyesyesyesyesyes
dnsDomainLevelsyesyesyesyesyesyesyesyes
shExpMatchyesyesyesyesyesyesyesyes
weekdayRangeyesyesyesyesyesyesyesyes
dateRangeyesyesyesyesyesyesyesyes
timeRangeyesyesyesyesyesyesyesyes
alertyesyesyesnoyesyesyesyes
dnsResolveExyesyesnoyesyesyesyesno
myIpAddressExyesyesnoyesyesyesyesno
isResolvableExyesyesnoyesyesyesyesno
isInNetExyesyesnoyesyesyesyesno
sortIpAddressListyesyesnononoyesyesno

Rules with notes for winhttp

  • PAC-C001Hostname pattern applied to url instead of host

    https URLs are cut to scheme://host:port/ (path, query and user name removed); http URLs are passed whole. Later requests to the same host and scheme with a different path or port could get an earlier, cached answer. lab, verified 2026-10-11

  • PAC-C018Upper-case letters in a hostname pattern

    host keeps its case (Example.COM arrives as Example.COM, also from BITS). dnsDomainIs and shExpMatch compare case-sensitively; localHostOrDomainIs ignores case. lab, verified 2026-10-11

  • PAC-C031IP address written with leading zeros, in hex, as one number or in short form

    Passes the host as written; reads leading zeros as octal in isInNet; dnsResolve returns address-like text unchanged; returns a proxy entry unchanged, and the Windows address lookup reads the forms like the browsers. lab, verified 2026-10-11

  • PAC-D006Large PAC served without compression

    A PAC sent gzip-compressed (Content-Encoding: gzip) failed to load. lab, verified 2026-10-11

  • PAC-D007PAC distributed via WPAD DNS discovery

    Without a suffix search list: wpad under the primary DNS suffix, then under the connection's own suffix, then wpad.local by multicast DNS, WPAD by NetBIOS and wpad by LLMNR. With a suffix search list: wpad under each listed suffix in order, and no multicast, NetBIOS or LLMNR queries. No DHCP packet was seen during these detection runs. lab, verified 2026-10-11

  • PAC-D009PAC loaded from a file path or SMB share

    A file:// PAC URL was rejected; no PAC was loaded. lab, verified 2026-10-11

  • PAC-D010PAC URL does not return 200

    Only status 200 is accepted; 203, 204, 404 and 500 all failed. A 302 redirect to the PAC was followed. A 401 answer (Basic or NTLM) failed. A server that took 29 seconds to answer still worked; one that took 40 seconds failed after about 30 seconds. lab, verified 2026-10-11

  • PAC-E001PAC file does not parse

    A file that does not compile gives the calling program an error instead of a proxy list; what happens next depends on the program. lab, verified 2026-10-11

  • PAC-E002No FindProxyForURL function

    A file whose function is spelled findProxyForURL fails with an error to the calling program. A file that defines only FindProxyForURLEx works. lab, verified 2026-10-11

  • PAC-E006Evaluation throws an exception

    An exception gives the calling program an error instead of a proxy list. .NET Framework and .NET 8 programs then connected directly without showing an error. lab, verified 2026-10-11

  • PAC-E007Evaluation did not finish within the time limit

    No time limit was observed: a script with an endless loop blocked the calling program for more than 18 minutes, and the script kept running after that program was ended. No memory limit was observed either: a script that kept allocating memory grew to 2.9 GiB. lab, verified 2026-10-11

  • PAC-E008Loop without a reachable exit

    An endless loop was not stopped: it blocked the calling program for more than 18 minutes and kept running after that program was ended. lab, verified 2026-10-11

  • PAC-E010isInNet called with an invalid address, mask or argument count

    Own implementation without a check of the mask; answers short masks, leading zeros and a missing mask differently from the browsers. lab, verified 2026-10-11

  • PAC-E011Return value is not a valid proxy string

    Lenient and different from Chromium: "PROXY a:3128 DIRECT" (no ';') and a tab between entries give DIRECT; lower-case "proxy" or "direct" is ignored; a ',' also separates entries; one empty entry ("PROXY ; PROXY b:1") removes the whole list; the keyword HTTP gives no entries; an unknown keyword is skipped; "PROXY DIRECTORY:80" is read as DIRECT; "PROXY http://a:8080" becomes the proxy "http" on port 80; an IPv6 proxy without brackets is cut at the first ':'. undefined, null and a number give no entries. lab, verified 2026-10-11

  • PAC-E012Proxy port out of range or not numeric

    The entry is kept with a different port: 99999 became 34463, -1 became 65535, 0 became 80 and "80abc" became 80. lab, verified 2026-10-11

  • PAC-E013File saved as UTF-16 instead of UTF-8 or ASCII

    A UTF-8 file with or without a byte order mark loads normally. A UTF-16 file and a gzip-compressed response fail to load; a Latin-1 file loads, but its non-ASCII characters are garbled. lab, verified 2026-10-11

  • PAC-E017PAC helper called with the wrong number of arguments

    isPlainHostName, isInNet and weekdayRange raised an error that ends the script when an argument was missing, extra or null, for example isPlainHostName(), isPlainHostName("a", "b"), isInNet with two or four arguments and weekdayRange(null). dateRange() and timeRange() without arguments returned false. lab, verified 2026-10-11

  • PAC-E018Browser or Node.js objects used in the PAC

    window and navigator are undefined; using them throws. lab, verified 2026-10-11

  • PAC-K001ES2015 to ES2017 syntax (let, const, arrow functions, template literals)

    About ES2017. let, const, arrow functions, classes, template strings, destructuring, array spread, async functions and generators work; optional chaining (?.), ??, object spread, BigInt literals, regular-expression lookbehind and named groups are syntax errors, and then the whole file fails to load. lab, verified 2026-10-11

  • PAC-K002alert() used in the PAC

    alert exists and returns false, with or without arguments; the script continues. lab, verified 2026-10-11

  • PAC-K003IPv6 extension functions (isInNetEx, dnsResolveEx, myIpAddressEx)

    All six are present (isResolvableEx, isInNetEx, dnsResolveEx, myIpAddressEx, sortIpAddressList, getClientVersion). dnsResolveEx lists IPv4 and IPv6 addresses separated by ';' with IPv6 in brackets, and returns false for a name that does not resolve; isInNetEx needs a prefix such as /8, does not look up host names and is false for /0; getClientVersion returns "1.0". lab, verified 2026-10-11

  • PAC-K004FindProxyForURLEx entry point

    When both functions are defined, FindProxyForURLEx decides; a file that defines only FindProxyForURLEx works. lab, verified 2026-10-11

  • PAC-K005SOCKS keywords mean different versions on different engines

    "SOCKS s:1080" is returned as a SOCKS entry; a missing port becomes 1080. "SOCKS5 s:1080" and "SOCKS4 s:1080" are misread as a plain SOCKS entry with the broken host name "5 s" or "4 s". .NET Framework and .NET 8 programs went direct instead of using a SOCKS entry. lab, verified 2026-10-11

  • PAC-K006HTTPS proxy keyword without a PROXY fallback

    The HTTPS entry is returned to the program unchanged. A .NET Framework program turned it into a broken proxy address and the request failed; a .NET 8 program skipped it for http requests and used no proxy. lab, verified 2026-10-11

  • PAC-K007Time functions that answer differently per engine (weekdayRange, dateRange, timeRange)

    dateRange and timeRange always return false, whatever the arguments. weekdayRange works with upper-case day names and wraps (FRI to MON); lower-case names raise an error or give false. lab, verified 2026-10-11

  • PAC-K008Mutable state outside FindProxyForURL

    Top-level variables keep their values between calls; a counter increased by FindProxyForURL gave a different answer on the second call. lab, verified 2026-10-11

  • PAC-K009Case-sensitive host comparisons without lower-casing host

    The host is passed with the case the program used (Example.COM stays Example.COM); BITS showed the same. An IPv6 host arrives in brackets with its case kept. lab, verified 2026-10-11

  • PAC-K010ES2015+ library methods (startsWith, flat, replaceAll, globalThis)

    Present: Array includes, String padStart, Object.entries, Map, Set, Promise, Symbol, Proxy, Reflect. Missing (undefined, so a call throws): Array flat, Object.fromEntries, String replaceAll, Array at, globalThis. lab, verified 2026-10-11

  • PAC-K013Routing decided by myIpAddress()

    myIpAddress returned the machine's IPv4 address, and myIpAddressEx a list of a link-local IPv6 address in brackets followed by the IPv4 address. How Windows chooses among several adapters was not measured. lab, verified 2026-10-11

  • PAC-K015Regular-expression syntax inside a shExpMatch pattern

    Only * and ? are wildcards; [ ] + ( ) | { } $ are matched literally, so regex alternation never matches. A ^ in the pattern changes the match (shExpMatch("x^", "x^") is false). Matching is case-sensitive. lab, verified 2026-10-11

  • PAC-K020JavaScript syntax newer than ES2017 (?., ??, object spread)

    Optional chaining (?.), ??, object spread, BigInt literals, regular-expression lookbehind and named groups are syntax errors, and then the whole file fails to load. ES2015 to ES2017 syntax (let, const, arrow functions, classes, template strings, array spread, async functions, generators, **) works. lab, verified 2026-10-11

  • PAC-K021Decision depends on the URL path or query

    https URLs reach the script as https://host:port/. http URLs reach it whole, but later requests to the same host and scheme, also with another path or port, got an answer that the script had given for an earlier request. lab, verified 2026-10-11

  • PAC-K022console used in the PAC

    console is undefined; a call throws and the request is handled as a script failure. lab, verified 2026-10-11

  • PAC-P006PAC file is large

    A PAC body of 1,048,576 bytes (1 MiB) loads; one byte more and the download fails, so the file is not used. lab, verified 2026-10-11

  • PAC-X001No unconditional return at the end of FindProxyForURL

    undefined, null or a number as the result gives an empty list, so the program uses no proxy. lab, verified 2026-10-11

  • PAC-X013PROXY entry without a port

    A missing port becomes 80; the entry is kept, not rejected. lab, verified 2026-10-11

  • PAC-X014DIRECT as fallback after a proxy

    Windows returns the whole list, DIRECT included. Older Windows programs (.NET Framework, .NET 8) get only the entries before the first DIRECT: .NET Framework programs then added a DIRECT of their own after the last proxy, even where the PAC returned no DIRECT, while .NET 8 programs did not fall back to DIRECT at all. lab, verified 2026-10-11