Understanding Proxy Auto-Configuration (PAC) Files

When working with network routing and proxy configurations, Proxy Auto-Configuration (PAC) files provide a powerful mechanism for dynamically directing traffic. A PAC file is essentially a JavaScript-based script that determines how web requests should be handled—whether they should go directly to their destination or be routed through a proxy server.

The core of a PAC file is the FindProxyForURL function, which receives two parameters: the target URL and the hostname. Based on this information, the function returns routing instructions.

function FindProxyForURL(url, host) {
    return "DIRECT";
}

This minimal example demonstrates a PAC file that routes all traffic directly without any proxy involvement.

Return Values and Routing Logic

The function can return three distinct directives: "DIRECT" for direct connections, "PROXY host:port" for HTTP proxy routing, and "SOCKS host:port" for SOCKS protocol routing. Multiple fallback options can be chained together:

return "PROXY 192.168.1.100:3128; SOCKS 192.168.1.100:1080; DIRECT";

This configuration attempts the primary proxy first, falls back to the SOCKS server if the primary fails, and defaults to a direct connection if both proxies are unavailable.

Built-in PAC Functions

PAC specifications include several utility functions for sophisticated routing decisions.

The dnsDomainIs function performs case-insensitive domain matching:

if (dnsDomainIs(host, "example.org") || 
    dnsDomainIs(host, "www.example.org")) {
    return "DIRECT";
}

The shExpMatch function provides shell-style pattern matching with wildcard support:

if (shExpMatch(host, "secure.gateway.net") ||
    shExpMatch(url, "https://api.service.com/v1/*")) {
    return "DIRECT"; 
}

The isInNet function checks whether an IP address falls within a specified subnet:

if (isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0")) {
    return "DIRECT";
}

For obtaining the local machine's IP address, use myIpAddress:

if (isInNet(myIpAddress(), "192.168.0.0", "255.255.0.0")) {
    return "PROXY 10.0.0.1:8080";
}

DNS resolution is handled through dnsResolve:

if (isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0") ||
    isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0")) {
    return "DIRECT";
}

The isPlainHostName function identifies hosts without domain components:

if (isPlainHostName(host)) {
    return "DIRECT";
}

Use isResolvable to check host accessibility:

if (isResolvable(host)) {
    return "PROXY gateway.example.com:8080";
}

The dnsDomainLevels function counts domain depth:

if (dnsDomainLevels(host) > 0) {
    return "PROXY gateway.example.com:8080";
} else {
    return "DIRECT";
}

Time-based routing is supported through weekdayRange, dateRange, and timeRange:

if (weekdayRange("MON", "FRI")) {
    return "PROXY gateway.example.com:8080";
}

if (dateRange("JAN", "MAY")) {
    return "PROXY gateway.example.com:8080"; 
}

if (timeRange(8, 18)) {
    return "PROXY gateway.example.com:8080";
}

Configuration and Deployment

On Windows systems, PAC files are configured through Internet Options under Connections tab and LAN settings. The script URI can reference local files using the file:/// protocol or remote servers via http:// or https://.

In Chrome, access these settings via chrome://settings/ under Advanced settings and proxy configuration options.

Important Considerations

When serving PAC files, ensure the Content-Type header is set to application/x-ns-proxy-autoconfig. Most browsers will still recognize the file without this header, but compliance ensures proper handling.

Host parameters in comparison functions are handled case-insensitively by the PAC engine, eliminating the need for manual case normalization.

The underlying DNS resolution layer automatically caches query results, so implementing application-level caching for dnsResolve results is unnecessary and redundant.

Tags: Proxy networking PAC javascript network-configuration

Posted on Wed, 19 Aug 2026 16:48:19 +0000 by Erkilite