wpad.dat generator: create the file for WPAD discovery
A wpad.dat is a PAC file under the name that automatic proxy discovery asks for. This page builds the file and explains where to put it, so that clients that look for a proxy on their own find it.
Create a wpad.dat in three steps
- List your proxies in the order clients should try them.
- List what goes direct: internal domains, single hosts and your own networks, each with a
comment after
#if you like. - Download wpad.dat and test it in the checker before you put it on the server.
The content is the same as in a proxy.pac. Only the name and the place where the file is served differ, and that is what the rest of this page is about.
#; it ends up next to the entry in the generated file, so the next person
knows why it is there. The file is built in your browser; nothing is sent anywhere until you open
it in the checker.Generated wpad.dat
[{"default":["proxy1.corp.example:8080 # primary, data centre 1","proxy2.corp.example:8080 # secondary, data centre 2"],"entry":"proxy","group":"Proxies","help":"One per line: [PROXY|HTTPS|SOCKS5] host:port, then an optional # comment. PROXY is the default type. Clients try the entries top to bottom and move on when a proxy does not answer.","id":"proxies","label":"Proxies, in failover order","max":10,"min":1,"placeholder":"proxy1.corp.example:8080 # primary","type":"entries"},{"default":"Default route: everything not matched above goes through the corporate proxies","group":"Proxies","help":"Written above the final return statement, the line that decides every request nothing else matched.","id":"proxies_note","label":"Block comment","max":5,"type":"comment"},{"default":false,"grade_note":"Lowers the grade unless \"Accept fail-open\" is ticked in the checker settings. A proxy.pac is for routing, not for security: with this option, clients bypass the proxy whenever it is down, so the firewall must decide whether that is allowed.","group":"Proxies","id":"direct_fallback","label":"Fall back to DIRECT when no proxy answers (fail-open)","rules":["direct-fallback-in-proxy-list"],"type":"checkbox"},{"default":[".corp.example # internal DNS zone and all its hosts","wiki.partner.example # partner wiki, reached over the site-to-site VPN"],"entry":"host","group":"Direct hosts and domains","help":"One per line. A name (wiki.partner.example) matches exactly that host; a name with a leading dot (.corp.example) matches the domain itself and every subdomain. No wildcards, no IP addresses (those go in the networks list).","id":"direct_hosts","label":"Hosts and domains that go direct","max":200,"placeholder":".corp.example # internal zone","type":"entries"},{"default":"Internal hosts and domains are reached without the proxy","group":"Direct hosts and domains","id":"direct_hosts_note","label":"Block comment","max":5,"type":"comment"},{"default":["198.51.100.0/24 # DMZ servers"],"entry":"network","group":"Direct networks","help":"IPv4 networks in CIDR notation, one per line (a bare address means /32). The network address must be aligned (10.20.0.0/16, not 10.20.1.0/16). They apply to IP-literal URLs only: the file never resolves a host name to compare it with a network, because that DNS lookup would block every request.","id":"direct_networks","label":"Networks that go direct","max":200,"placeholder":"10.20.0.0/16 # branch office","private_option":"private_literals","rules":["isinnet-on-hostname","dns-function-on-hot-path"],"type":"entries"},{"default":"Internal networks, matched for IP-address URLs only (no DNS lookup)","group":"Direct networks","id":"direct_networks_note","label":"Block comment","max":5,"type":"comment"},{"default":true,"group":"Options","help":"Host names are case-insensitive, string comparisons are not.","id":"lowercase","label":"Lower-case the host before comparing","rules":["host-not-lowercased"],"type":"checkbox"},{"default":true,"group":"Options","help":"Cheap and usually right inside a company network; a mistyped public name then fails locally instead of at the proxy.","id":"plain_hostnames","label":"Plain host names (no dot, such as http://intranet/) go direct","rules":["plain-hostname-blanket-direct"],"type":"checkbox"},{"default":true,"group":"Options","help":"10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8 and 169.254.0.0/16, for IP-literal URLs only.","id":"private_literals","label":"Private, loopback and link-local IP addresses go direct","type":"checkbox"},{"default":false,"group":"Bypass presets","help":"Identity-provider traffic that must not depend on proxy authentication (avoids sign-in loops).","id":"idp_entra","label":"Microsoft Entra ID sign-in (login.microsoftonline.com, aadcdn.msauth.net, aadcdn.msftauth.net)","type":"checkbox"},{"default":false,"group":"Bypass presets","id":"idp_okta","label":"Okta (okta.com, oktacdn.com and their subdomains)","type":"checkbox"},{"default":false,"group":"Bypass presets","id":"idp_google","label":"Google sign-in (accounts.google.com)","type":"checkbox"},{"default":[],"group":"File header","help":"Optional lines at the top of the file (owner, change reference). Plain ASCII, no personal data needed.","id":"file_comment","label":"File comment","max":10,"placeholder":"Owner: network team, change ticket NET-1234","type":"comment"}]// proxy.pac generated by the findproxyforurl.net PAC generator {{generator_version}} on {{generated_on}}
// Test changes at https://findproxyforurl.net/check/ before deploying them.
{{#each file_comment}}
// {{.|comment}}
{{/each}}
function FindProxyForURL(url, host) {
{{#if lowercase}}
// host names are case-insensitive, string comparisons are not
host = host.toLowerCase();
{{/if}}
{{#if plain_hostnames}}
// plain host names (no dot) stay on the local network
if (isPlainHostName(host)) {
return "DIRECT";
}
{{/if}}
{{#if direct_hosts}}
{{#each direct_hosts_note}}
// {{.|comment}}
{{/each}}
{{#if !direct_hosts_note}}
// hosts and domains that go direct
{{/if}}
if ({{#each direct_hosts sep="\n "}}{{#if .exact}}host == "{{.name}}"{{/if}}{{#if .domain}}{{#if .apex}}host == "{{.name}}" || {{/if}}dnsDomainIs(host, ".{{.name}}"){{/if}}{{#if !@last}} ||{{/if}}{{#if @last}}) {{{/if}}{{#if .comment}} // {{.comment|comment}}{{/if}}{{/each}}
return "DIRECT";
}
{{/if}}
{{#if idp_entra}}
// identity provider (Microsoft Entra ID) sign-in goes direct
if (host == "login.microsoftonline.com" || host == "aadcdn.msauth.net" || host == "aadcdn.msftauth.net") {
return "DIRECT";
}
{{/if}}
{{#if idp_okta}}
// identity provider (Okta) goes direct
if (host == "okta.com" || dnsDomainIs(host, ".okta.com") ||
host == "oktacdn.com" || dnsDomainIs(host, ".oktacdn.com")) {
return "DIRECT";
}
{{/if}}
{{#if idp_google}}
// identity provider (Google sign-in) goes direct
if (host == "accounts.google.com") {
return "DIRECT";
}
{{/if}}
{{#if private_literals || direct_networks}}
// IP-address URLs only: isInNet() on a host name would trigger a DNS lookup
if (/^\d+\.\d+\.\d+\.\d+$/.test(host)) {
{{#if private_literals}}
// private, loopback and link-local addresses (RFC 1918, RFC 1122, RFC 3927)
if (isInNet(host, "10.0.0.0", "255.0.0.0") ||
isInNet(host, "172.16.0.0", "255.240.0.0") ||
isInNet(host, "192.168.0.0", "255.255.0.0") ||
isInNet(host, "127.0.0.0", "255.0.0.0") ||
isInNet(host, "169.254.0.0", "255.255.0.0")) {
return "DIRECT";
}
{{#if direct_networks}}
{{/if}}
{{/if}}
{{#if direct_networks}}
{{#each direct_networks_note}}
// {{.|comment}}
{{/each}}
{{#if !direct_networks_note}}
// networks that go direct
{{/if}}
if ({{#each direct_networks sep="\n "}}isInNet(host, "{{.net}}", "{{.mask}}"){{#if !@last}} ||{{/if}}{{#if @last}}) {{{/if}} // {{.cidr}}{{#if .comment}} {{.comment|comment}}{{/if}}{{/each}}
return "DIRECT";
}
{{/if}}
}
{{/if}}
{{#each proxies_note}}
// {{.|comment}}
{{/each}}
{{#if !proxies_note}}
// default route: everything not matched above goes through the proxies
{{/if}}
// failover order:
{{#each proxies}}
// {{@number}}. {{.pac}}{{#if .comment}} {{.comment|comment}}{{/if}}
{{/each}}
{{#if direct_fallback}}
// then DIRECT: fail-open, clients bypass the proxies when none answers
{{/if}}
return "{{#each proxies sep="; "}}{{.pac}}{{/each}}{{#if direct_fallback}}; DIRECT{{/if}}";
}
Where clients look for wpad.dat
WPAD (Web Proxy Auto-Discovery) is the procedure behind the setting “Automatically detect settings”. It comes from an IETF draft that never became a standard, so clients implement it slightly differently, but the two ways of finding the file are the same everywhere:
- DHCP option 252. The client asks the DHCP server for option 252, which contains the full
URL of the file, for example
http://wpad.corp.example/wpad.dat. With DHCP the URL can point to any server and any name; usingwpad.datanyway keeps both ways consistent. - The DNS lookup for
wpad. Without an answer from DHCP, the client looks up a host calledwpadand fetcheshttp://wpad/wpad.dat. The operating system appends its DNS suffixes to that name. On Windows this can include parent domains (DNS devolution), for example fromeng.corp.exampletowpad.corp.example, and it applies to browsers too, because they use the Windows resolver. A name outside your organisation must never answer, which is why you should own awpadrecord in every internal DNS suffix. WPAD and wpad.dat shows which client does what, and Web proxy auto-detection explains the “Automatically detect settings” switch in Windows, macOS and the browsers.
Serve the file at the web root, over HTTP
For the DNS way, the file must be reachable as exactly http://wpad.<your domain>/wpad.dat:
- a DNS record
wpadin each internal DNS suffix, pointing at your web server, - the file in the web root of that server, named
wpad.datin lower case, - plain HTTP on port 80, because discovery does not use HTTPS,
- the content type
application/x-ns-proxy-autoconfigand a short cache lifetime such asCache-Control: max-age=3600.
Most web servers do not know the .dat extension. On Apache, set the type for this one file:
# Header needs mod_headers
<Files "wpad.dat">
ForceType application/x-ns-proxy-autoconfig
Header set Cache-Control "max-age=3600"
</Files>
On nginx, do the same in a location for the file:
location = /wpad.dat {
types { }
default_type application/x-ns-proxy-autoconfig;
add_header Cache-Control "max-age=3600";
}
On IIS, add a MIME type for .dat with the value application/x-ns-proxy-autoconfig; IIS does
not serve files whose extension has no MIME type.
Then test the delivery: paste the output of curl -sI http://wpad.corp.example/wpad.dat into the
checker under “Delivery” and choose “WPAD DNS discovery” or “DHCP option 252”.
Use discovery only where you cannot configure clients
Plain HTTP and unauthenticated DHCP mean that anyone who can answer first can hand out their own file and with it route all web traffic. On managed devices, set the file’s URL through group policy or MDM and serve it over HTTPS instead; the PAC file generator lists where that setting is on Windows, macOS and in the browsers. The WPAD page covers the risks and how to keep discovery safe, and wpad.dat vs proxy.pac compares the two ways of delivering the file.
Test the file before clients find it
Clients that use discovery pick up a new wpad.dat without anyone noticing, so a mistake reaches every one of them. Open the file in the checker first, and try it on a test client before you replace the file on the server. Ready-made files for common cases are on the PAC file examples page; any of them works as a wpad.dat.
Frequently asked questions
What is a wpad.dat file?
A PAC file, a small JavaScript file with a FindProxyForURL function, saved under the name wpad.dat. That is the name clients ask for when they look for a proxy configuration on their own through WPAD.
Where do I put the wpad.dat file?
In the web root of a server that answers as wpad.<your DNS suffix>, so that it is reachable as http://wpad.corp.example/wpad.dat. If you use DHCP option 252, the option contains the file's full URL instead.
Which MIME type does wpad.dat need?
application/x-ns-proxy-autoconfig. Web servers usually do not know the .dat extension, so set the type for the file explicitly; IIS does not serve the file at all until a MIME type for .dat exists.
Can wpad.dat be served over HTTPS?
Not for DNS discovery, which always asks for http://wpad.<suffix>/wpad.dat. A PAC file URL that you configure explicitly, for example by group policy, can and should use HTTPS.
Is wpad.dat the same as proxy.pac?
Yes, in content. You can serve the same file under both names, as wpad.dat for discovery and as proxy.pac for clients that have the URL configured.